...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Boost.Interprocess does not work only with processes but also with threads. Boost.Interprocess synchronization mechanisms can synchronize threads from different processes, but also threads from the same process.
In the traditional programming model an operating system has multiple processes running and each process has its own address space. To share information between processes we have several alternatives:
One of the biggest issues with interprocess communication mechanisms is the lifetime of the interprocess communication mechanism. It's important to know when an interprocess communication mechanism disappears from the system. In Boost.Interprocess, we can have 3 types of persistence:
Some native POSIX and Windows IPC mechanisms have different persistence so it's difficult to achieve portability between Windows and POSIX native mechanisms. Boost.Interprocess classes have the following persistence:
Table 18.1. Boost.Interprocess Persistence Table
Mechanism |
Persistence |
---|---|
Shared memory |
Kernel or Filesystem |
Memory mapped file |
Filesystem |
Process-shared mutex types |
Process |
Process-shared semaphore |
Process |
Process-shared condition |
Process |
File lock |
Process |
Message queue |
Kernel or Filesystem |
Named mutex |
Kernel or Filesystem |
Named semaphore |
Kernel or Filesystem |
Named condition |
Kernel or Filesystem |
As you can see, Boost.Interprocess defines some mechanisms with "Kernel or Filesystem" persistence. This is because POSIX allows this possibility to native interprocess communication implementations. One could, for example, implement shared memory using memory mapped files and obtain filesystem persistence (for example, there is no proper known way to emulate kernel persistence with a user library for Windows shared memory using native shared memory, or process persistence for POSIX shared memory, so the only portable way is to define "Kernel or Filesystem" persistence).
Some interprocess mechanisms are anonymous objects created in shared memory or memory-mapped files but other interprocess mechanisms need a name or identifier so that two unrelated processes can use the same interprocess mechanism object. Examples of this are shared memory, named mutexes and named semaphores (for example, native windows CreateMutex/CreateSemaphore API family).
The name used to identify an interprocess mechanism is not portable, even between UNIX systems. For this reason, Boost.Interprocess limits this name to a C++ variable identifier or keyword:
Named Boost.Interprocess resources (shared
memory, memory mapped files, named mutexes/conditions/semaphores) have kernel
or filesystem persistency. This means that even if all processes that have
opened those resources end, the resource will still be accessible to be opened
again and the resource can only be destructed via an explicit call to their
static member remove
function.
This behavior can be easily understood, since it's the same mechanism used
by functions controlling file opening/creation/erasure:
Table 18.2. Boost.Interprocess-Filesystem Analogy
Named Interprocess resource |
Corresponding std file |
Corresponding POSIX operation |
---|---|---|
Constructor |
std::fstream constructor |
open |
Destructor |
std::fstream destructor |
close |
Member |
None. |
unlink |
Now the correspondence between POSIX and Boost.Interprocess regarding shared memory and named semaphores:
Table 18.3. Boost.Interprocess-POSIX shared memory
|
POSIX operation |
---|---|
Constructor |
shm_open |
Destructor |
close |
Member |
shm_unlink |
Table 18.4. Boost.Interprocess-POSIX named semaphore
|
POSIX operation |
---|---|
Constructor |
sem_open |
Destructor |
close |
Member |
sem_unlink |
The most important property is that destructors of
named resources don't remove the resource from the system, they
only liberate resources allocated by the system for use by the process for
the named resource. To remove the resource from the
system the programmer must use remove
.
Named resources offered by Boost.Interprocess must cope with platform-dependant permission issues also present when creating files. If a programmer wants to shared shared memory, memory mapped files or named synchronization mechanisms (mutexes, semaphores, etc...) between users, it's necessary to specify those permissions. Sadly, traditional UNIX and Windows permissions are very different and Boost.Interprocess does not try to standardize permissions, but does not ignore them.
All named resource creation functions take an optional permissions
object
that can be configured with platform-dependant permissions.
Since each mechanism can be emulated through different mechanisms (a semaphore
might be implement using mapped files or native semaphores) permissions types
could vary when the implementation of a named resource changes (eg.: in Windows
mutexes require synchronize permissions
, but that's not the case of
files). To avoid this, Boost.Interprocess
relies on file-like permissions, requiring file read-write-delete permissions
to open named synchronization mechanisms (mutex, semaphores, etc.) and appropriate
read or read-write-delete permissions for shared memory. This approach has
two advantages: it's similar to the UNIX philosophy and the programmer does
not need to know how the named resource is implemented.