| <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.75.2"> |
| <link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset"> |
| <link rel="up" href="../interprocess.html" title="Chapter 9. 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> |
| <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> |
| <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> |
| <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" 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" 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> |
| <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" 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" 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> |
| <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" 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" 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<span class="bold"><strong>. This is because in practice, |
| there wasn't need of allocators with a pointer typedef |
| different from T</strong></span> 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" 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" 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" 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" 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" 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" 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" 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" 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" 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">interprocess</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">interprocess</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">interprocess</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> |
| <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 - 2010 Ion Gaztanaga<p> |
| Distributed under the Boost Software License, Version 1.0. (See accompanying |
| file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) |
| </p> |
| </div></td> |
| </tr></table> |
| <hr> |
| <div class="spirit-nav"> |
| <a accesskey="p" href="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> |