MechaTechnica

Accelerating the advancement of Artificial Intelligence for the advancement of humankind
Boost Thread vs C++ 11 Thread
Introduction
While C++ 11 borrowed a lot of the implementation from boost.thread, several important differences exist between the two. This article shows the differences between the two implementations and the pitfalls you should avoid.

Lifetime
A quick mention about the lifetime of a thread object and thread execution is necessary.

First, when a thread is started, two possibilities exist:
  1. The thread is finished before join() is called- in this case, the executing thread will no longer exist; however, its object could still be alive
  2. The thread object will cease to exist before the thread execution ends- in this case, the thread will continue executing even if its object is deleted
Therefore, it is important to realize the difference between the thread object and the thread that is executing. The thread object is simply a wrapper to the operating system calls that will eventually take place. Do not worry about memory leaks if the thread object is deleted before the thread execution ends. 

Simply, ensure that your executing thread is 'thread safe'; that is:
  • The executing thread deals with race conditions 'properly'
  • There are no deadlocks
If the thread object is deleted before the thread execution is finished, the thread becomes "detached". This means, there is no way to synchronize with your main() thread.

Auto Join vs Manual Join
I would like to just point one of the minor differences between C++ 11 and Boost. Examine the following C++ 11 code:
#include<iostream>
#include<thread>

using namespace std;

void my_func()
{
 cout<<"executing: "<<__FUNCTION__<<endl;
}

int main()
{
 thread t= std::thread(my_func);
 //you must call join; this program will throw an exception and terminate() will be called
 //t.join();  
 return 0;
}
The code above will throw an exception when you run it. Unlike Boost, you must call join() in C++ 11. Why? Because the C++ committee agreed that auto-joining a join-able thread inside the destructor could lead to a very difficult to debug program, so they make you the programmer, join the thread explicitly.

Create and forget threads
Lets just say you are interested in creating a thread and you don't care about when it will join. 

Here's how we would do this in C++ 11:
#include<iostream>
#include<thread>
#include<condition_variable>

std::mutex m;
std::condition_variable cv;

void my_func()
{
 std::cout<<"executing: "<<__FUNCTION__<<std::endl;
 std::cout<<"We have "<<std::thread::hardware_concurrency()<<" cores availble to go crazy with threads"<<std::endl;
 std::cout<<"sleeping "<<2000<<" milliseconds before signaling main"<<std::endl;
 std::this_thread::sleep_for(std::chrono::milliseconds(2000));
 cv.notify_one(); //signal the main thread to proceed
}

int main()
{
 std::thread(my_func).detach(); //no need for join any more
 //but now we risk exiting the program before the thread is finished
 std::unique_lock<std::mutex> lk(m);
 cv.wait(lk);
 std::cout<<"Main thread exit: "<<std::endl;
 return 0;
}
In the above code, we notice we have no handle to our thread object and thus cannot call join(). The immediate problem we face now is a race condition. Will main finish before or after our thread? Luckily, we have condition_variable in C++ 11.

Therefore, we:
  • Start the thread my_func
  • Main blocks and waits for my my_func to signal
  • my_func signals and main proceeds exiting normally
Difference between C++ thread and boost thread
A few years ago we could highlight several differences between boost.thread and C++ 11 threads. Between 2011 and 2014, Boost.Thread class has been modified to be similar to the standard. We can find very little differences if we compare the two [4][5]. Indeed, it seem the reverse has happened, C++ 11 has influenced changes in Boost.

Choosing between Boost and C++ 11 threads in a production environment
Not all compilers support C++ 11. After all, its far easier to use std::thread than including the entire boost library in your repositories; plus, those would have to be updated every once in while. For those compilers that only support Boost, you might be wondering:
  • Could I install Boost.Thread only and not the entire boost package? Answer yes. You can choose with features of Boost to install and if you want just threads, you get just threads
  • Do I have to link statically or dynamically with Boost? Answer both are available. You can choose to link statically or dynamically. With Boost, you can build static or dynamic libraries during installation
  • Are there any performance differences? Answer no. They both should compare equally in performance timings. I personally have not seen any differences between the two
  • Will there be major refactoring if my compiler support C++ 11 in the future and I decide to switch to it? Answer not really. Going back to the earlier discussion, a lot of effort has been put in Boost to make it similar to C++ 11 so refactoring would be minimal at best
Conclusion
I hope this short intro to C++ 11 and Boost threads has given you a better view about which to choose in your development or may be you knew most of this already and would like more depth to this article. If you would like more depth or have other opinions about this article, please write in the comments below. Thanks for reading!

References
[1] http://www.boost.org/doc/libs/1_31_0/libs/thread/doc/thread.html
[2] http://www.justsoftwaresolutions.co.uk/files/designing_mt_programs.pdf
[3] http://en.cppreference.com/w/cpp/thread/condition_variable
[4] http://www.boost.org/doc/libs/1_55_0/doc/html/thread/thread_management.html#thread.thread_management.synopsis
[5] http://www.cplusplus.com/reference/thread/thread/

Article Owner: RobertoOrellana

Article Creation Date: 7/12/2015 12:00:00 AM

Tags: No server implementation yet

Rating: 0

Rate this article!
comments powered by Disqus