1

In C++, I have this sample implementation:

#include <thread>
#include <iostream>

void doSomeWork( void )
{
    std::cout << "hello from thread..." << std::endl;
    while(true)
    {
       printf("Getting inside doSomeWork\n");
       sleep(1);
    }
}

int main( int argc, char *argv[] )
{
    std::thread t( doSomeWork );
    t.join();

    processing();

    return 0;
}

void processing()
{
   while(true)
   {
      printf("Getting inside processing\n");
      sleep(1);
   }
}

I have a problem that doSomeWork() keep doing things and it block processing(). I thought thread is asynchronous so that while it is sleeping, I can other things. My question here is how can I sleep in doSomeWork() and yield other threads, then resume doSomework()?

halfer
  • 19,824
  • 17
  • 99
  • 186
olidev
  • 20,058
  • 51
  • 133
  • 197
  • 2
    What did you expect when you're *joining* the thread doing `doSomeWork`, making your main thread block until `doSomeWork` returns? – Anton Kovalenko Feb 22 '13 at 15:23

2 Answers2

6

The line

t.join();

pauses the calling thread until thread t completes (when doSomeWork()) returns.

Change your code to

std::thread t( doSomeWork );
processing();
t.join();

if you want processing() and doSomeWork() to run in parallel.

simonc
  • 41,632
  • 12
  • 85
  • 103
2

replace t.join(); with t.detach();

Note however, detach means something like "I'm not interesting in this thread, so it may be terminated in any time" or "I will synchronize the thread by some sync mechanism". Basically it is used when you have some external(to the thread) sync mechanism so you don't want to use join. It is common to use join every time but use detach only when needed. In your particular case you have sync mechanism with forever loop, so it is absolutely fine to use detach but be aware about their differences.

