Thread Synchronization Queue with Boost

Introduction

Currently I am working on a networking communication project and I am trying to develop it using C++ STL and boost. When developing a multi-thread program, synchronization is an important issue. If your program needs to process streaming packets, then maintaining a queue is a good idea.

Background

This is my first time using boost, it's not really easy to use because of a lack of good examples. You can find the boost library and documentation at http://www.boost.org/. Here is the advantage of using boost, taken from its website:

In a word, Productivity. Use of high-quality libraries like Boost speeds initial development, results in fewer bugs, reduces reinvention-of-the-wheel, and cuts long-term maintenance costs. And since Boost libraries tend to become de facto or de jure standards, many programmers are already familiar with them.

I am only using the boost synchronization class in this example but all the functions can be rewritten with boost and can be used in cross-platform development. The boost synchronization class looks straightforward but I still made some mistakes as a beginner, so I developed a test project to verify its functionality. After understanding how to use it, it will help you simplify the code and reduce bugs.

Using the Code

In this example, I implemented the thread synchronization model as producer-consumer. The producer thread creates data and inserts it into the queue and the consumer thread uses the data and deletes the data from the queue. I use a mutex object to keep the two threads synchronized.

I am trying to use different approaches to solve the same problem and then compare its advantages and disadvantages.

First I designed an interface to abstract the sync queue model. The ISynchronizedQueue abstract class has only have two methods: add() and get(). add() will be used in the producer thread to insert data into the queue and get() will be used in the consumer thread to acquire and remove data from the queue. There are three different implementations of this interface:

SynchronizedDequeue: is a double-ended queue, implemented with STL deque.

SychronizedVector: is a ring or cycle queue, implemented with STL vector.

SynchronizedDequeue has a dynamic queue size. The advantage is that if the producer is faster than the consumer, no data will escape, all the produced data will be processed by the consumer. The disadvantage is it has more impact on memory management performance. It will allocate memory when a packet is inserted into the queue, and release memory when we return the data to the consumer thread. Since there will be many times of memory allocation and deallocation, this may slow down the memory reclaim for bigger objects in the same process.

SychronizedVectorNB will not be blocked by either the producer or consumer thread. The advantage is that if there is some other activity needs to be done in the same loop of the queue access thread, then the non-block version will guarantee the response time.

The two queues above may block the thread when the thread tries to own the mutex object. If one thread owns the mutex and then some exception happens, the other thread will also be blocked. Its disadvantage is that it may fail in adding data to the queue when it fails to own the lock, the caller then needs to add the same data again.

In the test code, I create five producers, five consumers, and five queues. Each producer has its partner consumer linked by using the same queue. You can verify if each packet data produced is processed in order by consumer thread through its packet ID. You can define the LOG macro by yourself, I use a thread safe LOG macro with a log time output. With the log time you can see the thread performance more clearly.

After testing the three different sync queues with 5 producer-consumer threads pair and 1000 packets add and get each, their performances are basically same. The log itself will cost around 10 ms. You can modify it to see how the three types of queues perform in a larger data set, a longer running time, or with a big object memory allocation.

Points of Interest

It was kind of fun to use a little bit of the C++ boost library for the first time.

Share

About the Author

I started my career by developing Pattern Recognition application on windows and multiple mobile platforms. The Handwriting Recognition Software I took lead in development still help millions of senior Chinese people input information to computer today.

I have ever been working for Intel China Software Lab and IGT-CRDC for a period of time.

Now I am working on high precision 3D measuring and reconstruction devices. I am also developing 3D visualization software to process big point cloud.

I have been developing with C/C++,C#,MS-SQL,Java(Android),Python,Matlab and using frameworks like WPF/WCF,QT(Linux),C++ AMP/CUDA,OpenCV,PCL,VTK,Hoops. (BTW, Old fashioned tech like, Palm-OS, Symbian, Windows Mobile).