Search code examples
c++synchronizationipcboost-interprocess

Do these Boost::Interprocess components require synchronisation?


I am building a multi-producer/single-consumer application using IPC, implemented using Boost.Interprocess.

Each producer sends a message by allocating a block inside shared memory (managed_shared_memory::allocate), and marshalling an object into that block. Then, it sends a small object via a message_queue which holds the location (offset) of the block and the size.

The consumer receives this indicator from the queue and unmarshalls the object. The consumer is responsible for deallocating the block of memory.

Based on this implementation, I don't believe the objects or blocks as they exist in memory need synchronisation, because as soon as the consumer knows about them, the producer will no longer touch them. Therefore, I believe it is only the internals of message_queue and managed_shared_memory which need synchronisation.

My question is: Bearing in mind that each process is single-threaded, do allocate/deallocate, and send/receive calls need synchronisation?

The Boost examples provided by the documentation don't make use of synchronisation for the message queue, but I think this is only to simplify the sample source.


I have seen this question, but it is asking about thread-safety, and not about these specific components of Boost.Interprocess.


Solution

  • You do not need to use any kind of locking to protect these, operations. They are already protected using a recursive mutex in shared memory, otherwise multiple processes would not be able to operate in the same shared memory block at the same time.

    Regarding managed_shared_memory:

    One of the features of named/unique allocations/searches/destructions is that they are atomic. Named allocations use the recursive synchronization scheme defined by the internal mutex_family typedef defined of the memory allocation algorithm template parameter (MemoryAlgorithm). That is, the mutex type used to synchronize named/unique allocations is defined by the MemoryAlgorithm::mutex_family::recursive_mutex_type type. For shared memory, and memory mapped file based managed segments this recursive mutex is defined as boost::interprocess::interprocess_recursive_mutex.

    This also extends to raw allocation, you can verify this by looking at boost/interprocess/mem_algo/detail/simple_seq_fit.hpp.

    For message queue, boost::interprocess considers this to be a synchronization mechanism in the same way a mutex is, it will take care of all the necessary guarantees, locking its internal datastructures and issuing memory barriers as required.

    Furthermore this is all equally applicable to multithreaded programming. Even if you were calling send or allocate from multiple threads in the same program everything would be fine. The locking boost::interporcess provides would protect you from other threads in the same way it protects you from other processes.