Flow-IPC 1.0.2
Flow-IPC project: Full implementation reference.
|
Modules for SHared Memory (SHM) support. More...
Namespaces | |
namespace | classic |
ipc::shm sub-module with the SHM-classic SHM-provider. See ipc::shm doc header for introduction. | |
namespace | stl |
ipc::shm sub-module providing integration between STL-compliant components (including containers) and SHared Memory (SHM) providers. | |
Classes | |
struct | Arena_to_borrower_allocator_arena |
Implementation of Arena_to_borrower_allocator_arena_t. More... | |
struct | Arena_to_borrower_allocator_arena< classic::Pool_arena > |
Implementation of Arena_to_borrower_allocator_arena_t for SHM-classic arenas. More... | |
Typedefs | |
template<typename Arena > | |
using | Arena_to_borrower_allocator_arena_t = typename Arena_to_borrower_allocator_arena< Arena >::Type |
Alias that, given an Arena type (with Arena::construct<T>() which allocates/constructs a T ), yields a Borrower_allocator_arena type which can be used as the Arena arg to stl::Stateless_allocator for the borrower-side counterpart T , usable in Shm_session::borrow_object<T>() to recover so-constructed objects. More... | |
Modules for SHared Memory (SHM) support.
At a high level ipc::shm is a collection of sub-modules, each known as a SHM-provider, as of this writing most prominently ipc::shm::classic and ipc::shm::arena_lend::jemalloc; plus provider-agnostic support for SHM-stored native-C++ STL-compliant data structures. See the doc headers for each sub-namespace for further information.
That said here's an overview.
Generally speaking there are two approaches to making use of ipc::shm:
While there are applications for approach 1, approach 2 is best by default. It makes the setup of a SHM environment far, far easier – it is essentially done for you, with many painful details such as naming and cleanup (whether after graceful exit or otherwise) taken care of without your input. Furthermore it standardizes APIs in such a way as to make it possible to swap between the available SHM-providers without changing code. (There are some exceptions to this; they are well explained in docs.)
Regardless of approach, you will need to choose which SHM-provider to use for your application. I (ygoldfel) would informally recommend looking at it from the angle of approach 2, as the ipc::session paradigm might clarify the high-level differences between the SHM-providers. I will now briefly describe and contrast the SHM-providers.
As of this writing there are two known types of SHM-providers: arena-sharing and arena-lending, of which only the latter is formalized in terms of its general properties.
Pool_arena
itself.malloc()
provider (memory manager): jemalloc. It could be applied to other memory managers; e.g., tcmalloc. (At the moment we feel jemalloc is easily the most performant and customizable open-source malloc()
er around.) Generally the memory-manager-agnostic aspects live in shm::arena_lend; while the SHM-jemalloc-specific ones go into shm::arena_lend::jemalloc. A major aspect of arena-lending SHM-providers is the separation of the the arena from the lend/borrow engine (SHM-session). (Those aspects live in session::shm::arena_lend and session::shm::arena_lend::jemalloc; again, the memory-manager-agnostic and -non-agnostic aspects respectively.) With an arena-lending SHM-provider, each of the two processes in a session creates/maintains its own arena, in which the other side cannot allocate; then via the session object the other side borrows an allocated object which it can at least read (but not deallocate; and by default not write-to). Thus process 1 maintains a Jemalloc-managed arena; process 2 borrows objects from it and reads them; and conversely process 2 maintains a Jemalloc-managed arena; process 1 borrows objects from it and reads them. Hence there are 2 process-local SHM-arenas and 1 SHM-session for bidirectional lending/borrowing.shm::classic is deliberately minimalistic. As a result it is very fast around setup (which involves, simply, an OS SHM-open operation on each side) and around lend/borrow time (when a process wants to share a SHM-stored datum with another process). The negatives are:
There are no particular plans to make shm::classic more sophisticated or to formalize its type ("arena-sharing") to be extensible to more variations. It fulfills its purpose; and in fact it may be suitable for many applications.
In contrast shm::arena_lend is sophisticated. A process creates an arena (or arenas); one can allocate objects in arenas. A real memory manager is in charge of the mechanics of allocation; except when it would normally just mmap()
a vaddr space for local heap use, it instead executes our internal hooks that mmap()
to a SHM-pool; SHM-pools are created and destroyed as needed.
The other process might do the same. It, thus, maintains its own memory manager, for allocations in SHM invoked from that process. Without further action, the two managers and the arenas they maintain are independent and only touched by their respective processes.
To be useful for IPC one would share the objects between the processes. To be able to do so, during setup each process establishes a SHM-session to the other process (multiple sessions if talking to multiple processes). Then one registers each local arena with a SHM-session; this means objects from that arena can be sent to the process on the opposing side of the SHM-session. From that point on, any object constructed in a given arena can be lent (sent) to any process on the opposing side of a session with which that given arena has been registered. This negates the negatives of SHM-classic:
malloc()
/new
/etc., then you can trust this equally.Lastly, as it stands, the arena-lending paradigm does lack one capability of SHM-classic; it is fairly advanced and may or may not come up as an actual problem:
Imagine long-lived application A and relatively short-lived application B, with (say) serially appearing/ending processes B1, B2, B3 in chronological order. A can allocate and fill an object X1 while B1 is alive; it will persist even after B1 dies and through B2 and B3; B1 through B3 can all read it. But can B1 itself do so?
The other major sub-module, as mentioned, is agnostic to the specific SHM-provider. It allows one to store complex native C++ data directly in SHM. Namely, arbitrary combinations of STL-compliant containers, struct
s, fixed-length arrays, scalars, and even pointers are supported. Both SHM-providers above (shm::classic and shm::arena_lend::jemalloc) provide the semantics required to correctly plug-in to this system. See doc header for namespace shm::stl to continue exploring this topic.
using ipc::shm::Arena_to_borrower_allocator_arena_t = typedef typename Arena_to_borrower_allocator_arena<Arena>::Type |
Alias that, given an Arena
type (with Arena::construct<T>()
which allocates/constructs a T
), yields a Borrower_allocator_arena
type which can be used as the Arena
arg to stl::Stateless_allocator for the borrower-side counterpart T
, usable in Shm_session::borrow_object<T>()
to recover so-constructed objects.
Informally, for informational convenience:
Arena
. Hence they will map Arena
to itself.Arena
to a different borrower-arena type only whose Pointer
type member shall be used.Arena | SHM arena type that has method of the form shared_ptr<T> construct<T>(...) . |