I'm reading this tutorial on how to safely exit from threads.
In essence, it passes a future object to the function that is going to be executed from the thread, and checks, at every while loop, if that future already has a value (if it has, it exits the thread). See:
void threadFunction(std::future<void> futureObj)
{
std::cout << "Thread Start" << std::endl;
while (futureObj.wait_for(std::chrono::milliseconds(1)) == std::future_status::timeout)
{
std::cout << "Doing Some Work" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
std::cout << "Thread End" << std::endl;
}
The problem is that in order to check if futureObj is already setted, it has to wait for some time (here, 1 millissecond). So, I'm losing 1 millissecond on every iteration of the thread. Shouldn't this be preferable:
void threadFunction(bool *shouldStop)
{
std::cout << "Thread Start" << std::endl;
while (!*shouldStop)
{
std::cout << "Doing Some Work" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
std::cout << "Thread End" << std::endl;
}
In order to check shouldStop, no time is wasted. So my thread runs faster. Why he didn't do that?
UPDATE:
Here's a simple class that should do the same thing, I guess.
class Stoppable
{
private:
std::atomic<bool> _shouldContinue;
public:
Stoppable()
{
_shouldContinue.store(true);
}
virtual void run() = 0;
void operator()()
{
run();
}
bool shouldContinue()
{
return _shouldContinue.load();
}
void stop()
{
_shouldContinue.store(false);
}
};
Then, to use it, just subclass Stoppable and do like this:
void MySubClass::run()
{
while (shouldContinue())
{
//...
}
}
The second proposal:
void threadFunction(bool *shouldStop)
Is I am afraid wrong if you intend to set *shouldStop from another thread.
In this case it should be void threadFunction(std::atomic<bool> *shouldStop).
There is no one "right way" to signal a thread to stop as it will depend on whether you want your thread to work continually or only work when there is work to do. But there are wrong ways - usually involving undefined behaviour because of writing to a non-atomic variable in one thread and reading from it in another.
If you want your thread to continually work until stopped (for example, this is common in graphics rendering threads or real-time game logic threads) then there is no reason to wait before checking your stop signal.
If your thread is a worker thread which will only run while there is work to do, then it's more normal to use a std::condition_variable, std::mutex and a queue plus a signal.
In case it's interesting, here's an example of an implementation of a work queue. Note that this one permits completion of the work out of order with respect to submission. There are many strategies available:
#include <condition_variable>
#include <mutex>
#include <queue>
#include <functional>
#include <thread>
#include <vector>
#include <iostream>
#include <iomanip>
struct worker_control
{
std::queue<std::function<void()>> work_queue;
std::mutex m;
std::condition_variable cv;
bool stop_signal = false;
void post_work(std::function<void()> f)
{
auto lock = std::unique_lock(m);
work_queue.push(std::move(f));
lock.unlock();
cv.notify_one();
}
void request_stop()
{
auto lock = std::unique_lock(m);
stop_signal = true;
lock.unlock();
cv.notify_all();
}
};
std::mutex emit_mutex;
template<class...Args>
void emit(Args&&...args)
{
auto lock = std::unique_lock(emit_mutex);
std::cout << std::this_thread::get_id() << " : ";
((std::cout << args), ...);
std::cout << '\n';
}
void run_worker(worker_control& control)
{
auto should_run = [&]
{
return not control.work_queue.empty() or control.stop_signal;
};
while (1)
{
auto lock = std::unique_lock(control.m);
control.cv.wait(lock, should_run);
// at this point we own the lock on control.m
if (not control.work_queue.empty())
{
auto work = std::move(control.work_queue.front());
control.work_queue.pop();
lock.unlock(); // allow other workers access to the queue
work();
}
else
{
// we can only have got here if there is no work to do and we have been asked to stop
return;
}
}
}
int main()
{
std::vector<std::thread> worker_threads;
auto control = worker_control();
worker_threads.emplace_back([&]{ run_worker(control); });
worker_threads.emplace_back([&]{ run_worker(control); });
worker_threads.emplace_back([&]{ run_worker(control); });
control.post_work([]{ emit("the"); });
control.post_work([]{ emit("quick"); });
control.post_work([]{ emit("brown"); });
control.post_work([]{ emit("fox"); });
control.post_work([]{ emit("jumps"); });
control.post_work([]{ emit("over"); });
control.post_work([]{ emit("the"); });
control.post_work([]{ emit("lazy"); });
control.post_work([]{ emit("dog"); });
control.request_stop();
for (auto& t : worker_threads)
if (t.joinable())
t.join();
}
Example output:
140244960823040 : the
140244960823040 : fox
140244960823040 : jumps
140244960823040 : over
140244960823040 : the
140244960823040 : lazy
140244960823040 : dog
140244969215744 : quick
140244952430336 : brown
https://coliru.stacked-crooked.com/a/c1612695a3cfc955
Related
Consider this simple synchronization problem. I have two threads, A and B, that each execute 2 steps. I want step 1a to be performed before step 2b.
Thread A
Thread B
Step 1a
Step 1b
Step 2a
Step 2b
I have some options for how to implement this.
std::condition_variable + std::mutex + bool
This is the solution proposed by this stack overflow answer and this leetcode discussion page.
Thread B will wait on the condition variable, and Thread A will notify the condition variable. The mutex is required because it is the argument of the condition_variable's wait.
#include <iostream>
#include <thread>
#include <condition_variable>
std::condition_variable step_1a;
std::mutex a_mutex_I_guess;
bool step_1a_done = false;
void Step_1a() {
std::cout << "step 1a" << "\n";
}
void Step_2a() {
std::cout << "step 2a" << "\n";
}
void Step_1b() {
std::cout << "step 1b" << "\n";
}
void Step_2b() {
std::cout << "step 2b" << "\n";
}
void A() {
//std::unique_lock<std::mutex> lck{ a_mutex_I_guess }; unnecessary
Step_1a();
step_1a_done = true;
//lck.unlock(); unnecessary
step_1a.notify_one();
Step_2a();
}
void B() {
Step_1b();
std::unique_lock<std::mutex> lck{ a_mutex_I_guess };
step_1a.wait(lck, []() { return step_1a_done; });
Step_2b();
}
int main() {
std::thread thread_A{ A };
std::thread thread_B{ B };
thread_A.join();
thread_B.join();
}
To me, this seems like overkill. std::condition_variables are designed to handle multiple waiting threads. std::mutex is intended to protect shared data, not to be fodder for wait. On top of all of that, I needed bool step_1a_done to actually keep track of whether or not step_1a had completed.
As a measure of their complexity, the mutex, condition_variable, and bool together require 153 (80 + 72 + 1) bytes of memory on my machine.
std::binary_semaphore
Alternatively, I can use a binary semaphore. Semantically, the binary semaphore isn't meant for one-time-use. However, it gets the job done with simpler tools than the previous option.
#include <iostream>
#include <thread>
#include <semaphore>
std::binary_semaphore step_1a_sem{ 0 };
void Step_1a() {
std::cout << "step 1a" << "\n";
}
void Step_2a() {
std::cout << "step 2a" << "\n";
}
void Step_1b() {
std::cout << "step 1b" << "\n";
}
void Step_2b() {
std::cout << "step 2b" << "\n";
}
void A() {
//std::unique_lock<std::mutex> lck{ a_mutex_I_guess }; unnecessary
Step_1a();
step_1a_sem.release();
Step_2a();
}
void B() {
Step_1b();
step_1a_sem.acquire();
Step_2b();
}
int main() {
std::thread thread_A{ A };
std::thread thread_B{ B };
thread_A.join();
thread_B.join();
}
step_1a_sem requires only 1 byte of memory.
Question
My assessment is that binary_semaphore is better. However, even better would be a "one_time_semaphore" that documents (or enforces) in my code that release should only be called once. Are there C++ concurrency primitives that are a better fit for this thread synchronization problem?
EDIT: std::promise<void>
#Daniel Langr has pointed out that std::promise<void> also works. While this seems like the exact use case of std::promise<void>, things appear significantly more complicated under the hood than with a binary_semaphore. The memory requirement is 24 bytes.
#include <iostream>
#include <thread>
#include <future>
std::promise<void> step_1a_done;
void Step_1a() {
std::cout << "step 1a" << "\n";
}
void Step_2a() {
std::cout << "step 2a" << "\n";
}
void Step_1b() {
std::cout << "step 1b" << "\n";
}
void Step_2b() {
std::cout << "step 2b" << "\n";
}
void A() {
Step_1a();
step_1a_done.set_value();
Step_2a();
}
void B() {
Step_1b();
step_1a_done.get_future().wait();
Step_2b();
}
int main() {
std::thread thread_A{ A };
std::thread thread_B{ B };
thread_A.join();
thread_B.join();
}
I am trying to create a sort of threadpool that runs functions on separate threads and only starts a new iteration when all functions have finished.
map<size_t, bool> status_map;
vector<thread> threads;
condition_variable cond;
bool are_all_ready() {
mutex m;
unique_lock<mutex> lock(m);
for (const auto& [_, status] : status_map) {
if (!status) {
return false;
}
}
return true;
}
void do_little_work(size_t id) {
this_thread::sleep_for(chrono::seconds(1));
cout << id << " did little work..." << endl;
}
void do_some_work(size_t id) {
this_thread::sleep_for(chrono::seconds(2));
cout << id << " did some work..." << endl;
}
void do_much_work(size_t id) {
this_thread::sleep_for(chrono::seconds(4));
cout << id << " did much work..." << endl;
}
void run(const function<void(size_t)>& function, size_t id) {
while (true) {
mutex m;
unique_lock<mutex> lock(m);
cond.wait(lock, are_all_ready);
status_map[id] = false;
cond.notify_all();
function(id);
status_map[id] = true;
cond.notify_all();
}
}
int main() {
threads.push_back(thread(run, do_little_work, 0));
threads.push_back(thread(run, do_some_work, 1));
threads.push_back(thread(run, do_much_work, 2));
for (auto& thread : threads) {
thread.join();
}
return EXIT_SUCCESS;
}
I expect to get the output:
0 did little work...
1 did some work...
2 did much work...
0 did little work...
1 did some work...
2 did much work...
.
.
.
after the respective timeouts but when I run the program I only get
0 did little work...
0 did little work...
.
.
.
I also have to say that Im rather new to multithreading but in my understanding, the condition_variable should to the taks of blocking every thread till the predicate returns true. And in my case are_all_ready should return true after all functions have returned.
There are several ways to do this.
Easiest in my opinion would be a C++20 std::barrier, which says, "wait until all of N threads have arrived and are waiting here."
#include <barrier>
std::barrier synch_workers(3);
....
void run(const std::function<void(size_t)>& func, size_t id) {
while (true) {
synch_workers.arrive_and_wait(); // wait for all three to be ready
func(id);
}
}
Cruder and less efficient, but equally effective, would be to construct and join() new sets of three worker threads for each "batch" of work:
int main(...) {
std::vector<thread> threads;
...
while (flag_running) {
threads.push_back(...);
threads.push_back(...);
...
for (auto& thread : threads) {
thread.join();
}
threads.clear();
}
Aside
I'd suggest you revisit some core synchronization concepts, however. You are using new mutexes when you want to re-use a shared one. The scope of your unique_lock isn't quite right.
Now, your idea to track worker thread "busy/idle" state in a map is straightforward, but cannot correctly coordinate "batches" or "rounds" of work that must be begun at the same time.
If a worker sees in the map that two of three threads, including itself, are "idle", what does that mean? Is a "batch" of work concluding — i.e., two workers are waiting for a tardy third? Or has a batch just begun — i.e., the two idle threads are tardy and had better get to work like their more eager peer?
The threads cannot know the answer without keeping track of the current batch of work, which is what a barrier (or its more complex cousin the phaser) does under the hood.
As-is, your program has a crash (UB) due to concurrent access to status_map.
When you do:
void run(const function<void(size_t)>& function, size_t id)
{
...
mutex m;
unique_lock<mutex> lock(m);
...
status_map[id] = false;
the locks created are local variables, one per thread, and as such independent. So, it doesn't prevent multiple threads from writing to status_map at once, and thus crashing. That's what I get on my machine.
Now, if you make the mutex static, only one thread can access the map at once. But that also makes it so that only one thread runs at once. With this I see 0, 1 and 2 running, but only once at a time and a strong tendency for the previous thread to have run to run again.
My suggestion, go back to the drawing board and make it simpler. All threads run at once, single mutex to protect the map, only lock the mutex to access the map, and ... well, in fact, I don't even see the need for a condition variable.
e.g. what is wrong with:
#include <thread>
#include <iostream>
#include <vector>
using namespace std;
vector<thread> threads;
void do_little_work(size_t id) {
this_thread::sleep_for(chrono::seconds(1));
cout << id << " did little work..." << endl;
}
void do_some_work(size_t id) {
this_thread::sleep_for(chrono::seconds(2));
cout << id << " did some work..." << endl;
}
void do_much_work(size_t id) {
this_thread::sleep_for(chrono::seconds(4));
cout << id << " did much work..." << endl;
}
void run(const function<void(size_t)>& function, size_t id) {
while (true) {
function(id);
}
}
int main() {
threads.push_back(thread(run, do_little_work, 0));
threads.push_back(thread(run, do_some_work, 1));
threads.push_back(thread(run, do_much_work, 2));
for (auto& thread : threads) {
thread.join();
}
return EXIT_SUCCESS;
}
So you can create a std::future that does no work until .get() is called:
auto f_deferred = std::async( std::launch::deferred, []{ std::cout << "I ran\n"; } );
You can also write a std::future that is waitable, and can be made ready at any point by code in any thread:
std::packaged_task<void()> p( []( std::cout << "I also ran\n"; } );
auto f_waitable = p.get_future();
If you call f_deferred.wait_for(1ms), it won't bother waiting. If you call f_deferred.get(), a lambda of your choice (in this case, one that prints "I ran\n" executes.
If you call f_waitable.get(), there is no way for code managing the tasks to be aware that someone is waiting on the future. But if you call f_deferred.wait(1ms);, you simply get future_status::deferred immediately.
Is there any way I can combine these two?
A concrete use case is a thread pool returning futures when people queue tasks. If an unqueued future is .get()'d, I want to use the thread that is blocked to execute the task rather than having it idle. On the other hand, I want people with the returned futures to be able to determine if the task is finished, and even wait a bounded amount of time for the task to be finished. (in the case where you are waiting, I'm ok with your thread being idle during your wait)
Failing that, are there solutions in upcoming proposals that would solve this problem better than having my thread pool return a future with all of its limitations? I've heard that there is no future in futures and better solutions exist to the problem futures solve.
I am not sure if this is exactly what you need, but it serves the purpose of illustrating what I suggested in the comment. At the very least, I hope it gives you some ideas to implement what you need if it doesn't cover all your needs.
Disclaimer: This is very crude. A lot of things could certainly be done more elegantly and efficiently.
#include <iostream>
#include <thread>
#include <future>
#include <memory>
#include <functional>
#include <queue>
#include <random>
#include <chrono>
#include <mutex>
typedef std::packaged_task<void()> task;
typedef std::shared_ptr<task> task_ptr;
typedef std::lock_guard<std::mutex> glock;
typedef std::unique_lock<std::mutex> ulock;
typedef unsigned int uint;
typedef unsigned long ulong;
// For sync'd std::cout
std::mutex cout_mtx;
// For task scheduling
std::mutex task_mtx;
std::condition_variable task_cv;
// Prevents main() from exiting
// before the last worker exits
std::condition_variable kill_switch;
// RNG engine
std::mt19937_64 engine;
// Random sleep (in ms)
std::uniform_int_distribution<int> sleep(100, 10000);
// Task queue
std::queue<task_ptr> task_queue;
static uint tasks = 0;
static std::thread::id main_thread_id;
static uint workers = 0;
template<typename T>
class Task
{
// Not sure if this needs
// to be std::atomic.
// A simple bool might suffice.
std::atomic<bool> working;
task_ptr tp;
public:
Task(task_ptr _tp)
:
working(false),
tp(_tp)
{}
inline T get()
{
working.store(true);
(*tp)();
return tp->get_future().get();
}
inline bool is_working()
{
return working.load();
}
};
auto task_factory()
{
return std::make_shared<task>([&]
{
uint task_id(0);
{
glock lk(cout_mtx);
task_id = ++tasks;
if (std::this_thread::get_id() == main_thread_id)
{
std::cout << "Executing task " << task_id << " in main thread.\n";
}
else
{
std::cout << "Executing task " << task_id << " in worker " << std::this_thread::get_id() << ".\n";
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(sleep(engine)));
{
glock lk(cout_mtx);
std::cout << "\tTask " << task_id << " completed.\n";
}
});
}
auto func_factory()
{
return [&]
{
while(true)
{
ulock lk(task_mtx);
task_cv.wait(lk, [&]{ return !task_queue.empty(); });
Task<void> task(task_queue.front());
task_queue.pop();
// Check if the task has been assigned
if (!task.is_working())
{
// Sleep for a while and check again.
// If it is still not assigned after 1 s,
// start working on it.
// You can also place these checks
// directly in Task::get()
{
glock lk(cout_mtx);
std::cout << "\tTask not started, waiting 1 s...\n";
}
lk.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
lk.lock();
if (!task.is_working())
{
{
glock lk(cout_mtx);
std::cout << "\tTask not started after 1 s, commencing work...\n";
}
lk.unlock();
task.get();
lk.lock();
}
if (task_queue.empty())
{
break;
}
}
}
};
}
int main()
{
engine.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
std::cout << "Main thread: " << std::this_thread::get_id() << "\n";
main_thread_id = std::this_thread::get_id();
for (int i = 0; i < 50; ++i)
{
task_queue.push(task_factory());
}
std::cout << "Tasks enqueued: " << task_queue.size() << "\n";
// Spawn 5 workers
for (int i = 0; i < 5; ++i)
{
std::thread([&]
{
{
ulock lk(task_mtx);
++workers;
task_cv.wait(lk);
{
glock lk(cout_mtx);
std::cout << "\tWorker started\n";
}
}
auto fn(func_factory());
fn();
ulock lk(task_mtx);
--workers;
if (workers == 0)
{
kill_switch.notify_all();
}
}).detach();
}
// Notify all workers to start processing the queue
task_cv.notify_all();
// This is the important bit:
// Tasks can be executed by the main thread
// as well as by the workers.
// In fact, any thread can grab a task from the queue,
// check if it is running and start working
// on it if it is not.
auto fn(func_factory());
fn();
ulock lk(task_mtx);
if (workers > 0)
{
kill_switch.wait(lk);
}
return 0;
}
This is my CMakeLists.txt
cmake_minimum_required(VERSION 3.2)
project(tp_wait)
set(CMAKE_CXX_COMPILER "clang++")
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build type" FORCE)
find_package(Threads REQUIRED)
add_executable(${PROJECT_NAME} "main.cpp")
target_link_libraries(${PROJECT_NAME} ${CMAKE_THREAD_LIBS_INIT})
I need to check whether a file is locked using boost::interprocess::file_lock. I produced this, but I'm worried what it's gonna do:
bool DataCache::isLocked() const {
bool res = lock_->try_lock();
if(res)
lock_->unlock();
return res;
}
Is it a good idea? Isn't there a way to check it without locking it?
While the other answer is the key to not introducing a race condition, there is no reason to drop exception safety and error-resilience that comes from using the proper RAII wrappers like std::lock_guard<> and std::unique_lock<>.
You'd want to write:
if (auto lk = try_to_lock(mx)) {
std::cout << "simple test\n";
} // automatically unlocks at scope exit
And you can. Here's my simple implementation:
template <typename Lockable>
std::unique_lock<Lockable> try_to_lock(Lockable& lockable) {
return std::unique_lock<Lockable> (lockable, std::try_to_lock);
}
Live On Coliru
#include <mutex>
#include <iostream>
int main() {
// demo
std::mutex mx;
if (auto lk = try_to_lock(mx)) {
std::cout << "simple test\n";
} // automatically unlocks at scope exit
if (auto lk = try_to_lock(mx)) {
std::cout << "yes\n";
if (auto lk = try_to_lock(mx)) {
std::cout << "oops?!\n"; // not reached
} else {
std::cout << "no recursive lock\n";
}
// but you can manipulate the lock if you insist:
lk.unlock();
if (auto lk = try_to_lock(mx)) {
std::cout << "now we can lock again\n";
} else {
std::cout << "oops?!\n"; // not reached
}
}
}
Prints:
simple test
yes
no recursive lock
now we can lock again
As this doesn't fit in a comment: You could create "interface functions" for tryLock and unlock externally.
e.g.:
bool DataCache::try_lock() const {
return lock_->try_lock();
}
void DataCache::unlock() const {
lock_->unlock();
}
Usage:
DataCache cache;
if(cache.try_lock())
{
cache.doSomething();
cache.unlock();
}
else
{
//....
}
I'm not sure if the const will work here. I just copied it from the question code.
C++, XCode 4.6.3, OSX 10.8.2, deploying on iOS
I am trying to create a timed event.
My thought process was to create a thread, do the timing in it and then at the end have it call another function. This is working however it is pausing the rest of the program.
//Launch a thread
std::thread t1(start_thread);
//Join the thread with the main thread
t1.join();
void start_thread()
{
std::cout << "thread started" << std::endl;
auto start = std::chrono::high_resolution_clock::now();
std::this_thread::sleep_until(start + std::chrono::seconds(20));
stop_thread();
}
void stop_thread()
{
std::cout << "thread stopped." << std::endl;
}
Is there a way to do this that doesn't pause program execution?
Update:
I could declare the thread in the header file and join in the stop_thread():
void stop_thread()
{
std::cout << "thread stopped." << std::endl;
ti.join();
}
but that throws:
Type 'std::thread' does not provide a call operator
UPDATE 2: Calling t1.detach() instead of join seems to work.
You're right it works:
Here is an example coming from cpp reference
http://en.cppreference.com/w/cpp/thread/thread/detach
#include <iostream>
#include <chrono>
#include <thread>
void independentThread()
{
std::cout << "Starting concurrent thread.\n";
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "Exiting concurrent thread.\n";
}
void threadCaller()
{
std::cout << "Starting thread caller.\n";
std::thread t(independentThread);
t.detach();
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Exiting thread caller.\n";
}
int main()
{
threadCaller();
std::this_thread::sleep_for(std::chrono::seconds(5));
}
Output:
Starting thread caller.
Starting concurrent thread.
Exiting thread caller.
Exiting concurrent thread.
We see that the concurrent thread ends after the thread caller ends. This is not possible if detach is not called.
Hope that helps, but Jason found the solution.
Use a class instead.
enum{ PAUSED, STARTED, STOPPED };
class AsyncEvent
{
protected:
unsigned char mState;
public:
AsyncEvent():mState(PAUSED){ mThread = std::thread(&AsyncEvent::run,this); }
~AsyncEvent(){ mThread.join(); }
private:
std::thread mThread;
void run()
{
std::cout << "thread started" << std::endl;
while(mState != STOPPED)
{
if(mState == PAUSED)break;
auto start = std::chrono::high_resolution_clock::now();
std::this_thread::sleep_until(start + std::chrono::seconds(20));
}
}
void stop()
{
mState = STOPPED;
}
void pause()
{
mState = PAUSED;
}
};