Pages

Running a deamon thread

You probably know what a deamon process is: a process running in the background in your (UNIX) environment. A deamon thread is something very similar: a thread running in the background of your process.

We have a way to interact with a "normal" thread from the main thread that spawned it, but we have no way to relate to a deamon thread - it just runs freely until its natural end, or till the process is terminated.

One could wonder what is the point of having such a beast as a deamon thread, but here it comes handy the analogy with the deamon process. In the same way we sometimes want to start running a process in our environment and just forget about it, letting the operating system the burden to take care of it, we could be interested in having a job performed in the background of our application, letting the process taking care of it, if someone has to.

We can get this effect creating a boost::thread (or a std::thread, if your compiler support this C++11 feature) and then detach the generated thread. It is a simple matter, but better seeing it in an example, just to clarify.

This is the code that we want to run in a background thread:
void countdown(unsigned int count)
{
   do {
      std::cout << '[' << count << ']';
      boost::this_thread::sleep(boost::posix_time::seconds(1));
   } while(count--);
}
As you see, it just dumps data on the standard output console, sleeps for a while, and then iterates, for a number of times specified by the caller. We should notice that we could have some problem in the output generation since we could expect the main thread would write to cout too, so a mutex should be used for this shared resource - but we won't.

Here is the code that is going to use the countdown function:
boost::thread t(countdown, 10);

if(t.joinable()) // 1
{
   std::cout << "Detaching worker.";
   t.detach(); // 2
}

if(t.joinable() == false) // 3
{
   std::cout << "The worker thread now is a deamon, running by itself in background.";
}

std::cout << "Sleeping for a while ... ";
boost::this_thread::sleep(boost::posix_time::seconds(3));
std::cout << " ... terminating main." << std::endl; // 4
1. We should detach only a boost::thread that is alive and kicking or, as they better say, is joinable.
2. That's it. We simply call detach() on the boost::thead object. Actually, no much harm comes if we detach a thread not joinable. It would just result in a silly nonsensical call.
3. The consequent printing it's a bit too optimistic. If a boost::thread is not joinable we can't positively assume that it is still alive and working in the background. It could be anything. We don't have any information on it anymore.
4. Usually we should join all the spawned threads before terminating the main thread, but here we can't. As we said, we have no more control on that working thread. We should just assume that has been written properly and no issue would come from its possible brutal killing from the process manager at the end of the process life.

2 comments:

  1. This is incorrect. detached threads will also terminate once main terminates.

    ReplyDelete
    Replies
    1. Hello Rajat, thank you for give me a way to clarify what I have written.

      You are right, if a detached thread is still alive when all the user threads are completed, it is terminated automatically. Actually, the point in creating a deamon is making clear that we want that thread running freely until the end of the process.

      The difference between a user (not detached) thread and a deamon (detached thread) is that we don't join the latter to wait its termination. We could call join on a deamon, but that call won't have any effect. It will return immediately, and the deamon thread will still be alive.

      Please, let me know if it is a specific sentence in the post that looks misleading to you, so that I can rewrite it better.

      Delete