| <html> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> |
| <title>Architecture and internals</title> |
| <link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css"> |
| <meta name="generator" content="DocBook XSL Stylesheets V1.76.1"> |
| <link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset"> |
| <link rel="up" href="../interprocess.html" title="Chapter 10. Boost.Interprocess"> |
| <link rel="prev" href="interprocess_smart_ptr.html" title="Ownership smart pointers"> |
| <link rel="next" href="customizing_interprocess.html" title="Customizing Boost.Interprocess"> |
| </head> |
| <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> |
| <table cellpadding="2" width="100%"><tr> |
| <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td> |
| <td align="center"><a href="../../../index.html">Home</a></td> |
| <td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td> |
| <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> |
| <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> |
| <td align="center"><a href="../../../more/index.htm">More</a></td> |
| </tr></table> |
| <hr> |
| <div class="spirit-nav"> |
| <a accesskey="p" href="interprocess_smart_ptr.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../interprocess.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="customizing_interprocess.html"><img src="../../../doc/src/images/next.png" alt="Next"></a> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h2 class="title" style="clear: both"> |
| <a name="interprocess.architecture"></a><a class="link" href="architecture.html" title="Architecture and internals">Architecture and internals</a> |
| </h2></div></div></div> |
| <div class="toc"><dl> |
| <dt><span class="section"><a href="architecture.html#interprocess.architecture.basic_guidelines">Basic guidelines</a></span></dt> |
| <dt><span class="section"><a href="architecture.html#interprocess.architecture.architecture_algorithm_to_managed">From the memory algorithm to the managed segment</a></span></dt> |
| <dt><span class="section"><a href="architecture.html#interprocess.architecture.allocators_containers">Allocators and containers</a></span></dt> |
| <dt><span class="section"><a href="architecture.html#interprocess.architecture.performance">Performance of Boost.Interprocess</a></span></dt> |
| </dl></div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="interprocess.architecture.basic_guidelines"></a><a class="link" href="architecture.html#interprocess.architecture.basic_guidelines" title="Basic guidelines">Basic guidelines</a> |
| </h3></div></div></div> |
| <p> |
| When building <span class="bold"><strong>Boost.Interprocess</strong></span> architecture, I took some basic guidelines that can be |
| summarized by these points: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> should be portable at least in UNIX and Windows systems. That |
| means unifying not only interfaces but also behaviour. This is why |
| <span class="bold"><strong>Boost.Interprocess</strong></span> has chosen kernel or filesystem persistence for shared memory |
| and named synchronization mechanisms. Process persistence for shared memory is also |
| desirable but it's difficult to achieve in UNIX systems. |
| </li> |
| <li class="listitem"> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> inter-process synchronization primitives should be equal to thread |
| synchronization primitives. <span class="bold"><strong>Boost.Interprocess</strong></span> aims to have an interface compatible |
| with the C++ standard thread API. |
| </li> |
| <li class="listitem"> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> architecture should be modular, customizable but efficient. That's |
| why <span class="bold"><strong>Boost.Interprocess</strong></span> is based on templates and memory algorithms, index types, |
| mutex types and other classes are templatizable. |
| </li> |
| <li class="listitem"> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> architecture should allow the same concurrency as thread based |
| programming. Different mutual exclusion levels are defined so that a process |
| can concurrently allocate raw memory when expanding a shared memory vector while another |
| process can be safely searching a named object. |
| </li> |
| <li class="listitem"> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> containers know nothing about <span class="bold"><strong>Boost.Interprocess</strong></span>. All specific |
| behaviour is contained in the STL-like allocators. That allows STL vendors to slightly |
| modify (or better said, generalize) their standard container implementations and obtain |
| a fully std::allocator and boost::interprocess::allocator compatible container. This also |
| make <span class="bold"><strong>Boost.Interprocess</strong></span> containers compatible with standard algorithms. |
| </li> |
| </ul></div> |
| <p> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> is built above 3 basic classes: a <span class="bold"><strong>memory algorithm</strong></span>, a |
| <span class="bold"><strong>segment manager</strong></span> and a <span class="bold"><strong>managed memory segment</strong></span>: |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="interprocess.architecture.architecture_algorithm_to_managed"></a><a class="link" href="architecture.html#interprocess.architecture.architecture_algorithm_to_managed" title="From the memory algorithm to the managed segment">From the memory algorithm to the managed segment</a> |
| </h3></div></div></div> |
| <div class="toc"><dl> |
| <dt><span class="section"><a href="architecture.html#interprocess.architecture.architecture_algorithm_to_managed.architecture_memory_algorithm">The memory algorithm</a></span></dt> |
| <dt><span class="section"><a href="architecture.html#interprocess.architecture.architecture_algorithm_to_managed.architecture_segment_manager">The segment manager</a></span></dt> |
| <dt><span class="section"><a href="architecture.html#interprocess.architecture.architecture_algorithm_to_managed.architecture_managed_memory">Boost.Interprocess managed memory segments</a></span></dt> |
| </dl></div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.architecture.architecture_algorithm_to_managed.architecture_memory_algorithm"></a><a class="link" href="architecture.html#interprocess.architecture.architecture_algorithm_to_managed.architecture_memory_algorithm" title="The memory algorithm">The memory algorithm</a> |
| </h4></div></div></div> |
| <p> |
| The <span class="bold"><strong>memory algorithm</strong></span> is an object that is placed in the first bytes of a |
| shared memory/memory mapped file segment. The <span class="bold"><strong>memory algorithm</strong></span> can return |
| portions of that segment to users marking them as used and the user can return those |
| portions to the <span class="bold"><strong>memory algorithm</strong></span> so that the <span class="bold"><strong>memory algorithm</strong></span> mark them as free |
| again. There is an exception though: some bytes beyond the end of the memory |
| algorithm object, are reserved and can't be used for this dynamic allocation. |
| This "reserved" zone will be used to place other additional objects |
| in a well-known place. |
| </p> |
| <p> |
| To sum up, a <span class="bold"><strong>memory algorithm</strong></span> has the same mission as malloc/free of |
| standard C library, but it just can return portions of the segment |
| where it is placed. The layout of a memory segment would be: |
| </p> |
| <pre class="programlisting"><span class="identifier">Layout</span> <span class="identifier">of</span> <span class="identifier">the</span> <span class="identifier">memory</span> <span class="identifier">segment</span><span class="special">:</span> |
| <span class="identifier">____________</span> <span class="identifier">__________</span> <span class="identifier">____________________________________________</span> |
| <span class="special">|</span> <span class="special">|</span> <span class="special">|</span> <span class="special">|</span> |
| <span class="special">|</span> <span class="identifier">memory</span> <span class="special">|</span> <span class="identifier">reserved</span> <span class="special">|</span> <span class="identifier">The</span> <span class="identifier">memory</span> <span class="identifier">algorithm</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">portions</span> <span class="special">|</span> |
| <span class="special">|</span> <span class="identifier">algorithm</span> <span class="special">|</span> <span class="special">|</span> <span class="identifier">of</span> <span class="identifier">the</span> <span class="identifier">rest</span> <span class="identifier">of</span> <span class="identifier">the</span> <span class="identifier">segment</span><span class="special">.</span> <span class="special">|</span> |
| <span class="special">|</span><span class="identifier">____________</span><span class="special">|</span><span class="identifier">__________</span><span class="special">|</span><span class="identifier">____________________________________________</span><span class="special">|</span> |
| </pre> |
| <p> |
| The <span class="bold"><strong>memory algorithm</strong></span> takes care of memory synchronizations, just like malloc/free |
| guarantees that two threads can call malloc/free at the same time. This is usually |
| achieved placing a process-shared mutex as a member of the memory algorithm. Take |
| in care that the memory algorithm knows <span class="bold"><strong>nothing</strong></span> about the segment (if it is |
| shared memory, a shared memory file, etc.). For the memory algorithm the segment |
| is just a fixed size memory buffer. |
| </p> |
| <p> |
| The <span class="bold"><strong>memory algorithm</strong></span> is also a configuration point for the rest of the |
| <span class="bold"><strong>Boost.Interprocess</strong></span> |
| framework since it defines two basic types as member typedefs: |
| </p> |
| <pre class="programlisting"><span class="keyword">typedef</span> <span class="comment">/*implementation dependent*/</span> <span class="identifier">void_pointer</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="comment">/*implementation dependent*/</span> <span class="identifier">mutex_family</span><span class="special">;</span> |
| </pre> |
| <p> |
| The <code class="computeroutput"><span class="identifier">void_pointer</span></code> typedef defines the pointer type that will be used in the |
| <span class="bold"><strong>Boost.Interprocess</strong></span> framework (segment manager, allocators, containers). If the memory |
| algorithm is ready to be placed in a shared memory/mapped file mapped in different base |
| addresses, this pointer type will be defined as <code class="computeroutput"><span class="identifier">offset_ptr</span><span class="special"><</span><span class="keyword">void</span><span class="special">></span></code> or a similar relative |
| pointer. If the <span class="bold"><strong>memory algorithm</strong></span> will be used just with fixed address mapping, |
| <code class="computeroutput"><span class="identifier">void_pointer</span></code> can be defined as <code class="computeroutput"><span class="keyword">void</span><span class="special">*</span></code>. |
| </p> |
| <p> |
| The rest of the interface of a <span class="bold"><strong>Boost.Interprocess</strong></span> <span class="bold"><strong>memory algorithm</strong></span> is described in |
| <a class="link" href="customizing_interprocess.html#interprocess.customizing_interprocess.custom_interprocess_alloc" title="Writing a new shared memory allocation algorithm">Writing a new shared memory allocation algorithm</a> |
| section. As memory algorithm examples, you can see the implementations |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/simple_seq_fit.html" title="Class template simple_seq_fit">simple_seq_fit</a></code> or |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/rbtree_best_fit.html" title="Class template rbtree_best_fit">rbtree_best_fit</a></code> classes. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.architecture.architecture_algorithm_to_managed.architecture_segment_manager"></a><a class="link" href="architecture.html#interprocess.architecture.architecture_algorithm_to_managed.architecture_segment_manager" title="The segment manager">The segment manager</a> |
| </h4></div></div></div> |
| <p> |
| The <span class="bold"><strong>segment manager</strong></span>, is an object also placed in the first bytes of the |
| managed memory segment (shared memory, memory mapped file), that offers more |
| sophisticated services built above the <span class="bold"><strong>memory algorithm</strong></span>. How can <span class="bold"><strong>both</strong></span> the |
| segment manager and memory algorithm be placed in the beginning of the segment? |
| That's because the segment manager <span class="bold"><strong>owns</strong></span> the memory algorithm: The |
| truth is that the memory algorithm is <span class="bold"><strong>embedded</strong></span> in the segment manager: |
| </p> |
| <pre class="programlisting"><span class="identifier">The</span> <span class="identifier">layout</span> <span class="identifier">of</span> <span class="identifier">managed</span> <span class="identifier">memory</span> <span class="identifier">segment</span><span class="special">:</span> |
| <span class="identifier">_______</span> <span class="identifier">_________________</span> |
| <span class="special">|</span> <span class="special">|</span> <span class="special">|</span> <span class="special">|</span> |
| <span class="special">|</span> <span class="identifier">some</span> <span class="special">|</span> <span class="identifier">memory</span> <span class="special">|</span> <span class="identifier">other</span> <span class="special">|<-</span> <span class="identifier">The</span> <span class="identifier">memory</span> <span class="identifier">algorithm</span> <span class="identifier">considers</span> |
| <span class="special">|</span><span class="identifier">members</span><span class="special">|</span><span class="identifier">algorithm</span><span class="special">|</span><span class="identifier">members</span><span class="special">|</span> <span class="string">"other members"</span> <span class="identifier">as</span> <span class="identifier">reserved</span> <span class="identifier">memory</span><span class="special">,</span> <span class="identifier">so</span> |
| <span class="special">|</span><span class="identifier">_______</span><span class="special">|</span><span class="identifier">_________</span><span class="special">|</span><span class="identifier">_______</span><span class="special">|</span> <span class="identifier">it</span> <span class="identifier">does</span> <span class="keyword">not</span> <span class="identifier">use</span> <span class="identifier">it</span> <span class="keyword">for</span> <span class="identifier">dynamic</span> <span class="identifier">allocation</span><span class="special">.</span> |
| <span class="special">|</span><span class="identifier">_________________________</span><span class="special">|</span><span class="identifier">____________________________________________</span> |
| <span class="special">|</span> <span class="special">|</span> <span class="special">|</span> |
| <span class="special">|</span> <span class="identifier">segment</span> <span class="identifier">manager</span> <span class="special">|</span> <span class="identifier">The</span> <span class="identifier">memory</span> <span class="identifier">algorithm</span> <span class="identifier">will</span> <span class="keyword">return</span> <span class="identifier">portions</span> <span class="special">|</span> |
| <span class="special">|</span> <span class="special">|</span> <span class="identifier">of</span> <span class="identifier">the</span> <span class="identifier">rest</span> <span class="identifier">of</span> <span class="identifier">the</span> <span class="identifier">segment</span><span class="special">.</span> <span class="special">|</span> |
| <span class="special">|</span><span class="identifier">_________________________</span><span class="special">|</span><span class="identifier">____________________________________________</span><span class="special">|</span> |
| </pre> |
| <p> |
| The <span class="bold"><strong>segment manager</strong></span> initializes the memory algorithm and tells the memory |
| manager that it should not use the memory where the rest of the |
| <span class="bold"><strong>segment manager</strong></span>'s member are placed for dynamic allocations. The |
| other members of the <span class="bold"><strong>segment manager</strong></span> are <span class="bold"><strong>a recursive mutex</strong></span> |
| (defined by the memory algorithm's <span class="bold"><strong>mutex_family::recursive_mutex</strong></span> typedef member), |
| and <span class="bold"><strong>two indexes (maps)</strong></span>: one to implement named allocations, and another one to |
| implement "unique instance" allocations. |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| The first index is a map with a pointer to a c-string (the name of the named object) |
| as a key and a structure with information of the dynamically allocated object |
| (the most important being the address and the size of the object). |
| </li> |
| <li class="listitem"> |
| The second index is used to implement "unique instances" |
| and is basically the same as the first index, |
| but the name of the object comes from a <code class="computeroutput"><span class="keyword">typeid</span><span class="special">(</span><span class="identifier">T</span><span class="special">).</span><span class="identifier">name</span><span class="special">()</span></code> operation. |
| </li> |
| </ul></div> |
| <p> |
| The memory needed to store [name pointer, object information] pairs in the index is |
| allocated also via the <span class="bold"><strong>memory algorithm</strong></span>, so we can tell that internal indexes |
| are just like ordinary user objects built in the segment. The rest of the memory |
| to store the name of the object, the object itself, and meta-data for |
| destruction/deallocation is allocated using the <span class="bold"><strong>memory algorithm</strong></span> in a single |
| <code class="computeroutput"><span class="identifier">allocate</span><span class="special">()</span></code> call. |
| </p> |
| <p> |
| As seen, the <span class="bold"><strong>segment manager</strong></span> knows <span class="bold"><strong>nothing</strong></span> about shared memory/memory mapped files. |
| The <span class="bold"><strong>segment manager</strong></span> itself does not allocate portions of the segment, |
| it just asks the <span class="bold"><strong>memory algorithm</strong></span> to allocate the needed memory from the rest |
| of the segment. The <span class="bold"><strong>segment manager</strong></span> is a class built above the memory algorithm |
| that offers named object construction, unique instance constructions, and many |
| other services. |
| </p> |
| <p> |
| The <span class="bold"><strong>segment manager</strong></span> is implemented in <span class="bold"><strong>Boost.Interprocess</strong></span> by |
| the <code class="computeroutput"><a class="link" href="../boost/interprocess/segment_manager.html" title="Class template segment_manager">segment_manager</a></code> class. |
| </p> |
| <pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">CharType</span> |
| <span class="special">,</span><span class="keyword">class</span> <span class="identifier">MemoryAlgorithm</span> |
| <span class="special">,</span><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">IndexConfig</span><span class="special">></span> <span class="keyword">class</span> <span class="identifier">IndexType</span><span class="special">></span> |
| <span class="keyword">class</span> <span class="identifier">segment_manager</span><span class="special">;</span> |
| </pre> |
| <p> |
| As seen, the segment manager is quite generic: we can specify the character type |
| to be used to identify named objects, we can specify the memory algorithm that will |
| control dynamically the portions of the memory segment, and we can specify |
| also the index type that will store the [name pointer, object information] mapping. |
| We can construct our own index types as explained in |
| <a class="link" href="customizing_interprocess.html#interprocess.customizing_interprocess.custom_indexes" title="Building custom indexes">Building custom indexes</a> section. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.architecture.architecture_algorithm_to_managed.architecture_managed_memory"></a><a class="link" href="architecture.html#interprocess.architecture.architecture_algorithm_to_managed.architecture_managed_memory" title="Boost.Interprocess managed memory segments">Boost.Interprocess managed memory segments</a> |
| </h4></div></div></div> |
| <p> |
| The <span class="bold"><strong>Boost.Interprocess</strong></span> managed memory segments that construct the shared memory/memory |
| mapped file, place there the segment manager and forward the user requests to the |
| segment manager. For example, <code class="computeroutput"><a class="link" href="../boost/interprocess/basic_managed_shared_me_id909833.html" title="Class template basic_managed_shared_memory">basic_managed_shared_memory</a></code> |
| is a <span class="bold"><strong>Boost.Interprocess</strong></span> managed memory segment that works with shared memory. |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/basic_managed_mapped_file.html" title="Class template basic_managed_mapped_file">basic_managed_mapped_file</a></code> works with memory mapped files, etc... |
| </p> |
| <p> |
| Basically, the interface of a <span class="bold"><strong>Boost.Interprocess</strong></span> managed memory segment is the same as |
| the <span class="bold"><strong>segment manager</strong></span> but it also offers functions to "open", "create", or "open or create" |
| shared memory/memory-mapped files segments and initialize all needed resources. |
| Managed memory segment classes are not built in shared memory or memory mapped files, they |
| are normal C++ classes that store a pointer to the segment manager (which is built |
| in shared memory or memory mapped files). |
| </p> |
| <p> |
| Apart from this, managed memory segments offer specific functions: <code class="computeroutput"><span class="identifier">managed_mapped_file</span></code> |
| offers functions to flush memory contents to the file, <code class="computeroutput"><span class="identifier">managed_heap_memory</span></code> offers |
| functions to expand the memory, etc... |
| </p> |
| <p> |
| Most of the functions of <span class="bold"><strong>Boost.Interprocess</strong></span> managed memory segments can be shared |
| between all managed memory segments, since many times they just forward the functions |
| to the segment manager. Because of this, |
| in <span class="bold"><strong>Boost.Interprocess</strong></span> all managed memory segments derive from a common class that |
| implements memory-independent (shared memory, memory mapped files) functions: |
| <a href="../../../boost/interprocess/detail/managed_memory_impl.hpp" target="_top">boost::interprocess::detail::basic_managed_memory_impl</a> |
| </p> |
| <p> |
| Deriving from this class, <span class="bold"><strong>Boost.Interprocess</strong></span> implements several managed memory |
| classes, for different memory backends: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/basic_managed_shared_me_id909833.html" title="Class template basic_managed_shared_memory">basic_managed_shared_memory</a></code> (for shared memory). |
| </li> |
| <li class="listitem"> |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/basic_managed_mapped_file.html" title="Class template basic_managed_mapped_file">basic_managed_mapped_file</a></code> (for memory mapped files). |
| </li> |
| <li class="listitem"> |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/basic_managed_heap_memory.html" title="Class template basic_managed_heap_memory">basic_managed_heap_memory</a></code> (for heap allocated memory). |
| </li> |
| <li class="listitem"> |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/basic_managed_external__id909193.html" title="Class template basic_managed_external_buffer">basic_managed_external_buffer</a></code> (for user provided external buffer). |
| </li> |
| </ul></div> |
| </div> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="interprocess.architecture.allocators_containers"></a><a class="link" href="architecture.html#interprocess.architecture.allocators_containers" title="Allocators and containers">Allocators and containers</a> |
| </h3></div></div></div> |
| <div class="toc"><dl> |
| <dt><span class="section"><a href="architecture.html#interprocess.architecture.allocators_containers.allocators">Boost.Interprocess allocators</a></span></dt> |
| <dt><span class="section"><a href="architecture.html#interprocess.architecture.allocators_containers.implementation_segregated_storage_pools">Implementation of <span class="bold"><strong>Boost.Interprocess</strong></span> segregated storage pools</a></span></dt> |
| <dt><span class="section"><a href="architecture.html#interprocess.architecture.allocators_containers.implementation_adaptive_pools">Implementation of <span class="bold"><strong>Boost.Interprocess</strong></span> adaptive pools</a></span></dt> |
| <dt><span class="section"><a href="architecture.html#interprocess.architecture.allocators_containers.architecture_containers">Boost.Interprocess containers</a></span></dt> |
| </dl></div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.architecture.allocators_containers.allocators"></a><a class="link" href="architecture.html#interprocess.architecture.allocators_containers.allocators" title="Boost.Interprocess allocators">Boost.Interprocess allocators</a> |
| </h4></div></div></div> |
| <p> |
| The <span class="bold"><strong>Boost.Interprocess</strong></span> STL-like allocators are fairly simple and follow the usual C++ |
| allocator approach. Normally, allocators for STL containers are based above new/delete |
| operators and above those, they implement pools, arenas and other allocation tricks. |
| </p> |
| <p> |
| In <span class="bold"><strong>Boost.Interprocess</strong></span> allocators, the approach is similar, but all allocators are based |
| on the <span class="bold"><strong>segment manager</strong></span>. The segment manager is the only one that provides from simple |
| memory allocation to named object creations. <span class="bold"><strong>Boost.Interprocess</strong></span> allocators always store |
| a pointer to the segment manager, so that they can obtain memory from the segment or share |
| a common pool between allocators. |
| </p> |
| <p> |
| As you can imagine, the member pointers of the allocator are not a raw pointers, but |
| pointer types defined by the <code class="computeroutput"><span class="identifier">segment_manager</span><span class="special">::</span><span class="identifier">void_pointer</span></code> type. Apart from this, |
| the <code class="computeroutput"><span class="identifier">pointer</span></code> typedef of <span class="bold"><strong>Boost.Interprocess</strong></span> allocators is also of the same type of |
| <code class="computeroutput"><span class="identifier">segment_manager</span><span class="special">::</span><span class="identifier">void_pointer</span></code>. |
| </p> |
| <p> |
| This means that if our allocation algorithm defines <code class="computeroutput"><span class="identifier">void_pointer</span></code> as <code class="computeroutput"><span class="identifier">offset_ptr</span><span class="special"><</span><span class="keyword">void</span><span class="special">></span></code>, |
| <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">allocator</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code> will store an <code class="computeroutput"><span class="identifier">offset_ptr</span><span class="special"><</span><span class="identifier">segment_manager</span><span class="special">></span></code> |
| to point to the segment manager and the <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">allocator</span><span class="special"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">pointer</span></code> type |
| will be <code class="computeroutput"><span class="identifier">offset_ptr</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></code>. This way, <span class="bold"><strong>Boost.Interprocess</strong></span> allocators can be placed in the |
| memory segment managed by the segment manager, that is, shared memory, memory mapped files, |
| etc... |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.architecture.allocators_containers.implementation_segregated_storage_pools"></a><a class="link" href="architecture.html#interprocess.architecture.allocators_containers.implementation_segregated_storage_pools" title="Implementation of Boost.Interprocess segregated storage pools">Implementation of <span class="bold"><strong>Boost.Interprocess</strong></span> segregated storage pools</a> |
| </h4></div></div></div> |
| <p> |
| Segregated storage pools are simple and follow the classic segregated storage algorithm. |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| The pool allocates chunks of memory using the segment manager's raw memory |
| allocation functions. |
| </li> |
| <li class="listitem"> |
| The chunk contains a pointer to form a singly linked list of chunks. The pool |
| will contain a pointer to the first chunk. |
| </li> |
| <li class="listitem"> |
| The rest of the memory of the chunk is divided in nodes of the requested size and |
| no memory is used as payload for each node. Since the memory of a free node |
| is not used that memory is used to place a pointer to form a singly linked list of |
| free nodes. The pool has a pointer to the first free node. |
| </li> |
| <li class="listitem"> |
| Allocating a node is just taking the first free node from the list. If the list |
| is empty, a new chunk is allocated, linked in the list of chunks and the new free |
| nodes are linked in the free node list. |
| </li> |
| <li class="listitem"> |
| Deallocation returns the node to the free node list. |
| </li> |
| <li class="listitem"> |
| When the pool is destroyed, the list of chunks is traversed and memory is returned |
| to the segment manager. |
| </li> |
| </ul></div> |
| <p> |
| The pool is implemented by the |
| <a href="../../../boost/interprocess/allocators/detail/node_pool.hpp" target="_top">private_node_pool and shared_node_pool</a> classes. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.architecture.allocators_containers.implementation_adaptive_pools"></a><a class="link" href="architecture.html#interprocess.architecture.allocators_containers.implementation_adaptive_pools" title="Implementation of Boost.Interprocess adaptive pools">Implementation of <span class="bold"><strong>Boost.Interprocess</strong></span> adaptive pools</a> |
| </h4></div></div></div> |
| <p> |
| Adaptive pools are a variation of segregated lists but they have a more complicated |
| approach: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| Instead of using raw allocation, the pool allocates <span class="bold"><strong>aligned</strong></span> chunks of memory |
| using the segment manager. This is an <span class="bold"><strong>essential</strong></span> feature since a node can reach |
| its chunk information applying a simple mask to its address. |
| </li> |
| <li class="listitem"> |
| The chunks contains pointers to form a doubly linked list of chunks and |
| an additional pointer to create a singly linked list of free nodes placed |
| on that chunk. So unlike the segregated storage algorithm, the free list |
| of nodes is implemented <span class="bold"><strong>per chunk</strong></span>. |
| </li> |
| <li class="listitem"> |
| The pool maintains the chunks in increasing order of free nodes. This improves |
| locality and minimizes the dispersion of node allocations across the chunks |
| facilitating the creation of totally free chunks. |
| </li> |
| <li class="listitem"> |
| The pool has a pointer to the chunk with the minimum (but not zero) free nodes. |
| This chunk is called the "active" chunk. |
| </li> |
| <li class="listitem"> |
| Allocating a node is just returning the first free node of the "active" chunk. |
| The list of chunks is reordered according to the free nodes count. |
| The pointer to the "active" pool is updated if necessary. |
| </li> |
| <li class="listitem"> |
| If the pool runs out of nodes, a new chunk is allocated, and pushed back in the |
| list of chunks. The pointer to the "active" pool is updated if necessary. |
| </li> |
| <li class="listitem"> |
| Deallocation returns the node to the free node list of its chunk and updates |
| the "active" pool accordingly. |
| </li> |
| <li class="listitem"> |
| If the number of totally free chunks exceeds the limit, chunks are returned |
| to the segment manager. |
| </li> |
| <li class="listitem"> |
| When the pool is destroyed, the list of chunks is traversed and memory is returned |
| to the segment manager. |
| </li> |
| </ul></div> |
| <p> |
| The adaptive pool is implemented by the |
| <a href="../../../boost/interprocess/allocators/detail/adaptive_node_pool.hpp" target="_top">private_adaptive_node_pool and adaptive_node_pool</a> classes. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.architecture.allocators_containers.architecture_containers"></a><a class="link" href="architecture.html#interprocess.architecture.allocators_containers.architecture_containers" title="Boost.Interprocess containers">Boost.Interprocess containers</a> |
| </h4></div></div></div> |
| <p> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> containers are standard conforming counterparts of STL containers |
| in <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span></code> namespace, but with these little details: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> STL containers don't assume that memory allocated with |
| an allocator can be deallocated with other allocator of |
| the same type. They always compare allocators with <code class="computeroutput"><span class="keyword">operator</span><span class="special">==()</span></code> |
| to know if this is possible. |
| </li> |
| <li class="listitem"> |
| The pointers of the internal structures of the <span class="bold"><strong>Boost.Interprocess</strong></span> containers are |
| of the same type the <code class="computeroutput"><span class="identifier">pointer</span></code> type defined by the allocator of the container. This |
| allows placing containers in managed memory segments mapped in different base addresses. |
| </li> |
| </ul></div> |
| </div> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="interprocess.architecture.performance"></a><a class="link" href="architecture.html#interprocess.architecture.performance" title="Performance of Boost.Interprocess">Performance of Boost.Interprocess</a> |
| </h3></div></div></div> |
| <div class="toc"><dl> |
| <dt><span class="section"><a href="architecture.html#interprocess.architecture.performance.performance_allocations">Performance of raw memory allocations</a></span></dt> |
| <dt><span class="section"><a href="architecture.html#interprocess.architecture.performance.performance_named_allocation">Performance of named allocations</a></span></dt> |
| </dl></div> |
| <p> |
| This section tries to explain the performance characteristics of <span class="bold"><strong>Boost.Interprocess</strong></span>, |
| so that you can optimize <span class="bold"><strong>Boost.Interprocess</strong></span> usage if you need more performance. |
| </p> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.architecture.performance.performance_allocations"></a><a class="link" href="architecture.html#interprocess.architecture.performance.performance_allocations" title="Performance of raw memory allocations">Performance of raw memory allocations</a> |
| </h4></div></div></div> |
| <p> |
| You can have two types of raw memory allocations with <span class="bold"><strong>Boost.Interprocess</strong></span> classes: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| <span class="bold"><strong>Explicit</strong></span>: The user calls <code class="computeroutput"><span class="identifier">allocate</span><span class="special">()</span></code> and <code class="computeroutput"><span class="identifier">deallocate</span><span class="special">()</span></code> functions of |
| managed_shared_memory/managed_mapped_file... managed memory segments. This call is |
| translated to a <code class="computeroutput"><span class="identifier">MemoryAlgorithm</span><span class="special">::</span><span class="identifier">allocate</span><span class="special">()</span></code> function, which means that you |
| will need just the time that the memory algorithm associated with the managed memory segment |
| needs to allocate data. |
| </li> |
| <li class="listitem"> |
| <span class="bold"><strong>Implicit</strong></span>: For example, you are using <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">allocator</span><span class="special"><...></span></code> with |
| <span class="bold"><strong>Boost.Interprocess</strong></span> containers. This allocator calls the same <code class="computeroutput"><span class="identifier">MemoryAlgorithm</span><span class="special">::</span><span class="identifier">allocate</span><span class="special">()</span></code> |
| function than the explicit method, <span class="bold"><strong>every</strong></span> time a vector/string has to reallocate its |
| buffer or <span class="bold"><strong>every</strong></span> time you insert an object in a node container. |
| </li> |
| </ul></div> |
| <p> |
| If you see that memory allocation is a bottleneck in your application, you have |
| these alternatives: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| If you use map/set associative containers, try using <code class="computeroutput"><span class="identifier">flat_map</span></code> family instead |
| of the map family if you mainly do searches and the insertion/removal is mainly done |
| in an initialization phase. The overhead is now when the ordered vector has to |
| reallocate its storage and move data. You can also call the <code class="computeroutput"><span class="identifier">reserve</span><span class="special">()</span></code> method |
| of these containers when you know beforehand how much data you will insert. |
| However in these containers iterators are invalidated in insertions so this |
| substitution is only effective in some applications. |
| </li> |
| <li class="listitem"> |
| Use a <span class="bold"><strong>Boost.Interprocess</strong></span> pooled allocator for node containers, because pooled |
| allocators call <code class="computeroutput"><span class="identifier">allocate</span><span class="special">()</span></code> only when the pool runs out of nodes. This is pretty |
| efficient (much more than the current default general-purpose algorithm) and this |
| can save a lot of memory. See |
| <a class="link" href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_segregated_storage" title="Segregated storage node allocators">Segregated storage node allocators</a> and |
| <a class="link" href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_adaptive" title="Adaptive pool node allocators">Adaptive node allocators</a> for more information. |
| </li> |
| <li class="listitem"> |
| Write your own memory algorithm. If you have experience with memory allocation algorithms |
| and you think another algorithm is better suited than the default one for your application, |
| you can specify it in all <span class="bold"><strong>Boost.Interprocess</strong></span> managed memory segments. See the section |
| <a class="link" href="customizing_interprocess.html#interprocess.customizing_interprocess.custom_interprocess_alloc" title="Writing a new shared memory allocation algorithm">Writing a new shared memory allocation algorithm</a> |
| to know how to do this. If you think its better than the default one for general-purpose |
| applications, be polite and donate it to <span class="bold"><strong>Boost.Interprocess</strong></span> to make it default! |
| </li> |
| </ul></div> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.architecture.performance.performance_named_allocation"></a><a class="link" href="architecture.html#interprocess.architecture.performance.performance_named_allocation" title="Performance of named allocations">Performance of named allocations</a> |
| </h4></div></div></div> |
| <p> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> allows the same parallelism as two threads writing to a common |
| structure, except when the user creates/searches named/unique objects. The steps |
| when creating a named object are these: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| Lock a recursive mutex (so that you can make named allocations inside |
| the constructor of the object to be created). |
| </li> |
| <li class="listitem"> |
| Try to insert the [name pointer, object information] in the name/object index. |
| This lookup has to assure that the name has not been used before. |
| This is achieved calling <code class="computeroutput"><span class="identifier">insert</span><span class="special">()</span></code> function in the index. So the time this |
| requires is dependent on the index type (ordered vector, tree, hash...). |
| This can require a call to the memory algorithm allocation function if |
| the index has to be reallocated, it's a node allocator, uses pooled allocations... |
| </li> |
| <li class="listitem"> |
| Allocate a single buffer to hold the name of the object, the object itself, |
| and meta-data for destruction (number of objects, etc...). |
| </li> |
| <li class="listitem"> |
| Call the constructors of the object being created. If it's an array, one |
| construtor per array element. |
| </li> |
| <li class="listitem"> |
| Unlock the recursive mutex. |
| </li> |
| </ul></div> |
| <p> |
| The steps when destroying a named object using the name of the object |
| (<code class="computeroutput"><span class="identifier">destroy</span><span class="special"><</span><span class="identifier">T</span><span class="special">>(</span><span class="identifier">name</span><span class="special">)</span></code>) are these: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| Lock a recursive mutex . |
| </li> |
| <li class="listitem"> |
| Search in the index the entry associated to that name. Copy that information and |
| erase the index entry. This is done using <code class="computeroutput"><span class="identifier">find</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">key_type</span> <span class="special">&)</span></code> and <code class="computeroutput"><span class="identifier">erase</span><span class="special">(</span><span class="identifier">iterator</span><span class="special">)</span></code> |
| members of the index. This can require element reordering if the index is a |
| balanced tree, an ordered vector... |
| </li> |
| <li class="listitem"> |
| Call the destructor of the object (many if it's an array). |
| </li> |
| <li class="listitem"> |
| Deallocate the memory buffer containing the name, metadata and the object itself |
| using the allocation algorithm. |
| </li> |
| <li class="listitem"> |
| Unlock the recursive mutex. |
| </li> |
| </ul></div> |
| <p> |
| The steps when destroying a named object using the pointer of the object |
| (<code class="computeroutput"><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">T</span> <span class="special">*</span><span class="identifier">ptr</span><span class="special">)</span></code>) are these: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| Lock a recursive mutex . |
| </li> |
| <li class="listitem"> |
| Depending on the index type, this can be different: |
| <div class="itemizedlist"><ul class="itemizedlist" type="circle"> |
| <li class="listitem"> |
| If the index is a node index, (marked with <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">is_node_index</span></code> |
| specialization): Take the iterator stored near the object and call |
| <code class="computeroutput"><span class="identifier">erase</span><span class="special">(</span><span class="identifier">iterator</span><span class="special">)</span></code>. This can require element reordering if the index is a |
| balanced tree, an ordered vector... |
| </li> |
| <li class="listitem"> |
| If it's not an node index: Take the name stored near the object and erase |
| the index entry calling `erase(const key &). This can require element reordering |
| if the index is a balanced tree, an ordered vector... |
| </li> |
| </ul></div> |
| </li> |
| <li class="listitem"> |
| Call the destructor of the object (many if it's an array). |
| </li> |
| <li class="listitem"> |
| Deallocate the memory buffer containing the name, metadata and the object itself |
| using the allocation algorithm. |
| </li> |
| <li class="listitem"> |
| Unlock the recursive mutex. |
| </li> |
| </ul></div> |
| <p> |
| If you see that the performance is not good enough you have these alternatives: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| Maybe the problem is that the lock time is too big and it hurts parallelism. |
| Try to reduce the number of named objects in the global index and if your |
| application serves several clients try to build a new managed memory segment |
| for each one instead of using a common one. |
| </li> |
| <li class="listitem"> |
| Use another <span class="bold"><strong>Boost.Interprocess</strong></span> index type if you feel the default one is |
| not fast enough. If you are not still satisfied, write your own index type. See |
| <a class="link" href="customizing_interprocess.html#interprocess.customizing_interprocess.custom_indexes" title="Building custom indexes">Building custom indexes</a> for this. |
| </li> |
| <li class="listitem"> |
| Destruction via pointer is at least as fast as using the name of the object and |
| can be faster (in node containers, for example). So if your problem is that you |
| make at lot of named destructions, try to use the pointer. If the index is a |
| node index you can save some time. |
| </li> |
| </ul></div> |
| </div> |
| </div> |
| </div> |
| <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> |
| <td align="left"></td> |
| <td align="right"><div class="copyright-footer">Copyright © 2005-2010 Ion Gaztanaga<p> |
| Distributed under the Boost Software License, Version 1.0. (See accompanying |
| file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) |
| </p> |
| </div></td> |
| </tr></table> |
| <hr> |
| <div class="spirit-nav"> |
| <a accesskey="p" href="interprocess_smart_ptr.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../interprocess.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="customizing_interprocess.html"><img src="../../../doc/src/images/next.png" alt="Next"></a> |
| </div> |
| </body> |
| </html> |