why t.join cannot be called twice in this example? - c++

For some time I have been trying to use std::thread, and in my project i wanted to make sure that the threads are not making one thing couple times at once, that's why i am trying to make a simple project that has something like "check" if thread is done, and then start again
#include <future>
#include <thread>
#include <chrono>
#include <iostream>
using namespace std::chrono_literals;
void Thing()
{
std::this_thread::sleep_for(3s);
}
int main()
{
std::packaged_task<void()> task(Thing);
auto future = task.get_future();
std::thread t(std::move(task));
while (true) {
auto status = future.wait_for(0ms);
if (status != std::future_status::ready)
{
std::cout << "not yet" << std::endl;
}
else
{
t.join();
std::cout << "Join()" << std::endl;
}
std::this_thread::sleep_for(300ms);
}
}
using this code i have error at line with std::cout << "Join()" << std::endl; and the error says: Unhandled exception at 0x7632A842 in dasd.exe: Microsoft C++ exception: std::system_error at memory location 0x00AFF8D4.
this error is comes out when the thread is ready, and t.join() is called.
output of this project:
not yet
...
not yet
Join()
Thank You in advance

As you can see https://en.cppreference.com/w/cpp/thread/thread/join
join has as post condition
joinable() is false
and in error condition
invalid_argument if joinable() is false
So you cannot call it twice as you do.
You probably want to break the loop once you call join or rewrite your loop such as:
while (future.wait_for(300ms) != std::future_status::ready) {
std::cout << "not yet" << std::endl;
}
t.join();
std::cout << "Join()" << std::endl;

Actually, you don't need a while loop there. Instead, you could simply call join.
What join does is to wait for the thread to finish its job. After the thread finishes its job, it exits and cleans the stack and the second call to join doesn't make sense at all.
I also would suggest using std::async in case you want an async function that also returns a value.

Related

Invoke a method with a timeout