ixSci
  • 13,100
  • 5
  • 45
  • 79
  • 1
    since processing() runs forever, this is fine. However be careful if processing() would have ended, you end up with a race condition of main() ending before the thread did anything at all. – hetepeperfan Feb 22 '13 at 15:43
  • 1
    This is wrong. There is no need to detach(). In fact I think that is counter productive as it releases the native thread from control of the object. Really you should just move `t.join();` to the other side of `processing();`. Once the main thread exists it will kill all other threads (even of they are not finished, the use of join() is to prevent this). – Martin York Feb 22 '13 at 16:28
  • @Loki, there is nothing wrong here. Detach is as legit as join operation for some contexts. This context is a good choice for the detach. Join is useless and redundant here. – ixSci Feb 22 '13 at 17:10
  • 1
    @ixSci: In that context `detach()` is useless an redundant here. If you remove the `detach()` the code works just as well. Yet your object still maintains control of the thread. Thus this is wrong. – Martin York Feb 22 '13 at 17:12
  • @Loki, you have forever loop which guarantees main will not finish before other thread, so it is absolutely safe to detach it. And detach is here because you have to either detach or join, and you don't need to join since you have other sync mechanism(forever loop). Besides detach is more simple operation. So I don't see any point to use join here. – ixSci Feb 22 '13 at 17:18
  • 1
    You are **obviously** confused about what detach() does. There is no need to detach. The thread is already running. detach() removes the native thread from the c++ object. It has no other affect. There is no need to detach as the thread is already running and executing `doSomeWork()`. As for calling join. It is still the correct thing to do as the code has to be maintained. Not calling join leads to problems when you do alter processing so it does not loop for ever. So this answer is still wrong. – Martin York Feb 22 '13 at 19:09
  • @Loki, I'm not confused. You **have to** either join or detach, if you don't - you will have `std::terminate` called in thread destructor. That is it. C++ API for thread **requires** to do either detach or join. And your point about join is still not convincing. You are repeating it like mantra and you still have provided no real argument why detach is wrong here. – ixSci Feb 23 '13 at 03:11
  • @ixSci: Correct you seem not to be confused just completely wrong. Please read the API again. You can find its definition in the standard. See here: http://stackoverflow.com/a/4653479/14065 – Martin York Feb 23 '13 at 06:25
  • @Loki, I'm tired from you. `30.3.1.3 ~thread(); If joinable(), calls std::terminate(). Otherwise, has no effects.` – ixSci Feb 23 '13 at 06:30
  • Ok, let's start. While C++ standard doesn't state that `delete` statement is mandatory for pointers allocated with `new` it doesn't mean you don't have to call it. It should be like reflex, you should alway call `delete` if you called `new`. The same is with detach/join. They are different, join is another sync mechanism while detach means "I know what I'm doing", and it basically means that you either have some other sync mechanism or you just doesn't matter if thread will be forced you quit before it is done. That is all. – ixSci Feb 23 '13 at 08:49
  • I agree that `join` is more common solution but it doesn't make `detach` marginal. It just another solution. And your statement about "dtor do nothing after thread function is finished" is simply **wrong** I don't see any proofs in standard. And 3 major compilers **do terminate**. Check it out http://liveworkspace.org/code/38nxOa$1 – ixSci Feb 23 '13 at 08:51
  • @ixSci: There is no **requires to do either detach or join**. That is just false. The quote you have is correct. But `joinable()` simply means if the thread is still running. When the function provided to the std::thread object finishes the thread of execution dies and the std::thread object is now `joinable`. (ie there is no requirement to call join (or detach)). – Martin York Feb 23 '13 at 08:56
  • A call to `detch()` on the other hand simply releases the thread of execution from the std::thread object. This has no benefits and the down side is that yo u can no longer communicate with the thread or test its state. Note: Not being able to communicate with the thread or test its state is a real problem. As you have to make sure that all threads exit before the main thread exits `int main()`. – Martin York Feb 23 '13 at 08:57
  • When the main thread finishes execution of `main()` (and tidies up a tiny bit) the application is repeated by the OS. This stops all other threads of execution dead. Any objects in these thread cease to exist and their destructors are **NOT** called. This is just a resource leak waiting to happen. What you want to do is keep the thread of execution associated with the std::thread object so you can call `join()` to make sure it is finished and/or send it signal to make it exit quickly. – Martin York Feb 23 '13 at 08:58
  • I hope that was succinct enough to show that calling detach() is the wrong answer. – Martin York Feb 23 '13 at 08:58
  • I may have `conditional_variable` to sync my resource and do not use join. There are cases for that. OP has forever loop for sync so he doesn't need join. – ixSci Feb 23 '13 at 08:59
  • I see no condition variables. And relying on the code never to change is just not pheasbale in a real world application. Code changes and thus you must plan for the worst thus the correct solution is to join. Even if you don't join and rely on the looping forever there is no need to detach(). Just comment out the join() in the original question and the code will work as OP expected it to. detach() is the wrong solution to this problem. – Martin York Feb 23 '13 at 09:03
  • But I think your have demonstrated will your inability to understand the API in both what detach() and the destructor is actually doing. – Martin York Feb 23 '13 at 09:04
  • I don't agree that it is wrong nor do I want continue this argument. OP has enough comments to my answer to choose the right solution for himself. – ixSci Feb 23 '13 at 09:05
  • @ixSci: You don't understand that the call to `detach()` is just redundant in this context! And bad in the general context of threading (especially for beginners (unless you provide an alternative to control the lifespan of the thread)). – Martin York Feb 23 '13 at 09:08
  • No, I don't understand. And C++ standard with GCC, MSVC and clang don't understand either. It is good that you understand all the things. You are deleting your comments, rearranging them and delete info from them so I don't want to talk with you anymore. It becomes absolutely useless. – ixSci Feb 23 '13 at 09:10
  • @ixSci: Well the standard is on my side and not yours. Your misinterpretation of the API twice so far has shown that. Going back to you new/delete example. Yes you can use detach() but it is the equivalent of creating std::vector then detaching the underlying memory from the vector. In both situation you want to add extra code to make sure the resource is cleanly returned to the OS otherwise their are horrible side affects. It is a useful advanced technique. But in the context of the question a completely silly idea that leads to lots of other problems. Thus as I have said the answer is wrong. – Martin York Feb 23 '13 at 17:02