| <html> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> |
| <title>Allocators, containers and memory allocation algorithms</title> |
| <link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css"> |
| <meta name="generator" content="DocBook XSL Stylesheets V1.78.1"> |
| <link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset"> |
| <link rel="up" href="../interprocess.html" title="Chapter 14. Boost.Interprocess"> |
| <link rel="prev" href="managed_memory_segments.html" title="Managed Memory Segments"> |
| <link rel="next" href="memory_algorithms.html" title="Memory allocation algorithms"> |
| </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="managed_memory_segments.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="memory_algorithms.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.allocators_containers"></a><a class="link" href="allocators_containers.html" title="Allocators, containers and memory allocation algorithms">Allocators, containers |
| and memory allocation algorithms</a> |
| </h2></div></div></div> |
| <div class="toc"><dl class="toc"> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.allocator_introduction">Introduction |
| to Interprocess allocators</a></span></dt> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_segregated_storage">Segregated |
| storage node allocators</a></span></dt> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_adaptive">Adaptive |
| pool node allocators</a></span></dt> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.containers_explained">Interprocess |
| and containers in managed memory segments</a></span></dt> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.additional_containers">Boost |
| containers compatible with Boost.Interprocess</a></span></dt> |
| </dl></div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="interprocess.allocators_containers.allocator_introduction"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.allocator_introduction" title="Introduction to Interprocess allocators">Introduction |
| to Interprocess allocators</a> |
| </h3></div></div></div> |
| <div class="toc"><dl class="toc"> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.allocator_introduction.allocator_properties">Properties |
| of <span class="bold"><strong>Boost.Interprocess</strong></span> allocators</a></span></dt> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.allocator_introduction.allocator_swapping">Swapping |
| Boost.Interprocess allocators</a></span></dt> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.allocator_introduction.allocator">allocator: |
| A general purpose allocator for managed memory segments</a></span></dt> |
| </dl></div> |
| <p> |
| As seen, <span class="bold"><strong>Boost.Interprocess</strong></span> offers raw memory |
| allocation and object construction using managed memory segments (managed |
| shared memory, managed mapped files...) and one of the first user requests |
| is the use of containers in managed shared memories. To achieve this, <span class="bold"><strong>Boost.Interprocess</strong></span> makes use of managed memory segment's |
| memory allocation algorithms to build several memory allocation schemes, |
| including general purpose and node allocators. |
| </p> |
| <p> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> STL compatible allocators |
| are configurable via template parameters. Allocators define their <code class="computeroutput"><span class="identifier">pointer</span></code> typedef based on the <code class="computeroutput"><span class="identifier">void_pointer</span></code> typedef of the segment manager |
| passed as template argument. When this <code class="computeroutput"><span class="identifier">segment_manager</span><span class="special">::</span><span class="identifier">void_pointer</span></code> |
| is a relative pointer, (for example, <code class="computeroutput"><span class="identifier">offset_ptr</span><span class="special"><</span><span class="keyword">void</span><span class="special">></span></code>) |
| the user can place these allocators in memory mapped in different base addresses |
| in several processes. |
| </p> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.allocators_containers.allocator_introduction.allocator_properties"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.allocator_introduction.allocator_properties" title="Properties of Boost.Interprocess allocators">Properties |
| of <span class="bold"><strong>Boost.Interprocess</strong></span> allocators</a> |
| </h4></div></div></div> |
| <p> |
| Container allocators are normally default-constructible because the are |
| stateless. <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">allocator</span></code> and <span class="bold"><strong>Boost.Pool's</strong></span> |
| <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">pool_allocator</span></code>/<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">fast_pool_allocator</span></code> |
| are examples of default-constructible allocators. |
| </p> |
| <p> |
| On the other hand, <span class="bold"><strong>Boost.Interprocess</strong></span> |
| allocators need to allocate memory from a concrete memory segment and not |
| from a system-wide memory source (like the heap). <span class="bold"><strong>Boost.Interprocess</strong></span> |
| allocators are <span class="bold"><strong>stateful</strong></span>, which means that |
| they must be configured to tell them where the shared memory or the memory |
| mapped file is. |
| </p> |
| <p> |
| This information is transmitted at compile-time and run-time: The allocators |
| receive a template parameter defining the type of the segment manager and |
| their constructor receive a pointer to the segment manager of the managed |
| memory segment where the user wants to allocate the values. |
| </p> |
| <p> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> allocators have <span class="bold"><strong>no default-constructors</strong></span> and containers must be explicitly |
| initialized with a configured allocator: |
| </p> |
| <pre class="programlisting"><span class="comment">//The allocators must be templatized with the segment manager type</span> |
| <span class="keyword">typedef</span> <span class="identifier">any_interprocess_allocator</span> |
| <span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">,</span> <span class="special">...></span> <span class="identifier">Allocator</span><span class="special">;</span> |
| |
| <span class="comment">//The allocator must be constructed with a pointer to the segment manager</span> |
| <span class="identifier">Allocator</span> <span class="identifier">alloc_instance</span> <span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">(),</span> <span class="special">...);</span> |
| |
| <span class="comment">//Containers must be initialized with a configured allocator</span> |
| <span class="keyword">typedef</span> <span class="identifier">my_list</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">Allocator</span><span class="special">></span> <span class="identifier">MyIntList</span><span class="special">;</span> |
| <span class="identifier">MyIntList</span> <span class="identifier">mylist</span><span class="special">(</span><span class="identifier">alloc_inst</span><span class="special">);</span> |
| |
| <span class="comment">//This would lead to a compilation error, because</span> |
| <span class="comment">//the allocator has no default constructor</span> |
| <span class="comment">//MyIntList mylist;</span> |
| </pre> |
| <p> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> allocators also have |
| a <code class="computeroutput"><span class="identifier">get_segment_manager</span><span class="special">()</span></code> |
| function that returns the underlying segment manager that they have received |
| in the constructor: |
| </p> |
| <pre class="programlisting"><span class="identifier">Allocator</span><span class="special">::</span><span class="identifier">segment_manager</span> <span class="identifier">s</span> <span class="special">=</span> <span class="identifier">alloc_instance</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">();</span> |
| <span class="identifier">AnotherType</span> <span class="special">*</span><span class="identifier">a</span> <span class="special">=</span> <span class="identifier">s</span><span class="special">-></span><span class="identifier">construct</span><span class="special"><</span><span class="identifier">AnotherType</span><span class="special">>(</span><span class="identifier">anonymous_instance</span><span class="special">)(/*</span><span class="identifier">Parameters</span><span class="special">*/);</span> |
| </pre> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.allocators_containers.allocator_introduction.allocator_swapping"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.allocator_introduction.allocator_swapping" title="Swapping Boost.Interprocess allocators">Swapping |
| Boost.Interprocess allocators</a> |
| </h4></div></div></div> |
| <p> |
| When swapping STL containers, there is an active discussion on what to |
| do with the allocators. Some STL implementations, for example Dinkumware |
| from Visual .NET 2003, perform a deep swap of the whole container through |
| a temporary when allocators are not equal. The <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2004/n1599.html" target="_top">proposed |
| resolution</a> to container swapping is that allocators should be swapped |
| in a non-throwing way. |
| </p> |
| <p> |
| Unfortunately, this approach is not valid with shared memory. Using heap |
| allocators, if Group1 of node allocators share a common segregated storage, |
| and Group2 share another common segregated storage, a simple pointer swapping |
| is needed to swap an allocator of Group1 and another allocator of Group2. |
| But when the user wants to swap two shared memory allocators, each one |
| placed in a different shared memory segment, this is not possible. As generally |
| shared memory is mapped in different addresses in each process, a pointer |
| placed in one segment can't point to any object placed in other shared |
| memory segment, since in each process, the distance between the segments |
| is different. However, if both shared memory allocators are in the same |
| segment, a non-throwing swap is possible, just like heap allocators. |
| </p> |
| <p> |
| Until a final resolution is achieved. <span class="bold"><strong>Boost.Interprocess</strong></span> |
| allocators implement a non-throwing swap function that swaps internal pointers. |
| If an allocator placed in a shared memory segment is swapped with other |
| placed in a different shared memory segment, the result is undefined. But |
| a crash is quite sure. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.allocators_containers.allocator_introduction.allocator"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.allocator_introduction.allocator" title="allocator: A general purpose allocator for managed memory segments">allocator: |
| A general purpose allocator for managed memory segments</a> |
| </h4></div></div></div> |
| <p> |
| The <code class="computeroutput"><a class="link" href="../boost/interprocess/allocator.html" title="Class template allocator">allocator</a></code> |
| class defines an allocator class that uses the managed memory segment's |
| algorithm to allocate and deallocate memory. This is achieved through the |
| <span class="bold"><strong>segment manager</strong></span> of the managed memory |
| segment. This allocator is the equivalent for managed memory segments of |
| the standard <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">allocator</span></code>. <code class="computeroutput"><a class="link" href="../boost/interprocess/allocator.html" title="Class template allocator">allocator</a></code> |
| is templatized with the allocated type, and the segment manager. |
| </p> |
| <p> |
| <span class="bold"><strong>Equality:</strong></span> Two <code class="computeroutput"><a class="link" href="../boost/interprocess/allocator.html" title="Class template allocator">allocator</a></code> |
| instances constructed with the same segment manager compare equal. If an |
| instance is created using copy constructor, that instance compares equal |
| with the original one. |
| </p> |
| <p> |
| <span class="bold"><strong>Allocation thread-safety:</strong></span> Allocation and |
| deallocation are implemented as calls to the segment manager's allocation |
| function so the allocator offers the same thread-safety as the segment |
| manager. |
| </p> |
| <p> |
| To use <code class="computeroutput"><a class="link" href="../boost/interprocess/allocator.html" title="Class template allocator">allocator</a></code> |
| you must include the following header: |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">allocator</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <p> |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/allocator.html" title="Class template allocator">allocator</a></code> has |
| the following declaration: |
| </p> |
| <pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> |
| <span class="keyword">namespace</span> <span class="identifier">interprocess</span> <span class="special">{</span> |
| |
| <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">SegmentManager</span><span class="special">></span> |
| <span class="keyword">class</span> <span class="identifier">allocator</span><span class="special">;</span> |
| |
| <span class="special">}</span> <span class="comment">//namespace interprocess {</span> |
| <span class="special">}</span> <span class="comment">//namespace boost {</span> |
| </pre> |
| <p> |
| The allocator just provides the needed typedefs and forwards all allocation |
| and deallocation requests to the segment manager passed in the constructor, |
| just like <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">allocator</span></code> forwards the requests to <code class="computeroutput"><span class="keyword">operator</span> <span class="keyword">new</span><span class="special">[]</span></code>. |
| </p> |
| <p> |
| Using <code class="computeroutput"><a class="link" href="../boost/interprocess/allocator.html" title="Class template allocator">allocator</a></code> |
| is straightforward: |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">managed_shared_memory</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">allocator</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cassert</span><span class="special">></span> |
| |
| <span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span> |
| |
| <span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span> |
| <span class="special">{</span> |
| <span class="comment">//Remove shared memory on construction and destruction</span> |
| <span class="keyword">struct</span> <span class="identifier">shm_remove</span> |
| <span class="special">{</span> |
| <span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span> |
| |
| <span class="comment">//Create shared memory</span> |
| <span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> |
| <span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="comment">//segment name</span> |
| <span class="number">65536</span><span class="special">);</span> |
| |
| <span class="comment">//Create an allocator that allocates ints from the managed segment</span> |
| <span class="identifier">allocator</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">></span> |
| <span class="identifier">allocator_instance</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| |
| <span class="comment">//Copy constructed allocator is equal</span> |
| <span class="identifier">allocator</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">></span> |
| <span class="identifier">allocator_instance2</span><span class="special">(</span><span class="identifier">allocator_instance</span><span class="special">);</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">allocator_instance2</span> <span class="special">==</span> <span class="identifier">allocator_instance</span><span class="special">);</span> |
| |
| <span class="comment">//Allocate and deallocate memory for 100 ints</span> |
| <span class="identifier">allocator_instance2</span><span class="special">.</span><span class="identifier">deallocate</span><span class="special">(</span><span class="identifier">allocator_instance</span><span class="special">.</span><span class="identifier">allocate</span><span class="special">(</span><span class="number">100</span><span class="special">),</span> <span class="number">100</span><span class="special">);</span> |
| |
| <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| </div> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="interprocess.allocators_containers.stl_allocators_segregated_storage"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_segregated_storage" title="Segregated storage node allocators">Segregated |
| storage node allocators</a> |
| </h3></div></div></div> |
| <div class="toc"><dl class="toc"> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_segregated_storage.segregated_allocators_common">Additional |
| parameters and functions of segregated storage node allocators</a></span></dt> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_segregated_storage.node_allocator">node_allocator: |
| A process-shared segregated storage</a></span></dt> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_segregated_storage.private_node_allocator">private_node_allocator: |
| a private segregated storage</a></span></dt> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_segregated_storage.cached_node_allocator">cached_node_allocator: |
| caching nodes to avoid overhead</a></span></dt> |
| </dl></div> |
| <p> |
| Variable size memory algorithms waste some space in management information |
| for each allocation. Sometimes, usually for small objects, this is not acceptable. |
| Memory algorithms can also fragment the managed memory segment under some |
| allocation and deallocation schemes, reducing their performance. When allocating |
| many objects of the same type, a simple segregated storage becomes a fast |
| and space-friendly allocator, as explained in the <a href="http://www.boost.org/libs/pool/" target="_top"><span class="bold"><strong>Boost.Pool</strong></span></a> library. |
| </p> |
| <p> |
| Segregate storage node allocators allocate large memory chunks from a general |
| purpose memory allocator and divide that chunk into several nodes. No bookkeeping |
| information is stored in the nodes to achieve minimal memory waste: free |
| nodes are linked using a pointer constructed in the memory of the node. |
| </p> |
| <p> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> offers 3 allocators based |
| on this segregated storage algorithm: <code class="computeroutput"><a class="link" href="../boost/interprocess/node_allocator.html" title="Class template node_allocator">node_allocator</a></code>, |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/private_node_allocator.html" title="Class template private_node_allocator">private_node_allocator</a></code> |
| and <code class="computeroutput"><a class="link" href="../boost/interprocess/cached_node_allocator.html" title="Class template cached_node_allocator">cached_node_allocator</a></code>. |
| </p> |
| <p> |
| To know the details of the implementation of of the segregated storage pools |
| see the <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> section. |
| </p> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.allocators_containers.stl_allocators_segregated_storage.segregated_allocators_common"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_segregated_storage.segregated_allocators_common" title="Additional parameters and functions of segregated storage node allocators">Additional |
| parameters and functions of segregated storage node allocators</a> |
| </h4></div></div></div> |
| <p> |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/node_allocator.html" title="Class template node_allocator">node_allocator</a></code>, |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/private_node_allocator.html" title="Class template private_node_allocator">private_node_allocator</a></code> |
| and <code class="computeroutput"><a class="link" href="../boost/interprocess/cached_node_allocator.html" title="Class template cached_node_allocator">cached_node_allocator</a></code> |
| implement the standard allocator interface and the functions explained |
| in the <a class="link" href="allocators_containers.html#interprocess.allocators_containers.allocator_introduction.allocator_properties" title="Properties of Boost.Interprocess allocators">Properties |
| of Boost.Interprocess allocators</a>. |
| </p> |
| <p> |
| All these allocators are templatized by 3 parameters: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> |
| <li class="listitem"> |
| <code class="computeroutput"><span class="keyword">class</span> <span class="identifier">T</span></code>: |
| The type to be allocated. |
| </li> |
| <li class="listitem"> |
| <code class="computeroutput"><span class="keyword">class</span> <span class="identifier">SegmentManager</span></code>: |
| The type of the segment manager that will be passed in the constructor. |
| </li> |
| <li class="listitem"> |
| <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">NodesPerChunk</span></code>: |
| The number of nodes that a memory chunk will contain. This value will |
| define the size of the memory the pool will request to the segment |
| manager when the pool runs out of nodes. This parameter has a default |
| value. |
| </li> |
| </ul></div> |
| <p> |
| These allocators also offer the <code class="computeroutput"><span class="identifier">deallocate_free_chunks</span><span class="special">()</span></code> function. This function will traverse |
| all the memory chunks of the pool and will return to the managed memory |
| segment the free chunks of memory. If this function is not used, deallocating |
| the free chunks does not happen until the pool is destroyed so the only |
| way to return memory allocated by the pool to the segment before destructing |
| the pool is calling manually this function. This function is quite time-consuming |
| because it has quadratic complexity (O(N^2)). |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.allocators_containers.stl_allocators_segregated_storage.node_allocator"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_segregated_storage.node_allocator" title="node_allocator: A process-shared segregated storage">node_allocator: |
| A process-shared segregated storage</a> |
| </h4></div></div></div> |
| <p> |
| For heap-memory node allocators (like <span class="bold"><strong>Boost.Pool's</strong></span> |
| <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">fast_pool_allocator</span></code> usually a global, |
| thread-shared singleton pool is used for each node size. This is not possible |
| if you try to share a node allocator between processes. To achieve this |
| sharing <code class="computeroutput"><a class="link" href="../boost/interprocess/node_allocator.html" title="Class template node_allocator">node_allocator</a></code> |
| uses the segment manager's unique type allocation service (see <a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.unique" title="Unique instance construction">Unique |
| instance construction</a> section). |
| </p> |
| <p> |
| In the initialization, a <code class="computeroutput"><a class="link" href="../boost/interprocess/node_allocator.html" title="Class template node_allocator">node_allocator</a></code> |
| object searches this unique object in the segment. If it is not preset, |
| it builds one. This way, all <code class="computeroutput"><a class="link" href="../boost/interprocess/node_allocator.html" title="Class template node_allocator">node_allocator</a></code> |
| objects built inside a memory segment share a unique memory pool. |
| </p> |
| <p> |
| The common segregated storage is not only shared between node_allocators |
| of the same type, but it is also shared between all node allocators that |
| allocate objects of the same size, for example, <span class="bold"><strong>node_allocator<uint32></strong></span> |
| and <span class="bold"><strong>node_allocator<float32></strong></span>. This |
| saves a lot of memory but also imposes an synchronization overhead for |
| each node allocation. |
| </p> |
| <p> |
| The dynamically created common segregated storage integrates a reference |
| count so that a <code class="computeroutput"><a class="link" href="../boost/interprocess/node_allocator.html" title="Class template node_allocator">node_allocator</a></code> |
| can know if any other <code class="computeroutput"><a class="link" href="../boost/interprocess/node_allocator.html" title="Class template node_allocator">node_allocator</a></code> |
| is attached to the same common segregated storage. When the last allocator |
| attached to the pool is destroyed, the pool is destroyed. |
| </p> |
| <p> |
| <span class="bold"><strong>Equality:</strong></span> Two <code class="computeroutput"><a class="link" href="../boost/interprocess/node_allocator.html" title="Class template node_allocator">node_allocator</a></code> |
| instances constructed with the same segment manager compare equal. If an |
| instance is created using copy constructor, that instance compares equal |
| with the original one. |
| </p> |
| <p> |
| <span class="bold"><strong>Allocation thread-safety:</strong></span> Allocation and |
| deallocation are implemented as calls to the shared pool. The shared pool |
| offers the same synchronization guarantees as the segment manager. |
| </p> |
| <p> |
| To use <code class="computeroutput"><a class="link" href="../boost/interprocess/node_allocator.html" title="Class template node_allocator">node_allocator</a></code>, |
| you must include the following header: |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">node_allocator</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <p> |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/node_allocator.html" title="Class template node_allocator">node_allocator</a></code> |
| has the following declaration: |
| </p> |
| <pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> |
| <span class="keyword">namespace</span> <span class="identifier">interprocess</span> <span class="special">{</span> |
| |
| <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">SegmentManager</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">NodesPerChunk</span> <span class="special">=</span> <span class="special">...></span> |
| <span class="keyword">class</span> <span class="identifier">node_allocator</span><span class="special">;</span> |
| |
| <span class="special">}</span> <span class="comment">//namespace interprocess {</span> |
| <span class="special">}</span> <span class="comment">//namespace boost {</span> |
| </pre> |
| <p> |
| An example using <code class="computeroutput"><a class="link" href="../boost/interprocess/node_allocator.html" title="Class template node_allocator">node_allocator</a></code>: |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">managed_shared_memory</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">node_allocator</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cassert</span><span class="special">></span> |
| |
| <span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span> |
| |
| <span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span> |
| <span class="special">{</span> |
| <span class="comment">//Remove shared memory on construction and destruction</span> |
| <span class="keyword">struct</span> <span class="identifier">shm_remove</span> |
| <span class="special">{</span> |
| <span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span> |
| |
| <span class="comment">//Create shared memory</span> |
| <span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> |
| <span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="comment">//segment name</span> |
| <span class="number">65536</span><span class="special">);</span> |
| |
| <span class="comment">//Create a node_allocator that allocates ints from the managed segment</span> |
| <span class="comment">//The number of chunks per segment is the default value</span> |
| <span class="keyword">typedef</span> <span class="identifier">node_allocator</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">></span> |
| <span class="identifier">node_allocator_t</span><span class="special">;</span> |
| <span class="identifier">node_allocator_t</span> <span class="identifier">allocator_instance</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| |
| <span class="comment">//Create another node_allocator. Since the segment manager address</span> |
| <span class="comment">//is the same, this node_allocator will be</span> |
| <span class="comment">//attached to the same pool so "allocator_instance2" can deallocate</span> |
| <span class="comment">//nodes allocated by "allocator_instance"</span> |
| <span class="identifier">node_allocator_t</span> <span class="identifier">allocator_instance2</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| |
| <span class="comment">//Create another node_allocator using copy-constructor. This</span> |
| <span class="comment">//node_allocator will also be attached to the same pool</span> |
| <span class="identifier">node_allocator_t</span> <span class="identifier">allocator_instance3</span><span class="special">(</span><span class="identifier">allocator_instance2</span><span class="special">);</span> |
| |
| <span class="comment">//All allocators are equal</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">allocator_instance</span> <span class="special">==</span> <span class="identifier">allocator_instance2</span><span class="special">);</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">allocator_instance2</span> <span class="special">==</span> <span class="identifier">allocator_instance3</span><span class="special">);</span> |
| |
| <span class="comment">//So memory allocated with one can be deallocated with another</span> |
| <span class="identifier">allocator_instance2</span><span class="special">.</span><span class="identifier">deallocate</span><span class="special">(</span><span class="identifier">allocator_instance</span><span class="special">.</span><span class="identifier">allocate</span><span class="special">(</span><span class="number">1</span><span class="special">),</span> <span class="number">1</span><span class="special">);</span> |
| <span class="identifier">allocator_instance3</span><span class="special">.</span><span class="identifier">deallocate</span><span class="special">(</span><span class="identifier">allocator_instance2</span><span class="special">.</span><span class="identifier">allocate</span><span class="special">(</span><span class="number">1</span><span class="special">),</span> <span class="number">1</span><span class="special">);</span> |
| |
| <span class="comment">//The common pool will be destroyed here, since no allocator is</span> |
| <span class="comment">//attached to the pool</span> |
| <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.allocators_containers.stl_allocators_segregated_storage.private_node_allocator"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_segregated_storage.private_node_allocator" title="private_node_allocator: a private segregated storage">private_node_allocator: |
| a private segregated storage</a> |
| </h4></div></div></div> |
| <p> |
| As said, the node_allocator shares a common segregated storage between |
| node_allocators that allocate objects of the same size and this optimizes |
| memory usage. However, it needs a unique/named object construction feature |
| so that this sharing can be possible. Also imposes a synchronization overhead |
| per node allocation because of this share. Sometimes, the unique object |
| service is not available (for example, when building index types to implement |
| the named allocation service itself) or the synchronization overhead is |
| not acceptable. Many times the programmer wants to make sure that the pool |
| is destroyed when the allocator is destroyed, to free the memory as soon |
| as possible. |
| </p> |
| <p> |
| So <span class="bold"><strong>private_node_allocator</strong></span> uses the same |
| segregated storage as <code class="computeroutput"><span class="identifier">node_allocator</span></code>, |
| but each <span class="bold"><strong>private_node_allocator</strong></span> has its |
| own segregated storage pool. No synchronization is used when allocating |
| nodes, so there is far less overhead for an operation that usually involves |
| just a few pointer operations when allocating and deallocating a node. |
| </p> |
| <p> |
| <span class="bold"><strong>Equality:</strong></span> Two <code class="computeroutput"><a class="link" href="../boost/interprocess/private_node_allocator.html" title="Class template private_node_allocator">private_node_allocator</a></code> |
| instances <span class="bold"><strong>never</strong></span> compare equal. Memory |
| allocated with one allocator <span class="bold"><strong>can't</strong></span> be |
| deallocated with another one. |
| </p> |
| <p> |
| <span class="bold"><strong>Allocation thread-safety:</strong></span> Allocation and |
| deallocation are <span class="bold"><strong>not</strong></span> thread-safe. |
| </p> |
| <p> |
| To use <code class="computeroutput"><a class="link" href="../boost/interprocess/private_node_allocator.html" title="Class template private_node_allocator">private_node_allocator</a></code>, |
| you must include the following header: |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">private_node_allocator</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <p> |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/private_node_allocator.html" title="Class template private_node_allocator">private_node_allocator</a></code> |
| has the following declaration: |
| </p> |
| <pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> |
| <span class="keyword">namespace</span> <span class="identifier">interprocess</span> <span class="special">{</span> |
| |
| <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">SegmentManager</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">NodesPerChunk</span> <span class="special">=</span> <span class="special">...></span> |
| <span class="keyword">class</span> <span class="identifier">private_node_allocator</span><span class="special">;</span> |
| |
| <span class="special">}</span> <span class="comment">//namespace interprocess {</span> |
| <span class="special">}</span> <span class="comment">//namespace boost {</span> |
| </pre> |
| <p> |
| An example using <code class="computeroutput"><a class="link" href="../boost/interprocess/private_node_allocator.html" title="Class template private_node_allocator">private_node_allocator</a></code>: |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">managed_shared_memory</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">private_node_allocator</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cassert</span><span class="special">></span> |
| |
| <span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span> |
| |
| <span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span> |
| <span class="special">{</span> |
| <span class="comment">//Remove shared memory on construction and destruction</span> |
| <span class="keyword">struct</span> <span class="identifier">shm_remove</span> |
| <span class="special">{</span> |
| <span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span> |
| |
| <span class="comment">//Create shared memory</span> |
| <span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> |
| <span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="comment">//segment name</span> |
| <span class="number">65536</span><span class="special">);</span> |
| |
| <span class="comment">//Create a private_node_allocator that allocates ints from the managed segment</span> |
| <span class="comment">//The number of chunks per segment is the default value</span> |
| <span class="keyword">typedef</span> <span class="identifier">private_node_allocator</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">></span> |
| <span class="identifier">private_node_allocator_t</span><span class="special">;</span> |
| <span class="identifier">private_node_allocator_t</span> <span class="identifier">allocator_instance</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| |
| <span class="comment">//Create another private_node_allocator.</span> |
| <span class="identifier">private_node_allocator_t</span> <span class="identifier">allocator_instance2</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| |
| <span class="comment">//Although the segment manager address</span> |
| <span class="comment">//is the same, this private_node_allocator will have its own pool so</span> |
| <span class="comment">//"allocator_instance2" CAN'T deallocate nodes allocated by "allocator_instance".</span> |
| <span class="comment">//"allocator_instance2" is NOT equal to "allocator_instance"</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">allocator_instance</span> <span class="special">!=</span> <span class="identifier">allocator_instance2</span><span class="special">);</span> |
| |
| <span class="comment">//Create another node_allocator using copy-constructor.</span> |
| <span class="identifier">private_node_allocator_t</span> <span class="identifier">allocator_instance3</span><span class="special">(</span><span class="identifier">allocator_instance2</span><span class="special">);</span> |
| |
| <span class="comment">//This allocator is also unequal to allocator_instance2</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">allocator_instance2</span> <span class="special">!=</span> <span class="identifier">allocator_instance3</span><span class="special">);</span> |
| |
| <span class="comment">//Pools are destroyed with the allocators</span> |
| <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.allocators_containers.stl_allocators_segregated_storage.cached_node_allocator"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_segregated_storage.cached_node_allocator" title="cached_node_allocator: caching nodes to avoid overhead">cached_node_allocator: |
| caching nodes to avoid overhead</a> |
| </h4></div></div></div> |
| <p> |
| The total node sharing of <code class="computeroutput"><a class="link" href="../boost/interprocess/node_allocator.html" title="Class template node_allocator">node_allocator</a></code> |
| can impose a high overhead for some applications and the minimal synchronization |
| overhead of <code class="computeroutput"><a class="link" href="../boost/interprocess/private_node_allocator.html" title="Class template private_node_allocator">private_node_allocator</a></code> |
| can impose a unacceptable memory waste for other applications. |
| </p> |
| <p> |
| To solve this, <span class="bold"><strong>Boost.Interprocess</strong></span> offers |
| an allocator, <code class="computeroutput"><a class="link" href="../boost/interprocess/cached_node_allocator.html" title="Class template cached_node_allocator">cached_node_allocator</a></code>, |
| that allocates nodes from the common pool but caches some of them privately |
| so that following allocations have no synchronization overhead. When the |
| cache is full, the allocator returns some cached nodes to the common pool, |
| and those will be available to other allocators. |
| </p> |
| <p> |
| <span class="bold"><strong>Equality:</strong></span> Two <code class="computeroutput"><a class="link" href="../boost/interprocess/cached_node_allocator.html" title="Class template cached_node_allocator">cached_node_allocator</a></code> |
| instances constructed with the same segment manager compare equal. If an |
| instance is created using copy constructor, that instance compares equal |
| with the original one. |
| </p> |
| <p> |
| <span class="bold"><strong>Allocation thread-safety:</strong></span> Allocation and |
| deallocation are <span class="bold"><strong>not</strong></span> thread-safe. |
| </p> |
| <p> |
| To use <code class="computeroutput"><a class="link" href="../boost/interprocess/cached_node_allocator.html" title="Class template cached_node_allocator">cached_node_allocator</a></code>, |
| you must include the following header: |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">cached_node_allocator</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <p> |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/cached_node_allocator.html" title="Class template cached_node_allocator">cached_node_allocator</a></code> |
| has the following declaration: |
| </p> |
| <pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> |
| <span class="keyword">namespace</span> <span class="identifier">interprocess</span> <span class="special">{</span> |
| |
| <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">SegmentManager</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">NodesPerChunk</span> <span class="special">=</span> <span class="special">...></span> |
| <span class="keyword">class</span> <span class="identifier">cached_node_allocator</span><span class="special">;</span> |
| |
| <span class="special">}</span> <span class="comment">//namespace interprocess {</span> |
| <span class="special">}</span> <span class="comment">//namespace boost {</span> |
| </pre> |
| <p> |
| A <code class="computeroutput"><a class="link" href="../boost/interprocess/cached_node_allocator.html" title="Class template cached_node_allocator">cached_node_allocator</a></code> |
| instance and a <code class="computeroutput"><a class="link" href="../boost/interprocess/node_allocator.html" title="Class template node_allocator">node_allocator</a></code> |
| instance share the same pool if both instances receive the same template |
| parameters. This means that nodes returned to the shared pool by one of |
| them can be reused by the other. Please note that this does not mean that |
| both allocators compare equal, this is just information for programmers |
| that want to maximize the use of the pool. |
| </p> |
| <p> |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/cached_node_allocator.html" title="Class template cached_node_allocator">cached_node_allocator</a></code>, |
| offers additional functions to control the cache (the cache can be controlled |
| per instance): |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> |
| <li class="listitem"> |
| <code class="computeroutput"><span class="keyword">void</span> <span class="identifier">set_max_cached_nodes</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> |
| <span class="identifier">n</span><span class="special">)</span></code>: |
| Sets the maximum cached nodes limit. If cached nodes reach the limit, |
| some are returned to the shared pool. |
| </li> |
| <li class="listitem"> |
| <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">get_max_cached_nodes</span><span class="special">()</span> <span class="keyword">const</span></code>: |
| Returns the maximum cached nodes limit. |
| </li> |
| <li class="listitem"> |
| <code class="computeroutput"><span class="keyword">void</span> <span class="identifier">deallocate_cache</span><span class="special">()</span></code>: Returns the cached nodes to the |
| shared pool. |
| </li> |
| </ul></div> |
| <p> |
| An example using <code class="computeroutput"><a class="link" href="../boost/interprocess/cached_node_allocator.html" title="Class template cached_node_allocator">cached_node_allocator</a></code>: |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">managed_shared_memory</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">cached_node_allocator</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cassert</span><span class="special">></span> |
| |
| <span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span> |
| |
| <span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span> |
| <span class="special">{</span> |
| <span class="comment">//Remove shared memory on construction and destruction</span> |
| <span class="keyword">struct</span> <span class="identifier">shm_remove</span> |
| <span class="special">{</span> |
| <span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span> |
| |
| <span class="comment">//Create shared memory</span> |
| <span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> |
| <span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="comment">//segment name</span> |
| <span class="number">65536</span><span class="special">);</span> |
| |
| <span class="comment">//Create a cached_node_allocator that allocates ints from the managed segment</span> |
| <span class="comment">//The number of chunks per segment is the default value</span> |
| <span class="keyword">typedef</span> <span class="identifier">cached_node_allocator</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">></span> |
| <span class="identifier">cached_node_allocator_t</span><span class="special">;</span> |
| <span class="identifier">cached_node_allocator_t</span> <span class="identifier">allocator_instance</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| |
| <span class="comment">//The max cached nodes are configurable per instance</span> |
| <span class="identifier">allocator_instance</span><span class="special">.</span><span class="identifier">set_max_cached_nodes</span><span class="special">(</span><span class="number">3</span><span class="special">);</span> |
| |
| <span class="comment">//Create another cached_node_allocator. Since the segment manager address</span> |
| <span class="comment">//is the same, this cached_node_allocator will be</span> |
| <span class="comment">//attached to the same pool so "allocator_instance2" can deallocate</span> |
| <span class="comment">//nodes allocated by "allocator_instance"</span> |
| <span class="identifier">cached_node_allocator_t</span> <span class="identifier">allocator_instance2</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| |
| <span class="comment">//The max cached nodes are configurable per instance</span> |
| <span class="identifier">allocator_instance2</span><span class="special">.</span><span class="identifier">set_max_cached_nodes</span><span class="special">(</span><span class="number">5</span><span class="special">);</span> |
| |
| <span class="comment">//Create another cached_node_allocator using copy-constructor. This</span> |
| <span class="comment">//cached_node_allocator will also be attached to the same pool</span> |
| <span class="identifier">cached_node_allocator_t</span> <span class="identifier">allocator_instance3</span><span class="special">(</span><span class="identifier">allocator_instance2</span><span class="special">);</span> |
| |
| <span class="comment">//We can clear the cache</span> |
| <span class="identifier">allocator_instance3</span><span class="special">.</span><span class="identifier">deallocate_cache</span><span class="special">();</span> |
| |
| <span class="comment">//All allocators are equal</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">allocator_instance</span> <span class="special">==</span> <span class="identifier">allocator_instance2</span><span class="special">);</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">allocator_instance2</span> <span class="special">==</span> <span class="identifier">allocator_instance3</span><span class="special">);</span> |
| |
| <span class="comment">//So memory allocated with one can be deallocated with another</span> |
| <span class="identifier">allocator_instance2</span><span class="special">.</span><span class="identifier">deallocate</span><span class="special">(</span><span class="identifier">allocator_instance</span><span class="special">.</span><span class="identifier">allocate</span><span class="special">(</span><span class="number">1</span><span class="special">),</span> <span class="number">1</span><span class="special">);</span> |
| <span class="identifier">allocator_instance3</span><span class="special">.</span><span class="identifier">deallocate</span><span class="special">(</span><span class="identifier">allocator_instance2</span><span class="special">.</span><span class="identifier">allocate</span><span class="special">(</span><span class="number">1</span><span class="special">),</span> <span class="number">1</span><span class="special">);</span> |
| |
| <span class="comment">//The common pool will be destroyed here, since no allocator is</span> |
| <span class="comment">//attached to the pool</span> |
| <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| </div> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="interprocess.allocators_containers.stl_allocators_adaptive"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_adaptive" title="Adaptive pool node allocators">Adaptive |
| pool node allocators</a> |
| </h3></div></div></div> |
| <div class="toc"><dl class="toc"> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_adaptive.adaptive_allocators_common">Additional |
| parameters and functions of adaptive pool node allocators</a></span></dt> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_adaptive.adaptive_pool">adaptive_pool: |
| a process-shared adaptive pool</a></span></dt> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_adaptive.private_adaptive_pool">private_adaptive_pool: |
| a private adaptive pool</a></span></dt> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_adaptive.cached_adaptive_pool">cached_adaptive_pool: |
| Avoiding synchronization overhead</a></span></dt> |
| </dl></div> |
| <p> |
| Node allocators based on simple segregated storage algorithm are both space-efficient |
| and fast but they have a problem: they only can grow. Every allocated node |
| avoids any payload to store additional data and that leads to the following |
| limitation: when a node is deallocated, it's stored in a free list of nodes |
| but memory is not returned to the segment manager so a deallocated node can |
| be only reused by other containers using the same node pool. |
| </p> |
| <p> |
| This behaviour can be problematic if several containers use <code class="computeroutput"><a class="link" href="../boost/interprocess/node_allocator.html" title="Class template node_allocator">boost::interprocess::node_allocator</a></code> |
| to temporarily allocate a lot of objects but they end storing a few of them: |
| the node pool will be full of nodes that won't be reused wasting memory from |
| the segment. |
| </p> |
| <p> |
| Adaptive pool based allocators trade some space (the overhead can be as low |
| as 1%) and performance (acceptable for many applications) with the ability |
| to return free chunks of nodes to the memory segment, so that they can be |
| used by any other container or managed object construction. To know the details |
| of the implementation of of "adaptive pools" see the <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.Intrusive</strong></span> adaptive pools</a> |
| section. |
| </p> |
| <p> |
| Like with segregated storage based node allocators, Boost.Interprocess offers |
| 3 new allocators: <code class="computeroutput"><a class="link" href="../boost/interprocess/adaptive_pool.html" title="Class template adaptive_pool">adaptive_pool</a></code>, |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/private_adaptive_pool.html" title="Class template private_adaptive_pool">private_adaptive_pool</a></code>, |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/cached_adaptive_pool.html" title="Class template cached_adaptive_pool">cached_adaptive_pool</a></code>. |
| </p> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.allocators_containers.stl_allocators_adaptive.adaptive_allocators_common"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_adaptive.adaptive_allocators_common" title="Additional parameters and functions of adaptive pool node allocators">Additional |
| parameters and functions of adaptive pool node allocators</a> |
| </h4></div></div></div> |
| <p> |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/adaptive_pool.html" title="Class template adaptive_pool">adaptive_pool</a></code>, |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/private_adaptive_pool.html" title="Class template private_adaptive_pool">private_adaptive_pool</a></code> |
| and <code class="computeroutput"><a class="link" href="../boost/interprocess/cached_adaptive_pool.html" title="Class template cached_adaptive_pool">cached_adaptive_pool</a></code> |
| implement the standard allocator interface and the functions explained |
| in the <a class="link" href="allocators_containers.html#interprocess.allocators_containers.allocator_introduction.allocator_properties" title="Properties of Boost.Interprocess allocators">Properties |
| of Boost.Interprocess allocators</a>. |
| </p> |
| <p> |
| All these allocators are templatized by 4 parameters: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> |
| <li class="listitem"> |
| <code class="computeroutput"><span class="keyword">class</span> <span class="identifier">T</span></code>: |
| The type to be allocated. |
| </li> |
| <li class="listitem"> |
| <code class="computeroutput"><span class="keyword">class</span> <span class="identifier">SegmentManager</span></code>: |
| The type of the segment manager that will be passed in the constructor. |
| </li> |
| <li class="listitem"> |
| <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">NodesPerChunk</span></code>: |
| The number of nodes that a memory chunk will contain. This value will |
| define the size of the memory the pool will request to the segment |
| manager when the pool runs out of nodes. This parameter has a default |
| value. |
| </li> |
| <li class="listitem"> |
| <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">MaxFreeChunks</span></code>: |
| The maximum number of free chunks that the pool will hold. If this |
| limit is reached the pool returns the chunks to the segment manager. |
| This parameter has a default value. |
| </li> |
| </ul></div> |
| <p> |
| These allocators also offer the <code class="computeroutput"><span class="identifier">deallocate_free_chunks</span><span class="special">()</span></code> function. This function will traverse |
| all the memory chunks of the pool and will return to the managed memory |
| segment the free chunks of memory. This function is much faster than for |
| segregated storage allocators, because the adaptive pool algorithm offers |
| constant-time access to free chunks. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.allocators_containers.stl_allocators_adaptive.adaptive_pool"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_adaptive.adaptive_pool" title="adaptive_pool: a process-shared adaptive pool">adaptive_pool: |
| a process-shared adaptive pool</a> |
| </h4></div></div></div> |
| <p> |
| Just like <code class="computeroutput"><a class="link" href="../boost/interprocess/node_allocator.html" title="Class template node_allocator">node_allocator</a></code> |
| a global, process-thread pool is used for each node size. In the initialization, |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/adaptive_pool.html" title="Class template adaptive_pool">adaptive_pool</a></code> |
| searches the pool in the segment. If it is not preset, it builds one. The |
| adaptive pool, is created using a unique name. The adaptive pool it is |
| also shared between all node_allocators that allocate objects of the same |
| size, for example, <span class="bold"><strong>adaptive_pool<uint32></strong></span> |
| and <span class="bold"><strong>adaptive_pool<float32></strong></span>. |
| </p> |
| <p> |
| The common adaptive pool is destroyed when all the allocators attached |
| to the pool are destroyed. |
| </p> |
| <p> |
| <span class="bold"><strong>Equality:</strong></span> Two <code class="computeroutput"><a class="link" href="../boost/interprocess/adaptive_pool.html" title="Class template adaptive_pool">adaptive_pool</a></code> |
| instances constructed with the same segment manager compare equal. If an |
| instance is created using copy constructor, that instance compares equal |
| with the original one. |
| </p> |
| <p> |
| <span class="bold"><strong>Allocation thread-safety:</strong></span> Allocation and |
| deallocation are implemented as calls to the shared pool. The shared pool |
| offers the same synchronization guarantees as the segment manager. |
| </p> |
| <p> |
| To use <code class="computeroutput"><a class="link" href="../boost/interprocess/adaptive_pool.html" title="Class template adaptive_pool">adaptive_pool</a></code>, |
| you must include the following header: |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">adaptive_pool</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <p> |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/adaptive_pool.html" title="Class template adaptive_pool">adaptive_pool</a></code> |
| has the following declaration: |
| </p> |
| <pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> |
| <span class="keyword">namespace</span> <span class="identifier">interprocess</span> <span class="special">{</span> |
| |
| <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">SegmentManager</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">NodesPerChunk</span> <span class="special">=</span> <span class="special">...,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">MaxFreeChunks</span> <span class="special">=</span> <span class="special">...></span> |
| <span class="keyword">class</span> <span class="identifier">adaptive_pool</span><span class="special">;</span> |
| |
| <span class="special">}</span> <span class="comment">//namespace interprocess {</span> |
| <span class="special">}</span> <span class="comment">//namespace boost {</span> |
| </pre> |
| <p> |
| An example using <code class="computeroutput"><a class="link" href="../boost/interprocess/adaptive_pool.html" title="Class template adaptive_pool">adaptive_pool</a></code>: |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">managed_shared_memory</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">adaptive_pool</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cassert</span><span class="special">></span> |
| |
| <span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span> |
| |
| <span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span> |
| <span class="special">{</span> |
| <span class="comment">//Remove shared memory on construction and destruction</span> |
| <span class="keyword">struct</span> <span class="identifier">shm_remove</span> |
| <span class="special">{</span> |
| <span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span> |
| |
| <span class="comment">//Create shared memory</span> |
| <span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> |
| <span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="comment">//segment name</span> |
| <span class="number">65536</span><span class="special">);</span> |
| |
| <span class="comment">//Create a adaptive_pool that allocates ints from the managed segment</span> |
| <span class="comment">//The number of chunks per segment is the default value</span> |
| <span class="keyword">typedef</span> <span class="identifier">adaptive_pool</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">></span> |
| <span class="identifier">adaptive_pool_t</span><span class="special">;</span> |
| <span class="identifier">adaptive_pool_t</span> <span class="identifier">allocator_instance</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| |
| <span class="comment">//Create another adaptive_pool. Since the segment manager address</span> |
| <span class="comment">//is the same, this adaptive_pool will be</span> |
| <span class="comment">//attached to the same pool so "allocator_instance2" can deallocate</span> |
| <span class="comment">//nodes allocated by "allocator_instance"</span> |
| <span class="identifier">adaptive_pool_t</span> <span class="identifier">allocator_instance2</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| |
| <span class="comment">//Create another adaptive_pool using copy-constructor. This</span> |
| <span class="comment">//adaptive_pool will also be attached to the same pool</span> |
| <span class="identifier">adaptive_pool_t</span> <span class="identifier">allocator_instance3</span><span class="special">(</span><span class="identifier">allocator_instance2</span><span class="special">);</span> |
| |
| <span class="comment">//All allocators are equal</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">allocator_instance</span> <span class="special">==</span> <span class="identifier">allocator_instance2</span><span class="special">);</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">allocator_instance2</span> <span class="special">==</span> <span class="identifier">allocator_instance3</span><span class="special">);</span> |
| |
| <span class="comment">//So memory allocated with one can be deallocated with another</span> |
| <span class="identifier">allocator_instance2</span><span class="special">.</span><span class="identifier">deallocate</span><span class="special">(</span><span class="identifier">allocator_instance</span><span class="special">.</span><span class="identifier">allocate</span><span class="special">(</span><span class="number">1</span><span class="special">),</span> <span class="number">1</span><span class="special">);</span> |
| <span class="identifier">allocator_instance3</span><span class="special">.</span><span class="identifier">deallocate</span><span class="special">(</span><span class="identifier">allocator_instance2</span><span class="special">.</span><span class="identifier">allocate</span><span class="special">(</span><span class="number">1</span><span class="special">),</span> <span class="number">1</span><span class="special">);</span> |
| |
| <span class="comment">//The common pool will be destroyed here, since no allocator is</span> |
| <span class="comment">//attached to the pool</span> |
| <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.allocators_containers.stl_allocators_adaptive.private_adaptive_pool"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_adaptive.private_adaptive_pool" title="private_adaptive_pool: a private adaptive pool">private_adaptive_pool: |
| a private adaptive pool</a> |
| </h4></div></div></div> |
| <p> |
| Just like <code class="computeroutput"><a class="link" href="../boost/interprocess/private_node_allocator.html" title="Class template private_node_allocator">private_node_allocator</a></code> |
| owns a private segregated storage pool, <code class="computeroutput"><a class="link" href="../boost/interprocess/private_adaptive_pool.html" title="Class template private_adaptive_pool">private_adaptive_pool</a></code> |
| owns its own adaptive pool. If the user wants to avoid the excessive node |
| allocation synchronization overhead in a container <code class="computeroutput"><a class="link" href="../boost/interprocess/private_adaptive_pool.html" title="Class template private_adaptive_pool">private_adaptive_pool</a></code> |
| is a good choice. |
| </p> |
| <p> |
| <span class="bold"><strong>Equality:</strong></span> Two <code class="computeroutput"><a class="link" href="../boost/interprocess/private_adaptive_pool.html" title="Class template private_adaptive_pool">private_adaptive_pool</a></code> |
| instances <span class="bold"><strong>never</strong></span> compare equal. Memory |
| allocated with one allocator <span class="bold"><strong>can't</strong></span> be |
| deallocated with another one. |
| </p> |
| <p> |
| <span class="bold"><strong>Allocation thread-safety:</strong></span> Allocation and |
| deallocation are <span class="bold"><strong>not</strong></span> thread-safe. |
| </p> |
| <p> |
| To use <code class="computeroutput"><a class="link" href="../boost/interprocess/private_adaptive_pool.html" title="Class template private_adaptive_pool">private_adaptive_pool</a></code>, |
| you must include the following header: |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">private_adaptive_pool</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <p> |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/private_adaptive_pool.html" title="Class template private_adaptive_pool">private_adaptive_pool</a></code> |
| has the following declaration: |
| </p> |
| <pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> |
| <span class="keyword">namespace</span> <span class="identifier">interprocess</span> <span class="special">{</span> |
| |
| <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">SegmentManager</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">NodesPerChunk</span> <span class="special">=</span> <span class="special">...,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">MaxFreeChunks</span> <span class="special">=</span> <span class="special">...></span> |
| <span class="keyword">class</span> <span class="identifier">private_adaptive_pool</span><span class="special">;</span> |
| |
| <span class="special">}</span> <span class="comment">//namespace interprocess {</span> |
| <span class="special">}</span> <span class="comment">//namespace boost {</span> |
| </pre> |
| <p> |
| An example using <code class="computeroutput"><a class="link" href="../boost/interprocess/private_adaptive_pool.html" title="Class template private_adaptive_pool">private_adaptive_pool</a></code>: |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">managed_shared_memory</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">private_adaptive_pool</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cassert</span><span class="special">></span> |
| |
| <span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span> |
| |
| <span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span> |
| <span class="special">{</span> |
| <span class="comment">//Remove shared memory on construction and destruction</span> |
| <span class="keyword">struct</span> <span class="identifier">shm_remove</span> |
| <span class="special">{</span> |
| <span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span> |
| |
| <span class="comment">//Create shared memory</span> |
| <span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> |
| <span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="comment">//segment name</span> |
| <span class="number">65536</span><span class="special">);</span> |
| |
| <span class="comment">//Create a private_adaptive_pool that allocates ints from the managed segment</span> |
| <span class="comment">//The number of chunks per segment is the default value</span> |
| <span class="keyword">typedef</span> <span class="identifier">private_adaptive_pool</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">></span> |
| <span class="identifier">private_adaptive_pool_t</span><span class="special">;</span> |
| <span class="identifier">private_adaptive_pool_t</span> <span class="identifier">allocator_instance</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| |
| <span class="comment">//Create another private_adaptive_pool.</span> |
| <span class="identifier">private_adaptive_pool_t</span> <span class="identifier">allocator_instance2</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| |
| <span class="comment">//Although the segment manager address</span> |
| <span class="comment">//is the same, this private_adaptive_pool will have its own pool so</span> |
| <span class="comment">//"allocator_instance2" CAN'T deallocate nodes allocated by "allocator_instance".</span> |
| <span class="comment">//"allocator_instance2" is NOT equal to "allocator_instance"</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">allocator_instance</span> <span class="special">!=</span> <span class="identifier">allocator_instance2</span><span class="special">);</span> |
| |
| <span class="comment">//Create another adaptive_pool using copy-constructor.</span> |
| <span class="identifier">private_adaptive_pool_t</span> <span class="identifier">allocator_instance3</span><span class="special">(</span><span class="identifier">allocator_instance2</span><span class="special">);</span> |
| |
| <span class="comment">//This allocator is also unequal to allocator_instance2</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">allocator_instance2</span> <span class="special">!=</span> <span class="identifier">allocator_instance3</span><span class="special">);</span> |
| |
| <span class="comment">//Pools are destroyed with the allocators</span> |
| <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.allocators_containers.stl_allocators_adaptive.cached_adaptive_pool"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.stl_allocators_adaptive.cached_adaptive_pool" title="cached_adaptive_pool: Avoiding synchronization overhead">cached_adaptive_pool: |
| Avoiding synchronization overhead</a> |
| </h4></div></div></div> |
| <p> |
| Adaptive pools have also a cached version. In this allocator the allocator |
| caches some nodes to avoid the synchronization and bookkeeping overhead |
| of the shared adaptive pool. <code class="computeroutput"><a class="link" href="../boost/interprocess/cached_adaptive_pool.html" title="Class template cached_adaptive_pool">cached_adaptive_pool</a></code> |
| allocates nodes from the common adaptive pool but caches some of them privately |
| so that following allocations have no synchronization overhead. When the |
| cache is full, the allocator returns some cached nodes to the common pool, |
| and those will be available to other <code class="computeroutput"><a class="link" href="../boost/interprocess/cached_adaptive_pool.html" title="Class template cached_adaptive_pool">cached_adaptive_pools</a></code> |
| or <code class="computeroutput"><a class="link" href="../boost/interprocess/adaptive_pool.html" title="Class template adaptive_pool">adaptive_pools</a></code> |
| of the same managed segment. |
| </p> |
| <p> |
| <span class="bold"><strong>Equality:</strong></span> Two <code class="computeroutput"><a class="link" href="../boost/interprocess/cached_adaptive_pool.html" title="Class template cached_adaptive_pool">cached_adaptive_pool</a></code> |
| instances constructed with the same segment manager compare equal. If an |
| instance is created using copy constructor, that instance compares equal |
| with the original one. |
| </p> |
| <p> |
| <span class="bold"><strong>Allocation thread-safety:</strong></span> Allocation and |
| deallocation are <span class="bold"><strong>not</strong></span> thread-safe. |
| </p> |
| <p> |
| To use <code class="computeroutput"><a class="link" href="../boost/interprocess/cached_adaptive_pool.html" title="Class template cached_adaptive_pool">cached_adaptive_pool</a></code>, |
| you must include the following header: |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">cached_adaptive_pool</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <p> |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/cached_adaptive_pool.html" title="Class template cached_adaptive_pool">cached_adaptive_pool</a></code> |
| has the following declaration: |
| </p> |
| <pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> |
| <span class="keyword">namespace</span> <span class="identifier">interprocess</span> <span class="special">{</span> |
| |
| <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">SegmentManager</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">NodesPerChunk</span> <span class="special">=</span> <span class="special">...,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">MaxFreeNodes</span> <span class="special">=</span> <span class="special">...></span> |
| <span class="keyword">class</span> <span class="identifier">cached_adaptive_pool</span><span class="special">;</span> |
| |
| <span class="special">}</span> <span class="comment">//namespace interprocess {</span> |
| <span class="special">}</span> <span class="comment">//namespace boost {</span> |
| </pre> |
| <p> |
| A <code class="computeroutput"><a class="link" href="../boost/interprocess/cached_adaptive_pool.html" title="Class template cached_adaptive_pool">cached_adaptive_pool</a></code> |
| instance and an <code class="computeroutput"><a class="link" href="../boost/interprocess/adaptive_pool.html" title="Class template adaptive_pool">adaptive_pool</a></code> |
| instance share the same pool if both instances receive the same template |
| parameters. This means that nodes returned to the shared pool by one of |
| them can be reused by the other. Please note that this does not mean that |
| both allocators compare equal, this is just information for programmers |
| that want to maximize the use of the pool. |
| </p> |
| <p> |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/cached_adaptive_pool.html" title="Class template cached_adaptive_pool">cached_adaptive_pool</a></code>, |
| offers additional functions to control the cache (the cache can be controlled |
| per instance): |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> |
| <li class="listitem"> |
| <code class="computeroutput"><span class="keyword">void</span> <span class="identifier">set_max_cached_nodes</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> |
| <span class="identifier">n</span><span class="special">)</span></code>: |
| Sets the maximum cached nodes limit. If cached nodes reach the limit, |
| some are returned to the shared pool. |
| </li> |
| <li class="listitem"> |
| <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">get_max_cached_nodes</span><span class="special">()</span> <span class="keyword">const</span></code>: |
| Returns the maximum cached nodes limit. |
| </li> |
| <li class="listitem"> |
| <code class="computeroutput"><span class="keyword">void</span> <span class="identifier">deallocate_cache</span><span class="special">()</span></code>: Returns the cached nodes to the |
| shared pool. |
| </li> |
| </ul></div> |
| <p> |
| An example using <code class="computeroutput"><a class="link" href="../boost/interprocess/cached_adaptive_pool.html" title="Class template cached_adaptive_pool">cached_adaptive_pool</a></code>: |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">managed_shared_memory</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">cached_adaptive_pool</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cassert</span><span class="special">></span> |
| |
| <span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span> |
| |
| <span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span> |
| <span class="special">{</span> |
| <span class="comment">//Remove shared memory on construction and destruction</span> |
| <span class="keyword">struct</span> <span class="identifier">shm_remove</span> |
| <span class="special">{</span> |
| <span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span> |
| |
| <span class="comment">//Create shared memory</span> |
| <span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> |
| <span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="comment">//segment name</span> |
| <span class="number">65536</span><span class="special">);</span> |
| |
| <span class="comment">//Create a cached_adaptive_pool that allocates ints from the managed segment</span> |
| <span class="comment">//The number of chunks per segment is the default value</span> |
| <span class="keyword">typedef</span> <span class="identifier">cached_adaptive_pool</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">></span> |
| <span class="identifier">cached_adaptive_pool_t</span><span class="special">;</span> |
| <span class="identifier">cached_adaptive_pool_t</span> <span class="identifier">allocator_instance</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| |
| <span class="comment">//The max cached nodes are configurable per instance</span> |
| <span class="identifier">allocator_instance</span><span class="special">.</span><span class="identifier">set_max_cached_nodes</span><span class="special">(</span><span class="number">3</span><span class="special">);</span> |
| |
| <span class="comment">//Create another cached_adaptive_pool. Since the segment manager address</span> |
| <span class="comment">//is the same, this cached_adaptive_pool will be</span> |
| <span class="comment">//attached to the same pool so "allocator_instance2" can deallocate</span> |
| <span class="comment">//nodes allocated by "allocator_instance"</span> |
| <span class="identifier">cached_adaptive_pool_t</span> <span class="identifier">allocator_instance2</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| |
| <span class="comment">//The max cached nodes are configurable per instance</span> |
| <span class="identifier">allocator_instance2</span><span class="special">.</span><span class="identifier">set_max_cached_nodes</span><span class="special">(</span><span class="number">5</span><span class="special">);</span> |
| |
| <span class="comment">//Create another cached_adaptive_pool using copy-constructor. This</span> |
| <span class="comment">//cached_adaptive_pool will also be attached to the same pool</span> |
| <span class="identifier">cached_adaptive_pool_t</span> <span class="identifier">allocator_instance3</span><span class="special">(</span><span class="identifier">allocator_instance2</span><span class="special">);</span> |
| |
| <span class="comment">//We can clear the cache</span> |
| <span class="identifier">allocator_instance3</span><span class="special">.</span><span class="identifier">deallocate_cache</span><span class="special">();</span> |
| |
| <span class="comment">//All allocators are equal</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">allocator_instance</span> <span class="special">==</span> <span class="identifier">allocator_instance2</span><span class="special">);</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">allocator_instance2</span> <span class="special">==</span> <span class="identifier">allocator_instance3</span><span class="special">);</span> |
| |
| <span class="comment">//So memory allocated with one can be deallocated with another</span> |
| <span class="identifier">allocator_instance2</span><span class="special">.</span><span class="identifier">deallocate</span><span class="special">(</span><span class="identifier">allocator_instance</span><span class="special">.</span><span class="identifier">allocate</span><span class="special">(</span><span class="number">1</span><span class="special">),</span> <span class="number">1</span><span class="special">);</span> |
| <span class="identifier">allocator_instance3</span><span class="special">.</span><span class="identifier">deallocate</span><span class="special">(</span><span class="identifier">allocator_instance2</span><span class="special">.</span><span class="identifier">allocate</span><span class="special">(</span><span class="number">1</span><span class="special">),</span> <span class="number">1</span><span class="special">);</span> |
| |
| <span class="comment">//The common pool will be destroyed here, since no allocator is</span> |
| <span class="comment">//attached to the pool</span> |
| <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| </div> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="interprocess.allocators_containers.containers_explained"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.containers_explained" title="Interprocess and containers in managed memory segments">Interprocess |
| and containers in managed memory segments</a> |
| </h3></div></div></div> |
| <div class="toc"><dl class="toc"> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.containers_explained.stl_container_requirements">Container |
| requirements for Boost.Interprocess allocators</a></span></dt> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.containers_explained.containers">STL |
| containers in managed memory segments</a></span></dt> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.containers_explained.where_allocate">Where |
| is this being allocated?</a></span></dt> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.containers_explained.containers_and_move">Move |
| semantics in Interprocess containers</a></span></dt> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.containers_explained.containers_of_containers">Containers |
| of containers</a></span></dt> |
| </dl></div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.allocators_containers.containers_explained.stl_container_requirements"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.containers_explained.stl_container_requirements" title="Container requirements for Boost.Interprocess allocators">Container |
| requirements for Boost.Interprocess allocators</a> |
| </h4></div></div></div> |
| <p> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> STL compatible allocators |
| offer a STL compatible allocator interface and if they define their internal |
| <span class="bold"><strong>pointer</strong></span> typedef as a relative pointer, |
| they can sbe used to place STL containers in shared memory, memory mapped |
| files or in a user defined memory segment. |
| </p> |
| <p> |
| However, as Scott Meyers mentions in his Effective STL book, Item 10, |
| <span class="emphasis"><em>"Be aware of allocator conventions and restrictions"</em></span>: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> |
| <li class="listitem"> |
| <span class="emphasis"><em>"the Standard explicitly allows library implementers |
| to assume that every allocator's pointer typedef is a synonym for T*"</em></span> |
| </li> |
| <li class="listitem"> |
| <span class="emphasis"><em>"the Standard says that an implementation of the STL |
| is permitted to assume that all allocator objects of the same type |
| are equivalent and always compare equal"</em></span> |
| </li> |
| </ul></div> |
| <p> |
| Obviously, if any STL implementation ignores pointer typedefs, no smart |
| pointer can be used as allocator::pointer. If STL implementations assume |
| all allocator objects of the same type compare equal, it will assume that |
| two allocators, each one allocating from a different memory pool are equal, |
| which is a complete disaster. |
| </p> |
| <p> |
| STL containers that we want to place in shared memory or memory mapped |
| files with <span class="bold"><strong>Boost.Interprocess</strong></span> can't make |
| any of these assumptions, so: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> |
| <li class="listitem"> |
| STL containers may not assume that memory allocated with an allocator |
| can be deallocated with other allocators of the same type. All allocators |
| objects must compare equal only if memory allocated with one object |
| can be deallocated with the other one, and this can only tested with |
| operator==() at run-time. |
| </li> |
| <li class="listitem"> |
| Containers' internal pointers should be of the type allocator::pointer |
| and containers may not assume allocator::pointer is a raw pointer. |
| </li> |
| <li class="listitem"> |
| All objects must be constructed-destroyed via allocator::construct |
| and allocator::destroy functions. |
| </li> |
| </ul></div> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.allocators_containers.containers_explained.containers"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.containers_explained.containers" title="STL containers in managed memory segments">STL |
| containers in managed memory segments</a> |
| </h4></div></div></div> |
| <p> |
| Unfortunately, many STL implementations use raw pointers for internal data |
| and ignore allocator pointer typedefs and others suppose at some point |
| that the allocator::typedef is T*. This is because in practice, there wasn't |
| need of allocators with a pointer typedef different from T* for pooled/node |
| memory allocators. |
| </p> |
| <p> |
| Until STL implementations handle allocator::pointer typedefs in a generic |
| way, <span class="bold"><strong>Boost.Interprocess</strong></span> offers the following |
| classes: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"> |
| <span class="bold"><strong>boost:interprocess::vector</strong></span> is the |
| implementation of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span></code> |
| ready to be used in managed memory segments like shared memory. To |
| use it include: |
| </li></ul></div> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">vector</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"> |
| <span class="bold"><strong>boost:interprocess::deque</strong></span> is the implementation |
| of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">deque</span></code> ready to be used in managed |
| memory segments like shared memory. To use it include: |
| </li></ul></div> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">deque</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"> |
| <code class="computeroutput">list</code> is the |
| implementation of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span></code> |
| ready to be used in managed memory segments like shared memory. To |
| use it include: |
| </li></ul></div> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">list</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"> |
| <code class="computeroutput">slist</code> is the |
| implementation of SGI's <code class="computeroutput"><span class="identifier">slist</span></code> |
| container (singly linked list) ready to be used in managed memory segments |
| like shared memory. To use it include: |
| </li></ul></div> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">slist</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"> |
| <code class="computeroutput">set</code>/ <code class="computeroutput">multiset</code>/ <code class="computeroutput">map</code>/ <code class="computeroutput">multimap</code> |
| family is the implementation of std::set/multiset/map/multimap family |
| ready to be used in managed memory segments like shared memory. To |
| use them include: |
| </li></ul></div> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">set</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">map</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"> |
| <code class="computeroutput">flat_set</code>/ |
| <code class="computeroutput">flat_multiset</code>/ |
| <code class="computeroutput">flat_map</code>/ |
| <code class="computeroutput">flat_multimap</code> |
| classes are the adaptation and extension of Andrei Alexandrescu's famous |
| AssocVector class from Loki library, ready for the shared memory. These |
| classes offer the same functionality as <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">set</span><span class="special">/</span><span class="identifier">multiset</span><span class="special">/</span><span class="identifier">map</span><span class="special">/</span><span class="identifier">multimap</span></code> |
| implemented with an ordered vector, which has faster lookups than the |
| standard ordered associative containers based on red-black trees, but |
| slower insertions. To use it include: |
| </li></ul></div> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">flat_set</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">flat_map</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"> |
| <code class="computeroutput">basic_string</code> |
| is the implementation of <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_string</span></code> |
| ready to be used in managed memory segments like shared memory. It's |
| implemented using a vector-like contiguous storage, so it has fast |
| c string conversion and can be used with the <a class="link" href="streams.html#interprocess.streams.vectorstream" title="Formatting directly in your character vector: vectorstream">vectorstream</a> |
| iostream formatting classes. To use it include: |
| </li></ul></div> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">string</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <p> |
| All these containers have the same default arguments as standard containers |
| and they can be used with other, non <span class="bold"><strong>Boost.Interprocess</strong></span> |
| allocators (std::allocator, or boost::pool_allocator, for example). |
| </p> |
| <p> |
| To place any of these containers in managed memory segments, we must define |
| the allocator template parameter with a <span class="bold"><strong>Boost.Interprocess</strong></span> |
| allocator so that the container allocates the values in the managed memory |
| segment. To place the container itself in shared memory, we construct it |
| in the managed memory segment just like any other object with <span class="bold"><strong>Boost.Interprocess</strong></span>: |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">vector</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">allocator</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">managed_shared_memory</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| |
| <span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span> |
| <span class="special">{</span> |
| <span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span> |
| <span class="comment">//Remove shared memory on construction and destruction</span> |
| <span class="keyword">struct</span> <span class="identifier">shm_remove</span> |
| <span class="special">{</span> |
| <span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span> |
| |
| <span class="comment">//A managed shared memory where we can construct objects</span> |
| <span class="comment">//associated with a c-string</span> |
| <span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> |
| <span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="comment">//segment name</span> |
| <span class="number">65536</span><span class="special">);</span> |
| |
| <span class="comment">//Alias an STL-like allocator of ints that allocates ints from the segment</span> |
| <span class="keyword">typedef</span> <span class="identifier">allocator</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">></span> |
| <span class="identifier">ShmemAllocator</span><span class="special">;</span> |
| |
| <span class="comment">//Alias a vector that uses the previous STL-like allocator</span> |
| <span class="keyword">typedef</span> <span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">ShmemAllocator</span><span class="special">></span> <span class="identifier">MyVector</span><span class="special">;</span> |
| |
| <span class="keyword">int</span> <span class="identifier">initVal</span><span class="special">[]</span> <span class="special">=</span> <span class="special">{</span><span class="number">0</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">,</span> <span class="number">3</span><span class="special">,</span> <span class="number">4</span><span class="special">,</span> <span class="number">5</span><span class="special">,</span> <span class="number">6</span> <span class="special">};</span> |
| <span class="keyword">const</span> <span class="keyword">int</span> <span class="special">*</span><span class="identifier">begVal</span> <span class="special">=</span> <span class="identifier">initVal</span><span class="special">;</span> |
| <span class="keyword">const</span> <span class="keyword">int</span> <span class="special">*</span><span class="identifier">endVal</span> <span class="special">=</span> <span class="identifier">initVal</span> <span class="special">+</span> <span class="keyword">sizeof</span><span class="special">(</span><span class="identifier">initVal</span><span class="special">)/</span><span class="keyword">sizeof</span><span class="special">(</span><span class="identifier">initVal</span><span class="special">[</span><span class="number">0</span><span class="special">]);</span> |
| |
| <span class="comment">//Initialize the STL-like allocator</span> |
| <span class="keyword">const</span> <span class="identifier">ShmemAllocator</span> <span class="identifier">alloc_inst</span> <span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| |
| <span class="comment">//Construct the vector in the shared memory segment with the STL-like allocator</span> |
| <span class="comment">//from a range of iterators</span> |
| <span class="identifier">MyVector</span> <span class="special">*</span><span class="identifier">myvector</span> <span class="special">=</span> |
| <span class="identifier">segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="identifier">MyVector</span><span class="special">></span> |
| <span class="special">(</span><span class="string">"MyVector"</span><span class="special">)/*</span><span class="identifier">object</span> <span class="identifier">name</span><span class="special">*/</span> |
| <span class="special">(</span><span class="identifier">begVal</span> <span class="comment">/*first ctor parameter*/</span><span class="special">,</span> |
| <span class="identifier">endVal</span> <span class="comment">/*second ctor parameter*/</span><span class="special">,</span> |
| <span class="identifier">alloc_inst</span> <span class="comment">/*third ctor parameter*/</span><span class="special">);</span> |
| |
| <span class="comment">//Use vector as your want</span> |
| <span class="identifier">std</span><span class="special">::</span><span class="identifier">sort</span><span class="special">(</span><span class="identifier">myvector</span><span class="special">-></span><span class="identifier">rbegin</span><span class="special">(),</span> <span class="identifier">myvector</span><span class="special">-></span><span class="identifier">rend</span><span class="special">());</span> |
| <span class="comment">// . . .</span> |
| <span class="comment">//When done, destroy and delete vector from the segment</span> |
| <span class="identifier">segment</span><span class="special">.</span><span class="identifier">destroy</span><span class="special"><</span><span class="identifier">MyVector</span><span class="special">>(</span><span class="string">"MyVector"</span><span class="special">);</span> |
| <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| <p> |
| These containers also show how easy is to create/modify an existing container |
| making possible to place it in shared memory. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.allocators_containers.containers_explained.where_allocate"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.containers_explained.where_allocate" title="Where is this being allocated?">Where |
| is this being allocated?</a> |
| </h4></div></div></div> |
| <p> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> containers are placed |
| in shared memory/memory mapped files, etc... using two mechanisms <span class="bold"><strong>at the same time</strong></span>: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> |
| <li class="listitem"> |
| <span class="bold"><strong>Boost.Interprocess </strong></span><code class="computeroutput"><span class="identifier">construct</span><span class="special"><></span></code>, <code class="computeroutput"><span class="identifier">find_or_construct</span><span class="special"><></span></code>... functions. These functions |
| place a C++ object in the shared memory/memory mapped file. But this |
| places only the object, but <span class="bold"><strong>not</strong></span> the |
| memory that this object may allocate dynamically. |
| </li> |
| <li class="listitem"> |
| Shared memory allocators. These allow allocating shared memory/memory |
| mapped file portions so that containers can allocate dynamically fragments |
| of memory to store newly inserted elements. |
| </li> |
| </ul></div> |
| <p> |
| This means that to place any <span class="bold"><strong>Boost.Interprocess</strong></span> |
| container (including <span class="bold"><strong>Boost.Interprocess</strong></span> |
| strings) in shared memory or memory mapped files, containers <span class="bold"><strong>must</strong></span>: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> |
| <li class="listitem"> |
| Define their template allocator parameter to a <span class="bold"><strong>Boost.Interprocess</strong></span> |
| allocator. |
| </li> |
| <li class="listitem"> |
| Every container constructor must take the <span class="bold"><strong>Boost.Interprocess</strong></span> |
| allocator as parameter. |
| </li> |
| <li class="listitem"> |
| You must use construct<>/find_or_construct<>... functions |
| to place the container in the managed memory. |
| </li> |
| </ul></div> |
| <p> |
| If you do the first two points but you don't use <code class="computeroutput"><span class="identifier">construct</span><span class="special"><></span></code> or <code class="computeroutput"><span class="identifier">find_or_construct</span><span class="special"><></span></code> you are creating a container placed |
| <span class="bold"><strong>only</strong></span> in your process but that allocates |
| memory for contained types from shared memory/memory mapped file. |
| </p> |
| <p> |
| Let's see an example: |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">managed_shared_memory</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">vector</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">string</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">allocator</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| |
| <span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span> |
| <span class="special">{</span> |
| <span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span> |
| <span class="comment">//Typedefs</span> |
| <span class="keyword">typedef</span> <span class="identifier">allocator</span><span class="special"><</span><span class="keyword">char</span><span class="special">,</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">></span> |
| <span class="identifier">CharAllocator</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">basic_string</span><span class="special"><</span><span class="keyword">char</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">char_traits</span><span class="special"><</span><span class="keyword">char</span><span class="special">>,</span> <span class="identifier">CharAllocator</span><span class="special">></span> |
| <span class="identifier">MyShmString</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">allocator</span><span class="special"><</span><span class="identifier">MyShmString</span><span class="special">,</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">></span> |
| <span class="identifier">StringAllocator</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">vector</span><span class="special"><</span><span class="identifier">MyShmString</span><span class="special">,</span> <span class="identifier">StringAllocator</span><span class="special">></span> |
| <span class="identifier">MyShmStringVector</span><span class="special">;</span> |
| |
| <span class="comment">//Open shared memory</span> |
| <span class="comment">//Remove shared memory on construction and destruction</span> |
| <span class="keyword">struct</span> <span class="identifier">shm_remove</span> |
| <span class="special">{</span> |
| <span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span> |
| |
| <span class="identifier">managed_shared_memory</span> <span class="identifier">shm</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> <span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="number">10000</span><span class="special">);</span> |
| |
| <span class="comment">//Create allocators</span> |
| <span class="identifier">CharAllocator</span> <span class="identifier">charallocator</span> <span class="special">(</span><span class="identifier">shm</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| <span class="identifier">StringAllocator</span> <span class="identifier">stringallocator</span><span class="special">(</span><span class="identifier">shm</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| |
| <span class="comment">//This string is in only in this process (the pointer pointing to the</span> |
| <span class="comment">//buffer that will hold the text is not in shared memory).</span> |
| <span class="comment">//But the buffer that will hold "this is my text" is allocated from</span> |
| <span class="comment">//shared memory</span> |
| <span class="identifier">MyShmString</span> <span class="identifier">mystring</span><span class="special">(</span><span class="identifier">charallocator</span><span class="special">);</span> |
| <span class="identifier">mystring</span> <span class="special">=</span> <span class="string">"this is my text"</span><span class="special">;</span> |
| |
| <span class="comment">//This vector is only in this process (the pointer pointing to the</span> |
| <span class="comment">//buffer that will hold the MyShmString-s is not in shared memory).</span> |
| <span class="comment">//But the buffer that will hold 10 MyShmString-s is allocated from</span> |
| <span class="comment">//shared memory using StringAllocator. Since strings use a shared</span> |
| <span class="comment">//memory allocator (CharAllocator) the 10 buffers that hold</span> |
| <span class="comment">//"this is my text" text are also in shared memory.</span> |
| <span class="identifier">MyShmStringVector</span> <span class="identifier">myvector</span><span class="special">(</span><span class="identifier">stringallocator</span><span class="special">);</span> |
| <span class="identifier">myvector</span><span class="special">.</span><span class="identifier">insert</span><span class="special">(</span><span class="identifier">myvector</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="number">10</span><span class="special">,</span> <span class="identifier">mystring</span><span class="special">);</span> |
| |
| <span class="comment">//This vector is fully constructed in shared memory. All pointers</span> |
| <span class="comment">//buffers are constructed in the same shared memory segment</span> |
| <span class="comment">//This vector can be safely accessed from other processes.</span> |
| <span class="identifier">MyShmStringVector</span> <span class="special">*</span><span class="identifier">myshmvector</span> <span class="special">=</span> |
| <span class="identifier">shm</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="identifier">MyShmStringVector</span><span class="special">>(</span><span class="string">"myshmvector"</span><span class="special">)(</span><span class="identifier">stringallocator</span><span class="special">);</span> |
| <span class="identifier">myshmvector</span><span class="special">-></span><span class="identifier">insert</span><span class="special">(</span><span class="identifier">myshmvector</span><span class="special">-></span><span class="identifier">begin</span><span class="special">(),</span> <span class="number">10</span><span class="special">,</span> <span class="identifier">mystring</span><span class="special">);</span> |
| |
| <span class="comment">//Destroy vector. This will free all strings that the vector contains</span> |
| <span class="identifier">shm</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">myshmvector</span><span class="special">);</span> |
| <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.allocators_containers.containers_explained.containers_and_move"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.containers_explained.containers_and_move" title="Move semantics in Interprocess containers">Move |
| semantics in Interprocess containers</a> |
| </h4></div></div></div> |
| <p> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> containers support |
| move semantics, which means that the contents of a container can be moved |
| from a container two another one, without any copying. The contents of |
| the source container are transferred to the target container and the source |
| container is left in default-constructed state. |
| </p> |
| <p> |
| When using containers of containers, we can also use move-semantics to |
| insert objects in the container, avoiding unnecessary copies. |
| </p> |
| <p> |
| To transfer the contents of a container to another one, use <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">move</span><span class="special">()</span></code> |
| function, as shown in the example. For more details about functions supporting |
| move-semantics, see the reference section of Boost.Interprocess containers: |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">managed_shared_memory</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">vector</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">string</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">allocator</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cassert</span><span class="special">></span> |
| |
| <span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span> |
| <span class="special">{</span> |
| <span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span> |
| |
| <span class="comment">//Typedefs</span> |
| <span class="keyword">typedef</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span> <span class="identifier">SegmentManager</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">allocator</span><span class="special"><</span><span class="keyword">char</span><span class="special">,</span> <span class="identifier">SegmentManager</span><span class="special">></span> <span class="identifier">CharAllocator</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">basic_string</span><span class="special"><</span><span class="keyword">char</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">char_traits</span><span class="special"><</span><span class="keyword">char</span><span class="special">></span> |
| <span class="special">,</span><span class="identifier">CharAllocator</span><span class="special">></span> <span class="identifier">MyShmString</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">allocator</span><span class="special"><</span><span class="identifier">MyShmString</span><span class="special">,</span> <span class="identifier">SegmentManager</span><span class="special">></span> <span class="identifier">StringAllocator</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">vector</span><span class="special"><</span><span class="identifier">MyShmString</span><span class="special">,</span> <span class="identifier">StringAllocator</span><span class="special">></span> <span class="identifier">MyShmStringVector</span><span class="special">;</span> |
| |
| <span class="comment">//Remove shared memory on construction and destruction</span> |
| <span class="keyword">struct</span> <span class="identifier">shm_remove</span> |
| <span class="special">{</span> |
| <span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span> |
| |
| <span class="identifier">managed_shared_memory</span> <span class="identifier">shm</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> <span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="number">10000</span><span class="special">);</span> |
| |
| <span class="comment">//Create allocators</span> |
| <span class="identifier">CharAllocator</span> <span class="identifier">charallocator</span> <span class="special">(</span><span class="identifier">shm</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| <span class="identifier">StringAllocator</span> <span class="identifier">stringallocator</span><span class="special">(</span><span class="identifier">shm</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| |
| <span class="comment">//Create a vector of strings in shared memory.</span> |
| <span class="identifier">MyShmStringVector</span> <span class="special">*</span><span class="identifier">myshmvector</span> <span class="special">=</span> |
| <span class="identifier">shm</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="identifier">MyShmStringVector</span><span class="special">>(</span><span class="string">"myshmvector"</span><span class="special">)(</span><span class="identifier">stringallocator</span><span class="special">);</span> |
| |
| <span class="comment">//Insert 50 strings in shared memory. The strings will be allocated</span> |
| <span class="comment">//only once and no string copy-constructor will be called when inserting</span> |
| <span class="comment">//strings, leading to a great performance.</span> |
| <span class="identifier">MyShmString</span> <span class="identifier">string_to_compare</span><span class="special">(</span><span class="identifier">charallocator</span><span class="special">);</span> |
| <span class="identifier">string_to_compare</span> <span class="special">=</span> <span class="string">"this is a long, long, long, long, long, long, string..."</span><span class="special">;</span> |
| |
| <span class="identifier">myshmvector</span><span class="special">-></span><span class="identifier">reserve</span><span class="special">(</span><span class="number">50</span><span class="special">);</span> |
| <span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special"><</span> <span class="number">50</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span> |
| <span class="identifier">MyShmString</span> <span class="identifier">move_me</span><span class="special">(</span><span class="identifier">string_to_compare</span><span class="special">);</span> |
| <span class="comment">//In the following line, no string copy-constructor will be called.</span> |
| <span class="comment">//"move_me"'s contents will be transferred to the string created in</span> |
| <span class="comment">//the vector</span> |
| <span class="identifier">myshmvector</span><span class="special">-></span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">move_me</span><span class="special">));</span> |
| |
| <span class="comment">//The source string is in default constructed state</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">move_me</span><span class="special">.</span><span class="identifier">empty</span><span class="special">());</span> |
| |
| <span class="comment">//The newly created string will be equal to the "move_me"'s old contents</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">myshmvector</span><span class="special">-></span><span class="identifier">back</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">string_to_compare</span><span class="special">);</span> |
| <span class="special">}</span> |
| |
| <span class="comment">//Now erase a string...</span> |
| <span class="identifier">myshmvector</span><span class="special">-></span><span class="identifier">pop_back</span><span class="special">();</span> |
| |
| <span class="comment">//...And insert one in the first position.</span> |
| <span class="comment">//No string copy-constructor or assignments will be called, but</span> |
| <span class="comment">//move constructors and move-assignments. No memory allocation</span> |
| <span class="comment">//function will be called in this operations!!</span> |
| <span class="identifier">myshmvector</span><span class="special">-></span><span class="identifier">insert</span><span class="special">(</span><span class="identifier">myshmvector</span><span class="special">-></span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">string_to_compare</span><span class="special">));</span> |
| |
| <span class="comment">//Destroy vector. This will free all strings that the vector contains</span> |
| <span class="identifier">shm</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">myshmvector</span><span class="special">);</span> |
| <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.allocators_containers.containers_explained.containers_of_containers"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.containers_explained.containers_of_containers" title="Containers of containers">Containers |
| of containers</a> |
| </h4></div></div></div> |
| <p> |
| When creating containers of containers, each container needs an allocator. |
| To avoid using several allocators with complex type definitions, we can |
| take advantage of the type erasure provided by void allocators and the |
| ability to implicitly convert void allocators in allocators that allocate |
| other types. |
| </p> |
| <p> |
| Here we have an example that builds a map in shared memory. Key is a string |
| and the mapped type is a class that stores several containers: |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">managed_shared_memory</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">allocator</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">map</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">vector</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">string</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| |
| <span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span> |
| |
| <span class="comment">//Typedefs of allocators and containers</span> |
| <span class="keyword">typedef</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span> <span class="identifier">segment_manager_t</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">allocator</span><span class="special"><</span><span class="keyword">void</span><span class="special">,</span> <span class="identifier">segment_manager_t</span><span class="special">></span> <span class="identifier">void_allocator</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">allocator</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">segment_manager_t</span><span class="special">></span> <span class="identifier">int_allocator</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">int_allocator</span><span class="special">></span> <span class="identifier">int_vector</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">allocator</span><span class="special"><</span><span class="identifier">int_vector</span><span class="special">,</span> <span class="identifier">segment_manager_t</span><span class="special">></span> <span class="identifier">int_vector_allocator</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">vector</span><span class="special"><</span><span class="identifier">int_vector</span><span class="special">,</span> <span class="identifier">int_vector_allocator</span><span class="special">></span> <span class="identifier">int_vector_vector</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">allocator</span><span class="special"><</span><span class="keyword">char</span><span class="special">,</span> <span class="identifier">segment_manager_t</span><span class="special">></span> <span class="identifier">char_allocator</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">basic_string</span><span class="special"><</span><span class="keyword">char</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">char_traits</span><span class="special"><</span><span class="keyword">char</span><span class="special">>,</span> <span class="identifier">char_allocator</span><span class="special">></span> <span class="identifier">char_string</span><span class="special">;</span> |
| |
| <span class="keyword">class</span> <span class="identifier">complex_data</span> |
| <span class="special">{</span> |
| <span class="keyword">int</span> <span class="identifier">id_</span><span class="special">;</span> |
| <span class="identifier">char_string</span> <span class="identifier">char_string_</span><span class="special">;</span> |
| <span class="identifier">int_vector_vector</span> <span class="identifier">int_vector_vector_</span><span class="special">;</span> |
| |
| <span class="keyword">public</span><span class="special">:</span> |
| <span class="comment">//Since void_allocator is convertible to any other allocator<T>, we can simplify</span> |
| <span class="comment">//the initialization taking just one allocator for all inner containers.</span> |
| <span class="identifier">complex_data</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">id</span><span class="special">,</span> <span class="keyword">const</span> <span class="keyword">char</span> <span class="special">*</span><span class="identifier">name</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">void_allocator</span> <span class="special">&</span><span class="identifier">void_alloc</span><span class="special">)</span> |
| <span class="special">:</span> <span class="identifier">id_</span><span class="special">(</span><span class="identifier">id</span><span class="special">),</span> <span class="identifier">char_string_</span><span class="special">(</span><span class="identifier">name</span><span class="special">,</span> <span class="identifier">void_alloc</span><span class="special">),</span> <span class="identifier">int_vector_vector_</span><span class="special">(</span><span class="identifier">void_alloc</span><span class="special">)</span> |
| <span class="special">{}</span> |
| <span class="comment">//Other members...</span> |
| <span class="special">};</span> |
| |
| <span class="comment">//Definition of the map holding a string as key and complex_data as mapped type</span> |
| <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span><span class="keyword">const</span> <span class="identifier">char_string</span><span class="special">,</span> <span class="identifier">complex_data</span><span class="special">></span> <span class="identifier">map_value_type</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span><span class="identifier">char_string</span><span class="special">,</span> <span class="identifier">complex_data</span><span class="special">></span> <span class="identifier">movable_to_map_value_type</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">allocator</span><span class="special"><</span><span class="identifier">map_value_type</span><span class="special">,</span> <span class="identifier">segment_manager_t</span><span class="special">></span> <span class="identifier">map_value_type_allocator</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">map</span><span class="special"><</span> <span class="identifier">char_string</span><span class="special">,</span> <span class="identifier">complex_data</span> |
| <span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">less</span><span class="special"><</span><span class="identifier">char_string</span><span class="special">>,</span> <span class="identifier">map_value_type_allocator</span><span class="special">></span> <span class="identifier">complex_map_type</span><span class="special">;</span> |
| |
| <span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span> |
| <span class="special">{</span> |
| <span class="comment">//Remove shared memory on construction and destruction</span> |
| <span class="keyword">struct</span> <span class="identifier">shm_remove</span> |
| <span class="special">{</span> |
| <span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span> |
| |
| <span class="comment">//Create shared memory</span> |
| <span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span><span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="number">65536</span><span class="special">);</span> |
| |
| <span class="comment">//An allocator convertible to any allocator<T, segment_manager_t> type</span> |
| <span class="identifier">void_allocator</span> <span class="identifier">alloc_inst</span> <span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| |
| <span class="comment">//Construct the shared memory map and fill it</span> |
| <span class="identifier">complex_map_type</span> <span class="special">*</span><span class="identifier">mymap</span> <span class="special">=</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="identifier">complex_map_type</span><span class="special">></span> |
| <span class="comment">//(object name), (first ctor parameter, second ctor parameter)</span> |
| <span class="special">(</span><span class="string">"MyMap"</span><span class="special">)(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">less</span><span class="special"><</span><span class="identifier">char_string</span><span class="special">>(),</span> <span class="identifier">alloc_inst</span><span class="special">);</span> |
| |
| <span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special"><</span> <span class="number">100</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span> |
| <span class="comment">//Both key(string) and value(complex_data) need an allocator in their constructors</span> |
| <span class="identifier">char_string</span> <span class="identifier">key_object</span><span class="special">(</span><span class="identifier">alloc_inst</span><span class="special">);</span> |
| <span class="identifier">complex_data</span> <span class="identifier">mapped_object</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="string">"default_name"</span><span class="special">,</span> <span class="identifier">alloc_inst</span><span class="special">);</span> |
| <span class="identifier">map_value_type</span> <span class="identifier">value</span><span class="special">(</span><span class="identifier">key_object</span><span class="special">,</span> <span class="identifier">mapped_object</span><span class="special">);</span> |
| <span class="comment">//Modify values and insert them in the map</span> |
| <span class="identifier">mymap</span><span class="special">-></span><span class="identifier">insert</span><span class="special">(</span><span class="identifier">value</span><span class="special">);</span> |
| <span class="special">}</span> |
| <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| </div> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="interprocess.allocators_containers.additional_containers"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.additional_containers" title="Boost containers compatible with Boost.Interprocess">Boost |
| containers compatible with Boost.Interprocess</a> |
| </h3></div></div></div> |
| <div class="toc"><dl class="toc"> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.additional_containers.unordered">Boost |
| unordered containers</a></span></dt> |
| <dt><span class="section"><a href="allocators_containers.html#interprocess.allocators_containers.additional_containers.multi_index">Boost.MultiIndex |
| containers</a></span></dt> |
| </dl></div> |
| <p> |
| As mentioned, container developers might need to change their implementation |
| to make them compatible with Boost.Interprocess, because implementation usually |
| ignore allocators with smart pointers. Hopefully several Boost containers |
| are compatible with <span class="bold"><strong>Interprocess</strong></span>. |
| </p> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.allocators_containers.additional_containers.unordered"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.additional_containers.unordered" title="Boost unordered containers">Boost |
| unordered containers</a> |
| </h4></div></div></div> |
| <p> |
| <span class="bold"><strong>Boost.Unordered</strong></span> containers are compatible |
| with Interprocess, so programmers can store hash containers in shared memory |
| and memory mapped files. Here is a small example storing <code class="computeroutput"><span class="identifier">unordered_map</span></code> in shared memory: |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">managed_shared_memory</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">allocator</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| |
| |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">unordered_map</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> <span class="comment">//boost::unordered_map</span> |
| |
| |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">functional</span><span class="special">></span> <span class="comment">//std::equal_to</span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">functional</span><span class="special">/</span><span class="identifier">hash</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> <span class="comment">//boost::hash</span> |
| |
| |
| <span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span> |
| <span class="special">{</span> |
| <span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span> |
| <span class="comment">//Remove shared memory on construction and destruction</span> |
| <span class="keyword">struct</span> <span class="identifier">shm_remove</span> |
| <span class="special">{</span> |
| <span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span> |
| |
| <span class="comment">//Create shared memory</span> |
| <span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> <span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="number">65536</span><span class="special">);</span> |
| |
| <span class="comment">//Note that unordered_map<Key, MappedType>'s value_type is std::pair<const Key, MappedType>,</span> |
| <span class="comment">//so the allocator must allocate that pair.</span> |
| <span class="keyword">typedef</span> <span class="keyword">int</span> <span class="identifier">KeyType</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="keyword">float</span> <span class="identifier">MappedType</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span><span class="keyword">const</span> <span class="keyword">int</span><span class="special">,</span> <span class="keyword">float</span><span class="special">></span> <span class="identifier">ValueType</span><span class="special">;</span> |
| |
| <span class="comment">//Typedef the allocator</span> |
| <span class="keyword">typedef</span> <span class="identifier">allocator</span><span class="special"><</span><span class="identifier">ValueType</span><span class="special">,</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">></span> <span class="identifier">ShmemAllocator</span><span class="special">;</span> |
| |
| <span class="comment">//Alias an unordered_map of ints that uses the previous STL-like allocator.</span> |
| <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">unordered_map</span> |
| <span class="special"><</span> <span class="identifier">KeyType</span> <span class="special">,</span> <span class="identifier">MappedType</span> |
| <span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hash</span><span class="special"><</span><span class="identifier">KeyType</span><span class="special">></span> <span class="special">,</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">equal_to</span><span class="special"><</span><span class="identifier">KeyType</span><span class="special">></span> |
| <span class="special">,</span> <span class="identifier">ShmemAllocator</span><span class="special">></span> |
| <span class="identifier">MyHashMap</span><span class="special">;</span> |
| |
| <span class="comment">//Construct a shared memory hash map.</span> |
| <span class="comment">//Note that the first parameter is the initial bucket count and</span> |
| <span class="comment">//after that, the hash function, the equality function and the allocator</span> |
| <span class="identifier">MyHashMap</span> <span class="special">*</span><span class="identifier">myhashmap</span> <span class="special">=</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="identifier">MyHashMap</span><span class="special">>(</span><span class="string">"MyHashMap"</span><span class="special">)</span> <span class="comment">//object name</span> |
| <span class="special">(</span> <span class="number">3</span><span class="special">,</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">hash</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(),</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">equal_to</span><span class="special"><</span><span class="keyword">int</span><span class="special">>()</span> <span class="comment">//</span> |
| <span class="special">,</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_allocator</span><span class="special"><</span><span class="identifier">ValueType</span><span class="special">>());</span> <span class="comment">//allocator instance</span> |
| |
| <span class="comment">//Insert data in the hash map</span> |
| <span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special"><</span> <span class="number">100</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span> |
| <span class="identifier">myhashmap</span><span class="special">-></span><span class="identifier">insert</span><span class="special">(</span><span class="identifier">ValueType</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="special">(</span><span class="keyword">float</span><span class="special">)</span><span class="identifier">i</span><span class="special">));</span> |
| <span class="special">}</span> |
| <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.allocators_containers.additional_containers.multi_index"></a><a class="link" href="allocators_containers.html#interprocess.allocators_containers.additional_containers.multi_index" title="Boost.MultiIndex containers">Boost.MultiIndex |
| containers</a> |
| </h4></div></div></div> |
| <p> |
| The widely used <span class="bold"><strong>Boost.MultiIndex</strong></span> library |
| is compatible with <span class="bold"><strong>Boost.Interprocess</strong></span> |
| so we can construct pretty good databases in shared memory. Constructing |
| databases in shared memory is a bit tougher than in normal memory, usually |
| because those databases contain strings and those strings need to be placed |
| in shared memory. Shared memory strings require an allocator in their constructors |
| so this usually makes object insertion a bit more complicated. |
| </p> |
| <p> |
| Here is an example that shows how to put a multi index container in shared |
| memory: |
| </p> |
| <p> |
| </p> |
| <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">managed_shared_memory</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">allocators</span><span class="special">/</span><span class="identifier">allocator</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">string</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| |
| |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">multi_index_container</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">multi_index</span><span class="special">/</span><span class="identifier">member</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">multi_index</span><span class="special">/</span><span class="identifier">ordered_index</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| |
| |
| <span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span> |
| <span class="keyword">namespace</span> <span class="identifier">bmi</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">multi_index</span><span class="special">;</span> |
| |
| <span class="keyword">typedef</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">allocator</span><span class="special"><</span><span class="keyword">char</span><span class="special">>::</span><span class="identifier">type</span> <span class="identifier">char_allocator</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">basic_string</span><span class="special"><</span><span class="keyword">char</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">char_traits</span><span class="special"><</span><span class="keyword">char</span><span class="special">>,</span> <span class="identifier">char_allocator</span><span class="special">></span><span class="identifier">shm_string</span><span class="special">;</span> |
| |
| <span class="comment">//Data to insert in shared memory</span> |
| <span class="keyword">struct</span> <span class="identifier">employee</span> |
| <span class="special">{</span> |
| <span class="keyword">int</span> <span class="identifier">id</span><span class="special">;</span> |
| <span class="keyword">int</span> <span class="identifier">age</span><span class="special">;</span> |
| <span class="identifier">shm_string</span> <span class="identifier">name</span><span class="special">;</span> |
| <span class="identifier">employee</span><span class="special">(</span> <span class="keyword">int</span> <span class="identifier">id_</span> |
| <span class="special">,</span> <span class="keyword">int</span> <span class="identifier">age_</span> |
| <span class="special">,</span> <span class="keyword">const</span> <span class="keyword">char</span> <span class="special">*</span><span class="identifier">name_</span> |
| <span class="special">,</span> <span class="keyword">const</span> <span class="identifier">char_allocator</span> <span class="special">&</span><span class="identifier">a</span><span class="special">)</span> |
| <span class="special">:</span> <span class="identifier">id</span><span class="special">(</span><span class="identifier">id_</span><span class="special">),</span> <span class="identifier">age</span><span class="special">(</span><span class="identifier">age_</span><span class="special">),</span> <span class="identifier">name</span><span class="special">(</span><span class="identifier">name_</span><span class="special">,</span> <span class="identifier">a</span><span class="special">)</span> |
| <span class="special">{}</span> |
| <span class="special">};</span> |
| |
| <span class="comment">//Tags</span> |
| <span class="keyword">struct</span> <span class="identifier">id</span><span class="special">{};</span> |
| <span class="keyword">struct</span> <span class="identifier">age</span><span class="special">{};</span> |
| <span class="keyword">struct</span> <span class="identifier">name</span><span class="special">{};</span> |
| |
| <span class="comment">// Define a multi_index_container of employees with following indices:</span> |
| <span class="comment">// - a unique index sorted by employee::int,</span> |
| <span class="comment">// - a non-unique index sorted by employee::name,</span> |
| <span class="comment">// - a non-unique index sorted by employee::age.</span> |
| <span class="keyword">typedef</span> <span class="identifier">bmi</span><span class="special">::</span><span class="identifier">multi_index_container</span><span class="special"><</span> |
| <span class="identifier">employee</span><span class="special">,</span> |
| <span class="identifier">bmi</span><span class="special">::</span><span class="identifier">indexed_by</span><span class="special"><</span> |
| <span class="identifier">bmi</span><span class="special">::</span><span class="identifier">ordered_unique</span> |
| <span class="special"><</span><span class="identifier">bmi</span><span class="special">::</span><span class="identifier">tag</span><span class="special"><</span><span class="identifier">id</span><span class="special">>,</span> <span class="identifier">BOOST_MULTI_INDEX_MEMBER</span><span class="special">(</span><span class="identifier">employee</span><span class="special">,</span><span class="keyword">int</span><span class="special">,</span><span class="identifier">id</span><span class="special">)>,</span> |
| <span class="identifier">bmi</span><span class="special">::</span><span class="identifier">ordered_non_unique</span><span class="special"><</span> |
| <span class="identifier">bmi</span><span class="special">::</span><span class="identifier">tag</span><span class="special"><</span><span class="identifier">name</span><span class="special">>,</span><span class="identifier">BOOST_MULTI_INDEX_MEMBER</span><span class="special">(</span><span class="identifier">employee</span><span class="special">,</span><span class="identifier">shm_string</span><span class="special">,</span><span class="identifier">name</span><span class="special">)>,</span> |
| <span class="identifier">bmi</span><span class="special">::</span><span class="identifier">ordered_non_unique</span> |
| <span class="special"><</span><span class="identifier">bmi</span><span class="special">::</span><span class="identifier">tag</span><span class="special"><</span><span class="identifier">age</span><span class="special">>,</span> <span class="identifier">BOOST_MULTI_INDEX_MEMBER</span><span class="special">(</span><span class="identifier">employee</span><span class="special">,</span><span class="keyword">int</span><span class="special">,</span><span class="identifier">age</span><span class="special">)></span> <span class="special">>,</span> |
| <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">allocator</span><span class="special"><</span><span class="identifier">employee</span><span class="special">>::</span><span class="identifier">type</span> |
| <span class="special">></span> <span class="identifier">employee_set</span><span class="special">;</span> |
| |
| <span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span> |
| <span class="special">{</span> |
| <span class="comment">//Remove shared memory on construction and destruction</span> |
| <span class="keyword">struct</span> <span class="identifier">shm_remove</span> |
| <span class="special">{</span> |
| <span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span> |
| <span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span> |
| |
| <span class="comment">//Create shared memory</span> |
| <span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span><span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="number">65536</span><span class="special">);</span> |
| |
| <span class="comment">//Construct the multi_index in shared memory</span> |
| <span class="identifier">employee_set</span> <span class="special">*</span><span class="identifier">es</span> <span class="special">=</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="identifier">employee_set</span><span class="special">></span> |
| <span class="special">(</span><span class="string">"My MultiIndex Container"</span><span class="special">)</span> <span class="comment">//Container's name in shared memory</span> |
| <span class="special">(</span> <span class="identifier">employee_set</span><span class="special">::</span><span class="identifier">ctor_args_list</span><span class="special">()</span> |
| <span class="special">,</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_allocator</span><span class="special"><</span><span class="identifier">employee</span><span class="special">>());</span> <span class="comment">//Ctor parameters</span> |
| |
| <span class="comment">//Now insert elements</span> |
| <span class="identifier">char_allocator</span> <span class="identifier">ca</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_allocator</span><span class="special"><</span><span class="keyword">char</span><span class="special">>());</span> |
| <span class="identifier">es</span><span class="special">-></span><span class="identifier">insert</span><span class="special">(</span><span class="identifier">employee</span><span class="special">(</span><span class="number">0</span><span class="special">,</span><span class="number">31</span><span class="special">,</span> <span class="string">"Joe"</span><span class="special">,</span> <span class="identifier">ca</span><span class="special">));</span> |
| <span class="identifier">es</span><span class="special">-></span><span class="identifier">insert</span><span class="special">(</span><span class="identifier">employee</span><span class="special">(</span><span class="number">1</span><span class="special">,</span><span class="number">27</span><span class="special">,</span> <span class="string">"Robert"</span><span class="special">,</span> <span class="identifier">ca</span><span class="special">));</span> |
| <span class="identifier">es</span><span class="special">-></span><span class="identifier">insert</span><span class="special">(</span><span class="identifier">employee</span><span class="special">(</span><span class="number">2</span><span class="special">,</span><span class="number">40</span><span class="special">,</span> <span class="string">"John"</span><span class="special">,</span> <span class="identifier">ca</span><span class="special">));</span> |
| <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| </div> |
| <p> |
| Programmers can place <span class="bold"><strong>Boost.CircularBuffer</strong></span> |
| containers in sharecd memory provided they disable debugging facilities with |
| defines <code class="computeroutput"><span class="identifier">BOOST_CB_DISABLE_DEBUG</span></code> |
| or the more general <code class="computeroutput"><span class="identifier">NDEBUG</span></code>. |
| The reason is that those debugging facilities are only compatible with raw |
| pointers. |
| </p> |
| </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-2012 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="managed_memory_segments.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="memory_algorithms.html"><img src="../../../doc/src/images/next.png" alt="Next"></a> |
| </div> |
| </body> |
| </html> |