What I want to is invoking a method foo() with a timeout (say 1 minute). If its execution costs less than 1 minute, return the result. Otherwise an exception will be thrown. Here is the code:
//PRINT "START" IN THE LOG
auto m = std::make_shared<std::mutex>();
auto cv = std::make_shared<std::condition_variable>();
auto ready = std::make_shared<bool>(false);
auto response = std::make_shared<TResponse>();
auto exception = std::make_shared<FooException>();
exception->Code = ErrorCode::None;
std::thread([=]
{
std::unique_lock<std::mutex> lk(*m);
cv->wait(lk, [=]{ return *ready; });
try
{
//PRINT "PROCESS" IN THE LOG
auto r = foo();
*response = std::move(r);
}
catch(const FooException& e)
{
*exception = std::move(e);
}
lk.unlock();
cv->notify_one();
}).detach();
std::unique_lock<std::mutex> lk(*m);
*ready = true;
cv->notify_one();
auto status = cv->wait_for(lk, std::chrono::seconds(60));
if (status == std::cv_status::timeout)
{
//PRINT "TIMEOUT" IN THE LOG
//throw timeout exception
}
else
{
//PRINT "FINISH" IN THE LOG
if (exception->Code == ErrorCode::None)
{
return *response;
}
else
{
throw *exception;
}
}
You can see I add logs START/PROCESS/FINISH/TIMEOUT in the code, every time this method is executed, I can see START/PROCESS/FINISH or START/PROCESS/TIMEOUT pattern in the logs. However, sometimes the logs are START/PROCESS, without any FINISH/TIMEOUT. I think cv->wait_for should block the current thread for 60 seconds at most, then it exists with either TIMEOUT or FINISH.
The foo() method contains disk IO operations to network drives that sometimes hangs for more than 1 hour(the reason is not related to this question, and it can't be resolved now), I tried to replace foo with a thread sleep, everything is working as expected. What's wrong with this code and how can I improve this?
Because you have no predicate in the cv->wait_for call, the thread might be unblocked spuriously. However, it is strange that no FINISH/TIMEOUT is printed. So we might need more information here: What does happen with the program? Does it hang, does it throw, does it just exit, does it print in the line after cv->wait_for?
You could try using std::async and see if the same behavior appears (furthermore, it would greatly simplify your code):
std::future<int> res = std::async(foo);
std::future_status stat = res.wait_for(std::chrono::seconds(60));
if (stat != std::future_status::ready) {
std::cout << "Timed out..." << "\n";
} else {
try {
int result = res.get();
std::cout << "Result = " << result << std::endl;
} catch (const FooException& e) {
std::cerr << e.what() << '\n';
}
}
EDIT As pointed out in the comments by CuriouslyRecurringThoughts the future of std::async blocks in the destructor. If that is not an option, the following code uses a std::promise and a detached thread instead:
std::promise<int> prom;
std::future<int> res = prom.get_future();
std::thread([p = std::move(prom)]() mutable {
try {
p.set_value(foo());
} catch (const std::exception& e) {
p.set_exception(std::current_exception());
}
}).detach();
Waiting for the std::future is done as shown before.
It seems that despite the timed wait your main thread deadlocks because even when cv->wait_for returns with timeout it still tries to lk.lock() on the mutex which is currently locked by the second thread.
As mentioned on cppreference about wait_for:
When unblocked, regardless of the reason, lock is reacquired and wait_for() exits.
I'm not sure why the promise/future solution didn't work for you since you didn't post that example here, but I've tried a simple version of it which seems to work even when the second thread "hangs":
using namespace std::chrono_literals;
std::cout << "START" << std::endl;
std::promise<void> p;
auto f = p.get_future();
std::thread t([p = std::move(p)]() mutable {
std::cout << "PROCESS" << std::endl;
std::this_thread::sleep_for(5min);
p.set_value();
});
auto status = f.wait_for(5s);
std::cout << (status == std::future_status::ready ? "FINISH" : "TIMEOUT") << std::endl;
t.join();
The output is as expected:
START
PROCESS
TIMEOUT
We can create a separate thread to run the call itself, and wait on a condition variable back in your main thread which will be signaled by the thread doing the call to foo once it returns.
The trick is to wait on the condition variable with your 60s timeout, so that if the call takes longer than the timeout you will still wake up, know about it, and be able to throw the exception - all in the main thread.
Please find below a code example:
#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std::chrono_literals;
int foo()
{
//std::this_thread::sleep_for(10s); //Will Return Success
std::this_thread::sleep_for(70s); //Will Return Timeout
return 1;
}
int foo_wrapper()
{
std::mutex m;
std::condition_variable cv;
int retValue;
std::thread t([&cv, &retValue]()
{
retValue = foo();
cv.notify_one();
});
t.detach();
{
std::unique_lock<std::mutex> lock(m);
if(cv.wait_for(lock, 60s) == std::cv_status::timeout)
throw std::runtime_error("Timeout");
}
return retValue;
}
int main()
{
bool timedout = false;
try {
foo_wrapper();
}
catch(std::runtime_error& e) {
std::cout << e.what() << std::endl;
timedout = true;
}
if(!timedout)
std::cout << "Success" << std::endl;
else
std::cout << "Failure" << std::endl;
return 0;
}
If we use std::this_thread::sleep_for(10s); inside foo will return SUCCESS
And, if we use std::this_thread::sleep_for(70s); inside foo will return TIMEOUT
I hope it helps!
As Mike van Dyke says, and the documentation makes quite clear, you need a predicate to use a condition variable correctly, to deal with spurious wakeups:
When the condition variable is notified, a timeout expires, or a spurious wakeup occurs, the thread is awakened, and the mutex is atomically reacquired. The thread should then check the condition and resume waiting if the wake up was spurious.
Any use of a condvar for waiting without a loop and predicate is wrong. It should always have either an explicit while(!predicate) loop or look something like:
std::unique_lock<std::mutex> lk(*m);
auto status = cv->wait_for(lk, std::chrono::seconds(60), predicate);
if (status == std::cv_status::timeout)
{ /*...*/ } else { /*...*/ }
which means you need some predicate to check: setting *ready = false before notifying the condvar in your thread (and using !*ready as your predicate) would be fine.
As for why you didn't see the expected result - I have no idea, because I can't see your real logging code or what happens outside the code snippet you provided. Waking from wait_for without either having timed out or received a valid response or exception is the most likely, but you'll either have to debug your code or provide a complete example to help with that.

Is a condition variable's .wait_for() an efficient way to perform a background task at a specific interval?

I need to run an activity every so often while my program is running. In production code this is configurable with a default of 30 minutes, but in the example below I've used 5 seconds. Previously I had a std::thread that would loop once per second checking to see if it was time to run the activity OR if the program was closed. This allowed me to close the program at any time without having the .join() on the activity's thread block my application's exit waiting for its next iteration. At any moment it was less than a second away from checking to see if it should close or perform the activity.
I do not like the idea of wasting time checking every second for an activity that may only occur every 30 minutes while the program is running, so I attempted to switch it to a condition variable. I've included a small example of my implementation below. I want to be sure I'm using the right tools to do this. The issue I see with my code is unnecessary calls of the lambda expression which I'll explain below.
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
bool asking_thread_to_quit;
std::mutex cv_mutex;
std::condition_variable cv;
void RunThread()
{
{
std::lock_guard<std::mutex> lock(cv_mutex);
asking_thread_to_quit = false;
}
std::cout << "Started RunThread." << std::endl;
while(true)
{
{
std::unique_lock<std::mutex> lock(cv_mutex);
std::chrono::seconds delay(5);
if(cv.wait_for(lock, delay, [] { std::cout << "WAKEUP" << std::endl; return asking_thread_to_quit; })) // timed out
{
std::cout << "Breaking RunThread Loop." << std::endl;
break;
}
}
std::cout << "TIMER CODE!" << std::endl;
}
}
int main(int argc, char *argv[])
{
std::cout << "Program Started" << std::endl;
std::thread run_thread(RunThread);
// This is where the rest of the program would be implemented, but for the sake of this example, simply wait for user input to allow the thread to run in the background:
char test;
std::cin >> test;
{
std::lock_guard<std::mutex> lock(cv_mutex);
asking_thread_to_quit = true;
}
cv.notify_all();
std::cout << "Joining RunThread..." << std::endl;
run_thread.join();
std::cout << "RunThread Joined." << std::endl;
return 0;
}
If you execute the program and allow for one 5-second iteration to pass, it gives the following output:
Program Started
Started RunThread.
WAKEUP
WAKEUP
TIMER CODE!
WAKEUP
q <-- I typed this to quit.
Joining RunThread...
WAKEUP
Breaking RunThread Loop.
RunThread Joined.
You can see that it does the following:
(WAKEUP) Performs the check prior to waiting
Wait for five seconds
(WAKEUP) Performs the check
(TIMER CODE!) Executes the activity
(WAKEUP) Performs the check again before going back to waiting
Step 5 seems unnecessary as I just performed it a split second ago, but I believe it is necessary as .wait_for() doesn't know I'm using it inside of a while(true) loop. Is this something I'm stuck with, or is there a way to remove the initial check in the .wait_for() call? I'm guessing there is not as it would allow for the system to .wait_for() something that it doesn't need to wait for. This is what leads me to wonder if I'm using the right language features to begin with. Is there a better way?
The Answer
The answer given below goes into detail on other issues with my code as well as sparked an informative related conversation. I'm going to accept that answer as it helped me the most, but the quick answer to the question seems to be this:
asking_thread_to_quit could have been set to true during the TIMER CODE! section, requiring another check prior to waiting on the condition variable again.
Your code has a few issues with it.
void RunThread()
{
asking_thread_to_quit = false;
This is a race condition. You shouldn't modify a non-atomic shared variable in two different threads without synchronization.
std::cout << "Started RunThread." << std::endl;
while(true)
{
std::unique_lock<std::mutex> lock(cv_mutex);
std::chrono::seconds delay(5);
First using namespace std::literals::chrono_literals;. Then use 5s.
if(cv.wait_for(lock, delay, [] { std::cout << "WAKEUP" << std::endl; return asking_thread_to_quit; })) // timed out
{
std::cout << "Breaking RunThread Loop." << std::endl;
break;
}
else
{
std::cout << "TIMER CODE!" << std::endl;
}
the TIMER CODE usually shouldn't run within the std::mutex lock, as that means anyone sending a message is blocked until the timer code is finished.
}
}
Finally, WAKEUPs are spurious details. You could WAKEUP 50 times in that 5 seconds; condition variables do not guarantee a bounded number of checks.
asking_thread_to_quit = true;
cv.notify_all();
this again results in a race condition; your program does undefined behavior twice over now.
Changing asking_thread_to_quit to a std::atomic<bool> will get rid of the formal race condition and UB. It will, however, let your code miss a request to quit and mistakenly do another 5 second sleep followed by the task.
This is because the return value of your lambda could be calculated, then the asking_thread_to_quit=true and notify_all evaluates with nothing waiting on the condition variable (so nothing is woken up), then the condition variable is blocked on, 5 seconds pass, it wakes up returning false, then repeats the while loop.
With the mutex being held in all writes to the bool, the write cannot occur until after the lambda has returned and we are waiting on the condition with an unlocked mutex. This prevents the .notify_all() from being missed.
The cargo-cult solution to this is to always guard all reads and writes to asking_thread_to_quit by the cv_mutex. Then avoid holding the cv_mutex for any length of time, including while handling the timer wakeup.
std::unique_lock<std::mutex> lock_cv() {
return std::unique_lock<std::mutex>(cv_mutex);
}
void RunThread()
{
{
auto lock = lock_cv();
asking_thread_to_quit = false;
}
std::cout << "Started RunThread." << std::endl;
while(true)
{
{
auto lock = lock_cv();
using namespace std::literals::chrono_literals;
if(cv.wait_for(lock, 5s, [] { std::cout << "WAKEUP" << std::endl; return asking_thread_to_quit; })) // timed out
{
std::cout << "Breaking RunThread Loop." << std::endl;
break;
}
}
std::cout << "TIMER CODE!" << std::endl;
}
}
and in main:
{
auto lock = lock_cv();
asking_thread_to_quit = true;
}
cv.notify_all();
And yes, I intended for cv.notify_all() to be outside the mutex. It works; understanding why is outside the scope of the "cargo-cult" solution I'm providing here.
Finally, the WAKEUP is not spurious. The asking_thread_to_quit could have changed since the last time it was checked. Running the lambda guarantees we should fall asleep in a careful manner, with no gap between unlocking the mutex for waiting and waiting for notifications.
Spurious WAKEUPs can still occur; they would show up as more WAKEUPs than you expect.

Timer hangs main thread

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;
}

