5

How can I check if thread has finished work in C++11 and above? I have been reading the documentation and I have written the following code:

#include <iostream>
#include <thread>
void mythread() 
{
    //do some stuff
}
int main() 
{
  std::thread foo(mythread);  
  if (foo.joinable())
  {
    foo.join();
    //do some next stuff
  }
}

joinable tells only that the thread has started work, but I would like to know how to write code to check if the thread has finished work.

For example:

#include <iostream>
#include <thread>
void mythread() 
{
    //do some stuff
}
int main() 
{
  std::thread foo(mythread);  
  if (foo.finishedWork())
  {
    foo.join();
    //do some next stuff
  }
}
Chris Hamilton
  • 555
  • 5
  • 22
user2856064
  • 541
  • 1
  • 8
  • 25

4 Answers4

10

You may want to use std::future, it provides higher level facilities where you can trivially check if the asynchronous computation is finished (aka ready): Example:

void mythread() {
    //do some stuff
}

template<typename T>
bool future_is_ready(std::future<T>& t){
    return t.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
}

int main() 
{
    std::future<void> foo = std::async(std::launch::async, mythread);  
    if (future_is_ready(foo)){
        //do some next stuff
    }
}

On the other hand, you may think simply using a "safe" (or atomic) flag works:

#include <iostream>
#include <thread>

std::atomic<bool> is_done{false};

void mythread() 
{
    //do some stuff
    ......
    is_done = true;
}
int main() 
{
  std::thread foo(mythread);  
  if (is_done)
  {
    foo.join();
    //do some next stuff
  }
  .....
  if(foo.joinable()) foo.join();
}

But, it doesn't work. While you think is_done = true is the last thing you did in mythread(); You may have created some objects of automatic storage duration in that scope, and since such objects are destroyed in the reverse order of construction, there will still be "some work" in that thread after setting is_done.

WhiZTiM
  • 21,207
  • 4
  • 43
  • 68
1

You want a future. Start your thread withstd::async and use wait_for with zero seconds on it. Compare the result against future_status::ready.

knivil
  • 787
  • 3
  • 11
1

You can use wait_for of std::future to check whether the result is already there. A simple way to get a future for an asynchronous task is std::async.

#include <future>

// ...

// launch task and get result future
auto rf = std::async(std::launch::async, mythread);
// get initial status
auto status = rf.wait_for(std::chrono::nanoseconds(1));
// loop while task is not ready
while(status != std::future_status::ready)
{ 

    // not ready yet, do other stuff here

    // 1 nanosecond timeout check
    status = rf.wait_for(std::chrono::nanoseconds(1));
}
// we are done...
Pixelchemist
  • 24,090
  • 7
  • 47
  • 71
0

I had the same problem, and my solution was to wrap the thread class, so I can set a flag when the function has finished its work.

Here you find the discussion for the solution Stack Overflow

And here is the working example: Celma managed thread

Community
  • 1
  • 1
Rene
  • 2,466
  • 1
  • 12
  • 18
  • 2
    `volatile` doesn't prevent data races. – πάντα ῥεῖ Feb 23 '17 at 14:40
  • @πάνταῥεῖ Obviously you did not read the whole thread nor look at the source code before hitting the downvote button. – Rene Feb 23 '17 at 14:43
  • @πάνταῥεῖ The working example doesn't use volatile. It (correctly) uses `` instead. – Martin Bonner supports Monica Feb 23 '17 at 14:44
  • 1
    While this technically isn't a link-only answer, it's still not much of an answer. It's better to include the actual answer in the answer - or suggest to close this question as a duplicate of the linked one. – Barry Feb 23 '17 at 14:53
  • @πάνταῥεῖ Then I apaologise. I assumed because of your comment and the single vote == downvote that it was you. – Rene Feb 23 '17 at 15:24
  • @Barry I cannot mark entries as duplicates (or at least I don't know how). If you think this applies here, then go ahead. – Rene Feb 23 '17 at 15:25