I am starting a std::async from within a lambda function.
Even with the policy std::launch::async, the task is running synchronously on the same thread and therefore blocking it.
Is this normal or am I missing something?
int main()
{
auto lambda = [&]
{
auto future = std::async(std::launch::async, [&]
{
using namespace std::chrono_literals;
const auto delay = 5000ms;
std::this_thread::sleep_for(delay);
std::cout << "Done okay byeeeeeeee \n";
});
};
lambda();
for (long long i = 0 ; i < 10 ; ++i)
{
std::cout << "Doing stuff in main thread" << std::endl;
}
}
The problem is the future variable, or rather the destruction of it.
The destructor can block until the async is finished.
I had a comparable problem last and didn't solve it with std::async but with std::thread.
void get_sleep()
{
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "Done okay byeeeeeeee \n";
}
int main()
{
std::thread t(get_sleep);
t.detach();
for (int i = 0 ; i < 10 ; ++i)
{
std::cout << "Doing stuff in main thread" << std::endl;
}
return 0;
}
Expanding upon Some programmer dude's answer
Consider the following class→ I created this to see when the Destructor gets called.
struct MyStruct {
~MyStruct() {printf("DTOR\r\n");}
};
Here is your code, I have heavily commented the code, so let the code do the talking
int main(){
//1 You are on main thread, create lambda on main thread
auto lambda = [&]{
//3 lambda is being started to execute
MyStruct myStruct{}; //4 This I added
//4 std::async enqueues the inner lambda, which will run and return in the future
auto future = std::async(std::launch::async, [&]
{
using namespace std::chrono_literals;
const auto delay = 5000ms;
std::this_thread::sleep_for(delay);
std::cout << "Done okay byeeeeeeee \n";
});
//5 Going out of scope, destructors will be called therefore you will be blocked
};
//2 You are on main thread
// You execute lambda on main thread, now you will enter into its contents
lambda();
//6 After all destructors run you will continue here
Related
I'm studying concurrency in C++ and I'm trying to implement a multithreaded callback registration system. I came up with the following code, which is supposed to accept registration requests until an event occurs. After that, it should execute all the registered callbacks in order with which they were registered. The registration order doesn't have to be deterministic.
The code doesn't work as expected. First of all, it rarely prints the "Pushing callback with id" message. Secondly, it sometimes hangs (a deadlock caused by a race condition, I assume). I'd appreciate help in figuring out what's going on here. If you see that I overcomplicate some parts of the code or misuse some pieces, please also point it out.
#include <condition_variable>
#include <functional>
#include <iostream>
#include <mutex>
#include <queue>
#include <thread>
class CallbackRegistrar{
public:
void registerCallbackAndExecute(std::function<void()> callback) {
if (!eventTriggered) {
std::unique_lock<std::mutex> lock(callbackMutex);
auto saved_id = callback_id;
std::cout << "Pushing callback with id " << saved_id << std::endl;
registeredCallbacks.push(std::make_pair(callback_id, callback));
++callback_id;
callbackCond.wait(lock, [this, saved_id]{return releasedCallback.first == saved_id;});
releasedCallback.second();
callbackExecuted = true;
eventCond.notify_one();
}
else {
callback();
}
}
void registerEvent() {
eventTriggered = true;
while (!registeredCallbacks.empty()) {
releasedCallback = registeredCallbacks.front();
callbackCond.notify_all();
std::unique_lock<std::mutex> lock(eventMutex);
eventCond.wait(lock, [this]{return callbackExecuted;});
callbackExecuted = false;
registeredCallbacks.pop();
}
}
private:
std::queue<std::pair<unsigned, std::function<void()>>> registeredCallbacks;
bool eventTriggered{false};
bool callbackExecuted{false};
std::mutex callbackMutex;
std::mutex eventMutex;
std::condition_variable callbackCond;
std::condition_variable eventCond;
unsigned callback_id{1};
std::pair<unsigned, std::function<void()>> releasedCallback;
};
int main()
{
CallbackRegistrar registrar;
std::thread t1(&CallbackRegistrar::registerCallbackAndExecute, std::ref(registrar), []{std::cout << "First!\n";});
std::thread t2(&CallbackRegistrar::registerCallbackAndExecute, std::ref(registrar), []{std::cout << "Second!\n";});
registrar.registerEvent();
t1.join();
t2.join();
return 0;
}
This answer has been edited in response to more information being provided by the OP in a comment, the edit is at the bottom of the answer.
Along with the excellent suggestions in the comments, the main problem that I have found in your code is with the callbackCond condition variable wait condition that you have set up. What happens if releasedCallback.first does not equal savedId?
When I have run your code (with a thread-safe queue and eventTriggered as an atomic) I found that the problem was in this wait function, if you put a print statement in that function you will find that you get something like this:
releasedCallback.first: 0, savedId: 1
This then waits forever.
In fact, I've found that the condition variables used in your code aren't actually needed. You only need one, and it can live inside the thread-safe queue that you are going to build after some searching ;)
After you have the thread-safe queue, the code from above can be reduced to:
class CallbackRegistrar{
public:
using NumberedCallback = std::pair<unsigned int, std::function<void()>>;
void postCallback(std::function<void()> callback) {
if (!eventTriggered)
{
std::unique_lock<std::mutex> lock(mutex);
auto saved_id = callback_id;
std::cout << "Pushing callback with id " << saved_id << std::endl;
registeredCallbacks.push(std::make_pair(callback_id, callback));
++callback_id;
}
else
{
while (!registeredCallbacks.empty())
{
NumberedCallback releasedCallback;
registeredCallbacks.waitAndPop(releasedCallback);
releasedCallback.second();
}
callback();
}
}
void registerEvent() {
eventTriggered = true;
}
private:
ThreadSafeQueue<NumberedCallback> registeredCallbacks;
std::atomic<bool> eventTriggered{false};
std::mutex mutex;
unsigned int callback_id{1};
};
int main()
{
CallbackRegistrar registrar;
std::vector<std::thread> threads;
for (int i = 0; i < 10; i++)
{
threads.push_back(std::thread(&CallbackRegistrar::postCallback,
std::ref(registrar),
[i]{std::cout << std::to_string(i) <<"\n";}
));
}
registrar.registerEvent();
for (auto& thread : threads)
{
thread.join();
}
return 0;
}
I'm not sure if this does exactly what you want, but it doesn't deadlock. It's a good starting point in any case, but you need to bring your own implementation of ThreadSafeQueue.
Edit
This edit is in response to the comment by the OP stating that "once the event occurs, all the callbacks should be executed in [the] order that they've been pushed to the queue and by the same thread that registered them".
This was not mentioned in the original question post. However, if that is the required behaviour then we need to have a condition variable wait in the postCallback method. I think this is also the reason why the OP had the condition variable in the postCallback method in the first place.
In the code below I have made a few edits to the callbacks, they now take input parameters. I did this to print some useful information while the code is running so that it is easier to see how it works, and, importantly how the condition variable wait is working.
The basic idea is similar to what you had done, I've just trimmed out the stuff you didn't need.
class CallbackRegistrar{
public:
using NumberedCallback = std::pair<unsigned int, std::function<void(int, int)>>;
void postCallback(std::function<void(int, int)> callback, int threadId) {
if (!m_eventTriggered)
{
// Lock the m_mutex
std::unique_lock<std::mutex> lock(m_mutex);
// Save the current callback ID and push the callback to the queue
auto savedId = m_currentCallbackId++;
std::cout << "Pushing callback with ID " << savedId << "\n";
m_registeredCallbacks.push(std::make_pair(savedId, callback));
// Wait until our thread's callback is next in the queue,
// this will occur when the ID of the last called callback is one less than our saved callback.
m_conditionVariable.wait(lock, [this, savedId, threadId] () -> bool
{
std::cout << "Waiting on thread " << threadId << " last: " << m_lastCalledCallbackId << ", saved - 1: " << (savedId - 1) << "\n";
return (m_lastCalledCallbackId == (savedId - 1));
});
// Once we are finished waiting, get the callback out of the queue
NumberedCallback retrievedCallback;
m_registeredCallbacks.waitAndPop(retrievedCallback);
// Update last callback ID and call the callback
m_lastCalledCallbackId = retrievedCallback.first;
retrievedCallback.second(m_lastCalledCallbackId, threadId);
// Notify one waiting thread
m_conditionVariable.notify_one();
}
else
{
// If the event is already triggered, call the callback straight away
callback(-1, threadId);
}
}
void registerEvent() {
// This is all we have to do here.
m_eventTriggered = true;
}
private:
ThreadSafeQueue<NumberedCallback> m_registeredCallbacks;
std::atomic<bool> m_eventTriggered{ false};
std::mutex m_mutex;
std::condition_variable m_conditionVariable;
unsigned int m_currentCallbackId{ 1};
std::atomic<unsigned int> m_lastCalledCallbackId{ 0};
};
The main function is as above, except I am creating 100 threads instead of 10, and I have made the callback print out information about how it was called.
for (int createdThreadId = 0; createdThreadId < 100; createdThreadId++)
{
threads.push_back(std::thread(&CallbackRegistrar::postCallback,
std::ref(registrar),
[createdThreadId](int registeredCallbackId, int callingThreadId)
{
if (registeredCallbackId < 0)
{
std::cout << "Callback " << createdThreadId;
std::cout << " called immediately, from thread: " << callingThreadId << "\n";
}
else
{
std::cout << "Callback " << createdThreadId;
std::cout << " called from thread " << callingThreadId;
std::cout << " after being registered as " << registeredCallbackId << "\n";
}
},
createdThreadId));
}
I am not entirely sure why you want to do this, as it seems to defeat the point of having multiple threads, although I may be missing something there. But, regardless, I hope this helps you to understand better the problem you are trying to solve.
Experimenting with this code some more, I found out why the "Pushing callback with id " part was rarely printed. It's because the call to registrar.registerEvent from the main thread was usually faster than the calls to registerCallbackAndExecute from separate threads. Because of that, the condition if (!eventTriggered) was almost never fulfilled (eventTriggered had been set to true in the registerEvent method) and hence all calls to registerCallbackAndExecute were falling into the else branch and executing straightaway.
Then, the program sometimes also didn't finish, because of a race condition between registerEvent and registerCallbackAndExecute. Sometimes, registerEvent was being called after the check if (!eventTriggered) but before pushing the callback to the queue. Then, registerEvent completed instantly (as the queue was empty) while the thread calling registerCallbackAndExecute was pushing the callback to the queue. The latter thread then kept waiting forever for the event (that had already happened) to happen.
I am new to threading, and i am trying to write a function that keep outputing an variable while i should be able to change that variable at runtime, and the output should change to my input once I input a new value in. By the following program is not running as i expected, whats wrong here? is there anything i can reference to so i can build this funciton out?
int a;
void* ptr;
void* Input(void* arg){
while(true){
std::cin >> a;
std::cout << std::endl;
}
return ptr;
}
void* Output(void *arg){
while(true){
std::cout << a << std::endl;
}
return ptr;
}
int main(){
pthread_t GetInput;
pthread_create(&GetInput,NULL,Input,NULL);
pthread_t GetOutput;
pthread_create(&GetOutput,NULL,Output,NULL);
}
Your main thread is not waiting for your child thread and exited when main() returned. To make your main thread to wait for children finish their jobs, you should call pthread_join() for them.
int main(){
pthread_t GetInput;
pthread_create(&GetInput,NULL,Input,NULL);
pthread_t GetOutput;
pthread_create(&GetOutput,NULL,Output,NULL);
pthread_join(GetInput, NULL);
pthread_join(GetOutput, NULL);
return 0;
}
Here's another alternative using std::async() for your code.
#include <chrono>
#include <future>
#include <iostream>
#include <mutex>
int a;
std::mutex mtx_;
void Input(void* arg) {
while (true) {
int tmp_a;
std::cin >> tmp_a;
{
std::lock_guard<std::mutex> lock(mtx_);
a = tmp_a;
}
std::cout << std::endl;
}
}
void Output(void* arg) {
while (true) {
{
std::lock_guard<std::mutex> lock(mtx_);
std::cout << a << std::endl;
}
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main() {
auto ft_in = std::async(std::launch::async, Input, &a);
auto ft_out = std::async(std::launch::async, Output, &a);
ft_in.wait();
ft_out.wait();
return 0;
}
Well,I don't know how to use pthread.
And it seems Mr.john-park or Ms.john-park already gave a answer.
But I think use thread is a better choice.
To use it,we should:
#include<thread>
After that,if u want to start a new thread,and "connect" it with a function(In fact,we usually do)
There is a class named thread.
First,we should
thread *thread name*(*function name*);
WARNING:function nameshould be without "(" and ")"
May because here should be a pointer.
Then,to the question.
Suppose we wrote:
thread GetInput(Input);
thread GetOutput(Output);
When u want to stop GetOutput some time and run GetInput,
just
GetInput.join()
Here's a not so good example:
#include <iostream>
#include <thread>
using namespace std;
void f1()
{
while (true)
{
cout << "THREAD 1!" << endl;
}
}
void f2()
{
for (int i = 0; i < 10; i++)
cout << "THREAD 2!" << endl;
thread t1(f1);
t1.join();
for (int i = 0; i < 10; i++)
cout << "THREAD 2!" << endl;
}
int main()
{
thread t2(f2);
return 0;
}
First,we started t2.
Then t2 started t1.
Now we can know why we use join().
If we don't join(),
It'll be hard for us to read the output because it'll close the cmd window quickly.
But we can know,
after t2 end,
return 0;
ran.
But if we used join()
Here's the output:
THREAD 2!
THREAD 2!
THREAD 2!
...(THREAD 2!*10)
THREAD 1!
THREAD 1!
...(Always THREAD 1!)
I am trying to run run() function every 5 seconds without stopping while() loop (parallelly). How can I do that ? Thanks in advance
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
void run()
{
this_thread::sleep_for(chrono::milliseconds(5000));
cout << "good morning" << endl;
}
int main()
{
thread t1(run);
t1.detach();
while(1)
{
cout << "hello" << endl;
this_thread::sleep_for(chrono::milliseconds(500));
}
return 0;
}
In your main function, it is important to understand what each thread is doing.
The main thread creates a std::thread called t1
The main thread continues and detaches the thread
The main thread executes your while loop in which it:
prints hello
sleeps for 0.5 seconds
The main thread returns 0, your program is finished.
Any time from point 1, thread t1 sleeps for 5 seconds and then prints good morning. This happens only once! Also, as pointed out by #Fareanor, std::cout is not thread-safe, so accessing it with the main thread and thread t1 may result in a data race.
When the main thread reaches point 4 (it actually never does because your while loop is infinite), your thread t1 might have finished it's task or not. Imagine the potential problems that could occur. In most of the cases, you'll want to use std::thread::join().
To solve your problem, there are several alternatives. In the following, we will assume that the execution of the function run without the std::this_thread::sleep_for is insignificant compared to 5 seconds, as per the comment of #Landstalker. The execution time of run will then be 5 seconds plus some insignificant time.
As suggested in the comments, instead of executing the function run every 5 seconds, you could simply execute the body of run every 5 seconds by placing a while loop inside of that function:
void run()
{
while (true)
{
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
std::cout << "good morning" << std::endl;
}
}
int main()
{
std::thread t(run);
t.join();
return 0;
}
If, for some reason, you really need to execute the run function every 5 seconds as stated in your question, you could launch a wrapper function or lambda which contains the while loop:
void run()
{
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
std::cout << "good morning" << std::endl;
}
int main()
{
auto exec_run = [](){ while (true) run(); };
std::thread t(exec_run);
t.join();
return 0;
}
As a side note, it's better to avoid using namespace std.
Just call your run function in seperate thread function like below. Is this ok for you?
void ThreadFunction()
{
while(true) {
run();
this_thread::sleep_for(chrono::milliseconds(5000));
}
}
void run()
{
cout << "good morning" << endl;
}
int main()
{
thread t1(ThreadFunction);
t1.detach();
while(1)
{
cout << "hello" << endl;
this_thread::sleep_for(chrono::milliseconds(500));
}
return 0;
}
I'm trying to implement timer with standard environment
Here is a code I have:
bool shutdownDetected = false;
void signal_handler(const int sigid)
{
shutdownDetected = true;
}
int main(int argc, const char * argv[])
{
signal(SIGTERM, (sig_t)signal_handler);
std::async(std::launch::async, [&] () {
std::this_thread::sleep_for( std::chrono::milliseconds{5000});
std::cout << "On TIMER!" << std::endl;
} );
std::cout << "main function" << std::endl;
while (!shutdownDetected) {
}
return EXIT_SUCCESS;
}
As result I see in output after 5 seconds:
// 5 seconds left
On Timer
main function
but would like to see:
main function
// 5 seconds left
On Timer
Seems that my implementation hangs main thread as well. How to avoid this?
Your std::async command returns an std::future, which is then immediately destroyed. The problem is that destruction of a future involves 'joining' the thread you created, which means that the destructor is going to wait until the thread has ended itself and code execution in your main thread doesn't advance until that process has completed.
Simple answer is to assign the result of your std::async call to a variable, and possibly call its get() member function in your loop that tests for termination.
auto t = std::async(std::launch::async, [&] () {
std::this_thread::sleep_for( std::chrono::milliseconds{5000});
std::cout << "On TIMER!" << std::endl;
} );
std::cout << "main function" << std::endl;
t.get();
std::async(std::launch::async, [&] () {
std::this_thread::sleep_for( std::chrono::milliseconds{5000});
std::cout << "On TIMER!" << std::endl;
} );
Does not work unless you assign the std::future returned by std::async to a variable and keep it around. I did not know why this is, clearly because I couldn't be bothered to look it up. Vincent Savard did, and linked us to documentation on the destructor for std::future which says:
it may block if all of the following are true: the shared state was created by a call to std::async, the shared state is not yet ready, and this was the last reference to the shared state.
Since the returnded std::future is not assigned to anything, it is instantly destroyed and the destructor blocks until completion.
I'm going to leave out the signal handler as it's not relevant to the problem.
#include <iostream>
#include <future>
int main()
{
auto letMeLive = std::async(std::launch::async, [] () {
std::this_thread::sleep_for( std::chrono::milliseconds{5000});
std::cout << "On TIMER!" << std::endl;
} );
std::cout << "main function" << std::endl;
letMeLive.wait(); // instead of the signal handler
return EXIT_SUCCESS;
}
I am beginning to use the thread class.
In the main() thread below, an Example class is created.
Inside the constructor of Example, two threads are created in the Example::start() function.
Example::foo() is designed to print a message every second.
Example::bar() is designed to print a message every 5 seconds.
Inside the main() function, a loop is designed to print every 3 seconds.
I decided to not use join() in Example::start() because I would like to have the main() function continuously run.
Why does the main thread crash during run-time?
// thread example
#include <iostream> // std::cout
#include <thread> // std::thread
#include <chrono> // std::chrono::seconds
using namespace std;
class Example
{
public:
Example();
void start();
void foo();
void bar(int x);
};
Example::Example()
{
start();
}
void Example::start()
{
std::thread first (&Example::foo, this); // spawn new thread that calls foo()
std::thread second (&Example::bar, this, 5); // spawn new thread that calls bar(0)
// synchronize threads:
//first.join(); // pauses until first finishes
//second.join(); // pauses until second finishes
}
void Example::foo()
{
cout << "entered foo()" << endl;
int count = 0;
while(1) {
std::this_thread::sleep_for (std::chrono::seconds(1));
++count;
cout << "foo() count = " << count << endl;
}
}
void Example::bar(int x)
{
cout << "entered bar() x = " << x << endl;
int count = 0;
while(1) {
std::this_thread::sleep_for (std::chrono::seconds(5));
++count;
cout << "bar() count = " << count << endl;
}
}
int main() {
Example* c = new Example();
cout << "Example() created" << endl;
while(true) {
std::this_thread::sleep_for(std::chrono::seconds(3));
cout << "main() thread loop..." << endl;
}
std::cout << "end of main()";
delete c;
return 0;
}
Foo::Start() initalizes two threads, thread Foo and thread bar. When the function Start returns to the main thread, the two thread objects go out of scope and the destructor is called for clearing out of scope variables.
A simple solution would be to make threads part of the class.
On another note, std::cout is not a synchronized class, when writing your text might be garbled: Is cout synchronized/thread-safe?
Also, when creating your class Example, delete is never called which causes a memory leak.
Your comment here:
void Example::start()
{
std::thread first (&Example::foo, this); // spawn new thread that calls foo()
std::thread second (&Example::bar, this, 5); // spawn new thread that calls bar(0)
// synchronize threads:
//first.join(); // pauses until first finishes
//second.join(); // pauses until second finishes
}
Is wrong.
Not only does the the join pause until the threads finish. But they also allow the thread to be cleaned up. A thread destructor calls terminate while the thread is join-able (ie it is still running). So you must call join() on the thread (to wait for it to finish) before you can allow the destructor to be called.
One of the comments above suggests calling detach(). This detaches the thread of execution from the thread object (thus making it not join-able). This will work (as your code is in infinite loop), but is a bad idea generally. As allowing main() to exit while threads are still running is undefined behavior.