simultaneously run different thread without waiting for other thread to complete

The thing is i want to use c++ library which runs different threads simultaneously without having other threads to wait until the preceding thread is complete and their functionality within each thread is run simultaneuslly,I am talking about the code which is to be run in the thread;the sample code is shown below.
while(condition is true<it is infinite loop >){
running sleep here with random time
sleep(random time(sec))
rest of the code is here
}
This infinite while loop is run in each thread. I want to run this while loop in each thread to be run simultaneously without being stuck at the first thread to be completed. In other words all the infinite while loop(in each thread context) is to be run simultaneously. How do I achieve that? If you can please share some sample code actually I have used future with async but I get the same behavior as normal <thread> using join().
The issue you are encountering is because of the rather silly definition of std::async (in my opinion) that it doesn't have to execute your code asynchronously, but can instead run it when you attempt to get from its std::future return value.
No matter. If you set the first parameter of your call to std::launch::async you force it to run asynchronously. You can then save the future in a container, and if you retire futures from this container regularly, you can run as many threads as the system will let you.
Here's an example:
#include <iostream>
#include <thread>
#include <future>
#include <chrono>
#include <vector>
#include <mutex>
using future_store = std::vector<std::future<void>>;
void retireCompletedThreads(future_store &threadList)
{
for (auto i = threadList.begin(); i != threadList.end(); /* ++i */)
{
if (i->wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{
i->get();
i = threadList.erase(i);
}
else
{
++i;
}
}
}
void waitForAllThreads(future_store &threadList)
{
for (auto& f : threadList)
{
f.get();
}
}
std::mutex coutMutex;
int main(int argc, char* argv[])
{
future_store threadList;
// No infinite loop here, but you can if you want.
// You do need to limit the number of threads you create in some way though,
// for example, only create new threads if threadList.size() < 20.
for (auto i = 0; i < 20; ++i)
{
auto f = std::async(std::launch::async,
[i]() {
{
std::lock_guard<std::mutex> l(coutMutex);
std::cout << "Thread " << i << " started" << std::endl;
}
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> l(coutMutex);
std::cout << "Thread " << i << " completed" << std::endl;
}
});
threadList.push_back(std::move(f));
// Existing threads need to be checked for completion every so often
retireCompletedThreads(threadList);
}
waitForAllThreads(threadList);
}

