34

I assumed joinable would indicate this, however, it does not seem to be the case.

In a worker class, I was trying to indicate that it was still processing through a predicate:

bool isRunning(){return thread_->joinable();}

Wouldn't a thread that has exited not be joinable? What am I missing... what is the meaning of boost thread::joinable?

JeffV
  • 52,985
  • 32
  • 103
  • 124

7 Answers7

32

Since you can join a thread even after it has terminated, joinable() will still return true until you call join() or detach(). If you want to know if a thread is still running, you should be able to call timed_join with a wait time of 0. Note that this can result in a race condition since the thread may terminate right after the call.

interjay
  • 107,303
  • 21
  • 270
  • 254
  • 6
    It's a bit misleading to say that it can result in a race condition. `timed_join` alone can't do that. if you make any incorrect assumptions based on the result of the call, you can end up with a race condition, of course, but that's less to do with `timed_join` than with you assuming that the result of that call is still valid. Anyway, +1 – jalf Nov 03 '09 at 14:05
  • 38
    I think this is really bad. Why do the boost designers never think of intuitivity or of beginners. A simple isRunning() method would have been enough. Instead they force one to use a function that should intuitively not be used in this case. I don't want to try and join the thread, I just want to quickly test if it still does something. This is crap. Wasted a lot of time before I found this. Not a damn word in the "docs" either. – AndreasT Jan 11 '10 at 14:26
  • 3
    @AndreasT: Well Boost is done by people as you. If you have a concrete proposal, do it. It will be yet better if you provide in addition a patch with documentation and tests. – Vicente Botet Escriba Oct 08 '13 at 16:58
  • 4
    This answer is not valid as for boost 1.55 on windows : timed_joined() is deprecated, and calling try_join_for(0) returns false without checking wether the thread has finished. A patch has been issued for following versions of boost but it is not clear what the intended behavior is from boost's developer perspective : https://svn.boost.org/trac/boost/ticket/9618 – Ernest_Galbrun Mar 01 '14 at 08:14
6

Use thread::timed_join() with a minimal timeout. It will return false if the thread is still running.

Sample code:

thread_->timed_join(boost::posix_time::seconds(0));
anhoppe
  • 4,287
  • 3
  • 46
  • 58
Joakim Karlsson
  • 1,112
  • 1
  • 15
  • 27
  • 1
    This is false. If a thread was detached it will return false. Indeed you need to read it the other way around: if returns true the thread was running and then stopped during the timeout – Gaetano Mendola Dec 04 '12 at 12:26
  • 1
    @GaetanoMendola: Not exactly, the thread could be stopped and joinable when you call timed_join and the result be true. – Vicente Botet Escriba Oct 08 '13 at 17:03
  • Note: timed_join() is deprecated after boost 3.0. Use try_join_for or try_join_until. – Louis Go Jun 25 '21 at 04:16
4

I am using boost 1.54, by which stage timed_join() is being deprecated. Depending upon your usage, you could use joinable() which works perfectly for my purposes, or alternatively you could use try_join_for() or try_join_until(), see:

http://www.boost.org/doc/libs/1_54_0/doc/html/thread/thread_management.html

2

You fundamentally can't do this. The reason is that the two possible answers are "Yes" and "Not when I last looked but perhaps now". There is no reliable way to determine that a thread is still inside its run method, even if there was a reliable way to determine the opposite.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 7
    You fundamentally _can_ do this. You can reliably query or "observe" the status of a thread at any given time. The problem is just that you cannot make any assumptions for interactions based upon the status you got back, meaning the moment you have the info "the thread is still running" it could already have been stopped in the time it took to get that information, but that is rarely critical. Sorry but this post was not in any way helpful. – AndreasT Jan 11 '10 at 14:36
  • @AndreasT: If you can not do any assumptions, how this could be useful? – Vicente Botet Escriba Oct 08 '13 at 17:01
0

This is a bit crude but as of now it's still working for my requirements. :) I'm using boost 153 and qt. I created a vector of int for tracking the "status" of my threads. Every time I create a new thread, I add one entry to thread_ids with a value of 0. For each thread created, I pass an ID so I know what part of thread_ids I'm supposed to update. Set the status to 1 for running and other values depending on what activity I am currently doing so I know what activity was being done when the thread ended. 100 is the value I set for a properly finished thread. I'm not sure if this will help but if you have other suggestions on how to improve on this let me know. :)

std::vector<int> thread_ids;
const int max_threads = 4;
void Thread01(int n, int n2)
{
    thread_ids.at(n) = 1;
    boost::this_thread::sleep(boost::posix_time::milliseconds(n2 * 1000));
    thread_ids.at(n) = 100;
    qDebug()<<"Done "<<n;

}
void getThreadsStatus()
{
    qDebug()<<"status:";
    for(int i = 0; i < max_threads, i < thread_ids.size(); i++)
    {
        qDebug()<<thread_ids.at(i);
    }
}
int main(int argc, char *argv[])
{
    for(int i = 0; i < max_threads; i++)
    {
        thread_ids.push_back(0);
        threadpool.create_thread(
            boost::bind(&boost::asio::io_service::run, &ioService));
        ioService.post(boost::bind(Thread01, i, i + 2));
        getThreadsStatus();
    }

    ioService.stop();
    threadpool.join_all();
    getThreadsStatus();
}
Adonai
  • 11
  • 1
0

The easiest way, if the function that is running your thread is simple enough, is to set a variable to true when the function is finished. Of course, you will need a variable per thread, if you have many a map of thread ids and status can be a better option. I know it is hand made, but it works fine in the meanwhile.

class ThreadCreator
{
private:
    bool            m_threadFinished;
    void launchProducerThread(){
        // do stuff here
        m_threadRunning = true;
    }
public:
    ThreadCreator() : m_threadFinished(false) {
        boost::thread(&Consumer::launchProducerThread, this);
    }
};
Blackzafiro
  • 235
  • 1
  • 5
  • 11
0

This may not be a direct answer to your question, but I see the thread concept as a really light-weight mechanism, and intentionally devoid of anything except synchronization mechanisms. I think that the right place to put "is running" is in the class that defines the thread function. Note that from a design perspective, you can exit the thread on interrupt and still not have your work completed. If you want to clean up the thread after it's completed, you can wrap it in a safe pointer and hand it to the worker class.

  • I believe it would be better if you clarify with code examples and divide your text in paragraphs to facilitate readability. – phaberest Feb 11 '16 at 19:20