std::launch::async is blocking like a sync process

I am running Visual Studio 2012 and attempting to learn how std::async works. I have created a very simple C++ console application:
#include "stdafx.h"
#include <future>
#include <iostream>
void foo() {
std::cout << "foo() thread sleep" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "foo() thread awake" << std::endl;
}
int main()
{
std::future<void> res = std::async(std::launch::async, foo);
res.get();
std::cout << "MAIN THREAD" << std::endl;
system("pause");
return 0;
}
My initial expectation was to see "MAIN THREAD" printout appearing before "foo() thread awake" since the two threads are running asynchronously, with the foo() trailing behind due to its sleeping behavior. However, that is not what is actually happening. The call to res.get() blocks until foo() wakes up, and only then does it get to the "MAIN THREAD" printout. This is indicative of a synchronous behavior, so I am wondering what if perhaps I am either missing something, or not fully grasping the implementation. I have looked through numerous posts on this matter, but still cannot make any sense of it. Any help would be appreciated!
res.get();
blocks until the async is done.
http://en.cppreference.com/w/cpp/thread/future/get
Regardless of how you tell it to run, get can't give you the results until it's done.
Well, this is how std::future::get works - it blocks until future has some result or exception to provide.
that doesn't mean that async works synchronously, it is working asynchronously, it's only because you block the thread which waits on the result.
the idea was to to launch some task asynchronously, do something meanwhile and only call get when you need the result, as you might figured out, it is not the most scale-able thing..
if you use Visual Studio 2015, you can access the await keyword both for std::future and concurrency::task (Microsoft PPL library) , and for your own compatible defined types. this achieves non-blocking behavior.
#include "stdafx.h"
#include <future>
#include <iostream>
void foo() {
std::cout << "foo() thread sleep" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "foo() thread awake" << std::endl;
}
std::future<void> entry(){
await std::async(std::launch::async, foo);
std::cout << "foo has finished, back in entry()\n";
}
int main()
{
std::cout << "MAIN THREAD" << std::endl;
entry();
std::cout << "BACK INMAIN THREAD" << std::endl;
system("pause");
return 0;
} //make sure to compile with /await flag
The problem is that res.get() has to wait for its thread to finish before getting its result (if any). To see the concurrency in motion you need to move the get() to after the other code that you want to run at the same time.
This example may make it a little clearer:
#include <ctime>
#include <cstdlib>
#include <future>
#include <iostream>
void foo(int id) {
std::cout << "foo(" << id << ") thread sleep" << std::endl;
// random sleep
std::this_thread::sleep_for(std::chrono::seconds(std::rand() % 10));
std::cout << "foo(" << id << ") thread awake" << std::endl;
}
int main()
{
std::srand(std::time(0));
std::future<void> res1 = std::async(std::launch::async, foo, 1);
std::future<void> res2 = std::async(std::launch::async, foo, 2);
std::future<void> res3 = std::async(std::launch::async, foo, 3);
std::cout << "MAIN THREAD SLEEPING" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(20));
std::cout << "MAIN THREAD AWAKE" << std::endl;
// now wait for all the threads to end
res1.get();
res2.get();
res3.get();
system("pause");
return 0;
}