| <html> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> |
| <title>Managed Memory Segments</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="synchronization_mechanisms.html" title="Synchronization mechanisms"> |
| <link rel="next" href="allocators_containers.html" title="Allocators, containers and 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="synchronization_mechanisms.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="allocators_containers.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.managed_memory_segments"></a><a class="link" href="managed_memory_segments.html" title="Managed Memory Segments">Managed Memory Segments</a> |
| </h2></div></div></div> |
| <div class="toc"><dl> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.making_ipc_easy">Making Interprocess Data Communication Easy</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_shared_memory">Managed Shared Memory</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_mapped_files">Managed Mapped File</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features">Managed Memory Segment Features</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_advanced_features">Managed Memory Segment Advanced Features</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_heap_memory_external_buffer">Managed Heap Memory And Managed External Buffer</a></span></dt> |
| </dl></div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="interprocess.managed_memory_segments.making_ipc_easy"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.making_ipc_easy" title="Making Interprocess Data Communication Easy">Making Interprocess Data Communication Easy</a> |
| </h3></div></div></div> |
| <div class="toc"><dl> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.making_ipc_easy.managed_memory_segments_intro">Introduction</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.making_ipc_easy.managed_memory_segment_int">Declaration of managed memory segment classes</a></span></dt> |
| </dl></div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.making_ipc_easy.managed_memory_segments_intro"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.making_ipc_easy.managed_memory_segments_intro" title="Introduction">Introduction</a> |
| </h4></div></div></div> |
| <p> |
| As we have seen, <span class="bold"><strong>Boost.Interprocess</strong></span> offers some basic classes to create shared memory |
| objects and file mappings and map those mappable classes to the process' address space. |
| </p> |
| <p> |
| However, managing those memory segments is not not easy for non-trivial tasks. |
| A mapped region is a fixed-length memory buffer and creating and destroying objects |
| of any type dynamically, requires a lot of work, since it would require programming |
| a memory management algorithm to allocate portions of that segment. |
| Many times, we also want to associate names to objects created in shared memory, so |
| all the processes can find the object using the name. |
| </p> |
| <p> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> offers 4 managed memory segment classes: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| To manage a shared memory mapped region (<span class="bold"><strong>basic_managed_shared_memory</strong></span> class). |
| |
| </li> |
| <li class="listitem"> |
| To manage a memory mapped file (<span class="bold"><strong>basic_managed_mapped_file</strong></span>). |
| |
| </li> |
| <li class="listitem"> |
| To manage a heap allocated (<code class="computeroutput"><span class="keyword">operator</span> <span class="keyword">new</span></code>) memory buffer (<span class="bold"><strong>basic_managed_heap_memory</strong></span> class). |
| |
| </li> |
| <li class="listitem"> |
| To manage a user provided fixed size buffer (<span class="bold"><strong>basic_managed_external_buffer</strong></span> class). |
| |
| </li> |
| </ul></div> |
| <p> |
| The first two classes manage memory segments that can be shared between processes. The |
| third is useful to create complex data-bases to be sent though other mechanisms like |
| message queues to other processes. The fourth class can manage any fixed size memory |
| buffer. The first two classes will be explained in the next two sections. |
| <span class="bold"><strong>basic_managed_heap_memory</strong></span> and <span class="bold"><strong>basic_managed_external_buffer</strong></span> will be explained later. |
| </p> |
| <p> |
| The most important services of a managed memory segment are: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| Dynamic allocation of portions of a memory the segment. |
| |
| </li> |
| <li class="listitem"> |
| Construction of C++ objects in the memory segment. These objects can be anonymous |
| or we can associate a name to them. |
| |
| </li> |
| <li class="listitem"> |
| Searching capabilities for named objects. |
| |
| </li> |
| <li class="listitem"> |
| Customization of many features: memory allocation algorithm, index types or |
| character types. |
| |
| </li> |
| <li class="listitem"> |
| Atomic constructions and destructions so that if the segment is shared between |
| two processes it's impossible to create two objects associated with the same |
| name, simplifying synchronization. |
| |
| </li> |
| </ul></div> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.making_ipc_easy.managed_memory_segment_int"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.making_ipc_easy.managed_memory_segment_int" title="Declaration of managed memory segment classes">Declaration of managed memory segment classes</a> |
| </h4></div></div></div> |
| <p> |
| All <span class="bold"><strong>Boost.Interprocess</strong></span> managed memory segment classes are templatized classes |
| that can be customized by the user: |
| </p> |
| <pre class="programlisting"><span class="keyword">template</span> |
| <span class="special"><</span> |
| <span class="keyword">class</span> <span class="identifier">CharType</span><span class="special">,</span> |
| <span class="keyword">class</span> <span class="identifier">MemoryAlgorithm</span><span class="special">,</span> |
| <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">IndexConfig</span><span class="special">></span> <span class="keyword">class</span> <span class="identifier">IndexType</span> |
| <span class="special">></span> |
| <span class="keyword">class</span> <span class="identifier">basic_managed_shared_memory</span> <span class="special">/</span> <span class="identifier">basic_managed_mapped_file</span> <span class="special">/</span> |
| <span class="identifier">basic_managed_heap_memory</span> <span class="special">/</span> <span class="identifier">basic_external_buffer</span><span class="special">;</span> |
| </pre> |
| <p> |
| These classes can be customized with the following template parameters: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| <span class="bold"><strong>CharType</strong></span> is the type of the character that will be used to identify |
| the created named objects (for example, <span class="bold"><strong>char</strong></span> or <span class="bold"><strong>wchar_t</strong></span>) |
| |
| </li> |
| <li class="listitem"> |
| <p class="simpara"> |
| <span class="bold"><strong>MemoryAlgorithm</strong></span> is the memory algorithm used to allocate portions of the |
| segment (for example, rbtree_best_fit ). The internal typedefs of the |
| memory algorithm also define: |
| |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="circle"> |
| <li class="listitem"> |
| The synchronization type (<code class="computeroutput"><span class="identifier">MemoryAlgorithm</span><span class="special">::</span><span class="identifier">mutex_family</span></code>) to be used |
| in all allocation operations. |
| This allows the use of user-defined mutexes or avoiding internal |
| locking (maybe code will be externally synchronized by the user). |
| |
| </li> |
| <li class="listitem"> |
| The Pointer type (<code class="computeroutput"><span class="identifier">MemoryAlgorithm</span><span class="special">::</span><span class="identifier">void_pointer</span></code>) to be used |
| by the memory allocation algorithm or additional helper structures |
| (like a map to maintain object/name associations). All STL compatible |
| allocators and containers to be used with this managed memory segment |
| will use this pointer type. The pointer type |
| will define if the managed memory segment can be mapped between |
| several processes. For example, if <code class="computeroutput"><span class="identifier">void_pointer</span></code> is <code class="computeroutput"><span class="identifier">offset_ptr</span><span class="special"><</span><span class="keyword">void</span><span class="special">></span></code> |
| we will be able to map the managed segment in different base |
| addresses in each process. If <code class="computeroutput"><span class="identifier">void_pointer</span></code> is <code class="computeroutput"><span class="keyword">void</span><span class="special">*</span></code> only fixed |
| address mapping could be used. |
| |
| </li> |
| <li class="listitem"> |
| See <a class="link" href="customizing_interprocess.html#interprocess.customizing_interprocess.custom_interprocess_alloc" title="Writing a new shared memory allocation algorithm">Writing a new memory |
| allocation algorithm</a> for more details about memory algorithms. |
| |
| </li> |
| </ul></div> |
| </li> |
| <li class="listitem"> |
| <span class="bold"><strong>IndexType</strong></span> is the type of index that will be used to store the name-object |
| association (for example, a map, a hash-map, or an ordered vector). |
| |
| </li> |
| </ul></div> |
| <p> |
| This way, we can use <code class="computeroutput"><span class="keyword">char</span></code> or <code class="computeroutput"><span class="keyword">wchar_t</span></code> strings to identify created C++ |
| objects in the memory segment, we can plug new shared memory allocation |
| algorithms, and use the index type that is best suited to our needs. |
| </p> |
| </div> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_shared_memory"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_shared_memory" title="Managed Shared Memory">Managed Shared Memory</a> |
| </h3></div></div></div> |
| <div class="toc"><dl> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_shared_memory.managed_memory_common_shm">Common Managed Shared Memory Classes</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_shared_memory.constructing_managed_shared_memories">Constructing Managed Shared Memory</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_shared_memory.windows_managed_memory_common_shm">Using native windows shared memory</a></span></dt> |
| </dl></div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_shared_memory.managed_memory_common_shm"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_shared_memory.managed_memory_common_shm" title="Common Managed Shared Memory Classes">Common Managed Shared Memory Classes</a> |
| </h4></div></div></div> |
| <p> |
| As seen, <span class="bold"><strong>basic_managed_shared_memory</strong></span> offers a great variety of customization. But |
| for the average user, a common, default shared memory named object creation is needed. |
| Because of this, <span class="bold"><strong>Boost.Interprocess</strong></span> defines the most common managed shared memory |
| specializations: |
| </p> |
| <pre class="programlisting"><span class="comment">//!Defines a managed shared memory with c-strings as keys for named objects, |
| </span><span class="comment">//!the default memory algorithm (with process-shared mutexes, |
| </span><span class="comment">//!and offset_ptr as internal pointers) as memory allocation algorithm |
| </span><span class="comment">//!and the default index type as the index. |
| </span><span class="comment">//!This class allows the shared memory to be mapped in different base |
| </span><span class="comment">//!in different processes |
| </span><span class="keyword">typedef</span> |
| <span class="identifier">basic_managed_shared_memory</span><span class="special"><</span><span class="keyword">char</span> |
| <span class="special">,/*</span><span class="identifier">Default</span> <span class="identifier">memory</span> <span class="identifier">algorithm</span> <span class="identifier">defining</span> <span class="identifier">offset_ptr</span><span class="special"><</span><span class="keyword">void</span><span class="special">></span> <span class="identifier">as</span> <span class="identifier">void_pointer</span><span class="special">*/</span> |
| <span class="special">,/*</span><span class="identifier">Default</span> <span class="identifier">index</span> <span class="identifier">type</span><span class="special">*/></span> |
| <span class="identifier">managed_shared_memory</span><span class="special">;</span> |
| |
| <span class="comment">//!Defines a managed shared memory with wide strings as keys for named objects, |
| </span><span class="comment">//!the default memory algorithm (with process-shared mutexes, |
| </span><span class="comment">//!and offset_ptr as internal pointers) as memory allocation algorithm |
| </span><span class="comment">//!and the default index type as the index. |
| </span><span class="comment">//!This class allows the shared memory to be mapped in different base |
| </span><span class="comment">//!in different processes |
| </span><span class="keyword">typedef</span> |
| <span class="identifier">basic_managed_shared_memory</span><span class="special"><</span><span class="keyword">wchar_t</span> |
| <span class="special">,/*</span><span class="identifier">Default</span> <span class="identifier">memory</span> <span class="identifier">algorithm</span> <span class="identifier">defining</span> <span class="identifier">offset_ptr</span><span class="special"><</span><span class="keyword">void</span><span class="special">></span> <span class="identifier">as</span> <span class="identifier">void_pointer</span><span class="special">*/</span> |
| <span class="special">,/*</span><span class="identifier">Default</span> <span class="identifier">index</span> <span class="identifier">type</span><span class="special">*/></span> |
| <span class="identifier">wmanaged_shared_memory</span><span class="special">;</span> |
| </pre> |
| <p> |
| <code class="computeroutput"><span class="identifier">managed_shared_memory</span></code> allocates objects in shared memory associated with a c-string and |
| <code class="computeroutput"><span class="identifier">wmanaged_shared_memory</span></code> allocates objects in shared memory associated with a wchar_t null |
| terminated string. Both define the pointer type as <code class="computeroutput"><span class="identifier">offset_ptr</span><span class="special"><</span><span class="keyword">void</span><span class="special">></span></code> so they can be |
| used to map the shared memory at different base addresses in different processes. |
| </p> |
| <p> |
| If the user wants to map the shared memory in the same address in all processes and |
| want to use raw pointers internally instead of offset pointers, <span class="bold"><strong>Boost.Interprocess</strong></span> |
| defines the following types: |
| </p> |
| <pre class="programlisting"><span class="comment">//!Defines a managed shared memory with c-strings as keys for named objects, |
| </span><span class="comment">//!the default memory algorithm (with process-shared mutexes, |
| </span><span class="comment">//!and offset_ptr as internal pointers) as memory allocation algorithm |
| </span><span class="comment">//!and the default index type as the index. |
| </span><span class="comment">//!This class allows the shared memory to be mapped in different base |
| </span><span class="comment">//!in different processes*/ |
| </span><span class="keyword">typedef</span> <span class="identifier">basic_managed_shared_memory</span> |
| <span class="special"><</span><span class="keyword">char</span> |
| <span class="special">,/*</span><span class="identifier">Default</span> <span class="identifier">memory</span> <span class="identifier">algorithm</span> <span class="identifier">defining</span> <span class="keyword">void</span> <span class="special">*</span> <span class="identifier">as</span> <span class="identifier">void_pointer</span><span class="special">*/</span> |
| <span class="special">,/*</span><span class="identifier">Default</span> <span class="identifier">index</span> <span class="identifier">type</span><span class="special">*/></span> |
| <span class="identifier">fixed_managed_shared_memory</span><span class="special">;</span> |
| |
| <span class="comment">//!Defines a managed shared memory with wide strings as keys for named objects, |
| </span><span class="comment">//!the default memory algorithm (with process-shared mutexes, |
| </span><span class="comment">//!and offset_ptr as internal pointers) as memory allocation algorithm |
| </span><span class="comment">//!and the default index type as the index. |
| </span><span class="comment">//!This class allows the shared memory to be mapped in different base |
| </span><span class="comment">//!in different processes |
| </span><span class="keyword">typedef</span> <span class="identifier">basic_managed_shared_memory</span> |
| <span class="special"><</span><span class="keyword">wchar_t</span> |
| <span class="special">,/*</span><span class="identifier">Default</span> <span class="identifier">memory</span> <span class="identifier">algorithm</span> <span class="identifier">defining</span> <span class="keyword">void</span> <span class="special">*</span> <span class="identifier">as</span> <span class="identifier">void_pointer</span><span class="special">*/</span> |
| <span class="special">,/*</span><span class="identifier">Default</span> <span class="identifier">index</span> <span class="identifier">type</span><span class="special">*/></span> |
| <span class="identifier">wfixed_managed_shared_memory</span><span class="special">;</span> |
| </pre> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_shared_memory.constructing_managed_shared_memories"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_shared_memory.constructing_managed_shared_memories" title="Constructing Managed Shared Memory">Constructing Managed Shared Memory</a> |
| </h4></div></div></div> |
| <p> |
| Managed shared memory is an advanced class that combines a shared memory object |
| and a mapped region that covers all the shared memory object. That means that |
| when we <span class="bold"><strong>create</strong></span> a new managed shared memory: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| A new shared memory object is created. |
| |
| </li> |
| <li class="listitem"> |
| The whole shared memory object is mapped in the process' address space. |
| |
| </li> |
| <li class="listitem"> |
| Some helper objects are constructed (name-object index, internal synchronization |
| objects, internal variables...) in the mapped region to implement |
| managed memory segment features. |
| |
| </li> |
| </ul></div> |
| <p> |
| When we <span class="bold"><strong>open</strong></span> a managed shared memory |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| A shared memory object is opened. |
| |
| </li> |
| <li class="listitem"> |
| The whole shared memory object is mapped in the process' address space. |
| |
| </li> |
| </ul></div> |
| <p> |
| To use a managed shared memory, 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">managed_shared_memory</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <pre class="programlisting"><span class="comment">//1. Creates a new shared memory object |
| </span><span class="comment">// called "MySharedMemory". |
| </span><span class="comment">//2. Maps the whole object to this |
| </span><span class="comment">// process' address space. |
| </span><span class="comment">//3. Constructs some objects in shared memory |
| </span><span class="comment">// to implement managed features. |
| </span><span class="comment">//!! If anything fails, throws interprocess_exception |
| </span><span class="comment">// |
| </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="comment">//Shared memory object name |
| </span> <span class="special">,</span> <span class="number">65536</span><span class="special">);</span> <span class="comment">//Shared memory object size in bytes |
| </span></pre> |
| <pre class="programlisting"><span class="comment">//1. Opens a shared memory object |
| </span><span class="comment">// called "MySharedMemory". |
| </span><span class="comment">//2. Maps the whole object to this |
| </span><span class="comment">// process' address space. |
| </span><span class="comment">//3. Obtains pointers to constructed internal objects |
| </span><span class="comment">// to implement managed features. |
| </span><span class="comment">//!! If anything fails, throws interprocess_exception |
| </span><span class="comment">// |
| </span><span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span> <span class="special">(</span><span class="identifier">open_only</span><span class="special">,</span> <span class="string">"MySharedMemory"</span><span class="special">);//</span><span class="identifier">Shared</span> <span class="identifier">memory</span> <span class="identifier">object</span> <span class="identifier">name</span> |
| </pre> |
| <pre class="programlisting"><span class="comment">//1. If the segment was previously created |
| </span><span class="comment">// equivalent to "open_only". |
| </span><span class="comment">//2. Otherwise, equivalent to "open_only" (size is ignored) |
| </span><span class="comment">//!! If anything fails, throws interprocess_exception |
| </span><span class="comment">// |
| </span><span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span> <span class="special">(</span> <span class="identifier">open_or_create</span> |
| <span class="special">,</span> <span class="string">"MySharedMemory"</span> <span class="comment">//Shared memory object name |
| </span> <span class="special">,</span> <span class="number">65536</span><span class="special">);</span> <span class="comment">//Shared memory object size in bytes |
| </span></pre> |
| <p> |
| When the <code class="computeroutput"><span class="identifier">managed_shared_memory</span></code> object is destroyed, the shared memory |
| object is automatically unmapped, and all the resources are freed. To remove |
| the shared memory object from the system you must use the <code class="computeroutput"><span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span></code> |
| function. Shared memory object removing might fail if any |
| process still has the shared memory object mapped. |
| </p> |
| <p> |
| The user can also map the managed shared memory in a fixed address. This option is |
| essential when using using <code class="computeroutput"><span class="identifier">fixed_managed_shared_memory</span></code>. To do this, just |
| add the mapping address as an extra parameter: |
| </p> |
| <pre class="programlisting"><span class="identifier">fixed_managed_shared_memory</span> <span class="identifier">segment</span> <span class="special">(</span><span class="identifier">open_only</span> <span class="special">,</span><span class="string">"MyFixedAddressSharedMemory"</span> <span class="comment">//Shared memory object name |
| </span> <span class="special">,(</span><span class="keyword">void</span><span class="special">*)</span><span class="number">0x30000000</span> <span class="comment">//Mapping address |
| </span></pre> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_shared_memory.windows_managed_memory_common_shm"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_shared_memory.windows_managed_memory_common_shm" title="Using native windows shared memory">Using native windows shared memory</a> |
| </h4></div></div></div> |
| <p> |
| Windows users might also want to use native windows shared memory instead of |
| the portable <code class="computeroutput"><a class="link" href="../boost/interprocess/shared_memory_object.html" title="Class shared_memory_object">shared_memory_object</a></code> |
| based managed memory. This is achieved through the |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/basic_managed_windows_s_id819665.html" title="Class template basic_managed_windows_shared_memory">basic_managed_windows_shared_memory</a></code> |
| class. To use it just include: |
| </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_windows_shared_memory</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <p> |
| This class has the same interface as |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/basic_managed_shared_me_id819329.html" title="Class template basic_managed_shared_memory">basic_managed_shared_memory</a></code> |
| but uses native windows shared memory. Note that this managed class has the same |
| lifetime issues as the windows shared memory: when the last process attached to the |
| windows shared memory is detached from the memory (or ends/crashes) the memory is |
| destroyed. So there is no persistence support for windows shared memory. |
| </p> |
| <p> |
| To communicate between system services and user applications using <code class="computeroutput"><span class="identifier">managed_windows_shared_memory</span></code>, |
| please read the explanations given in chapter |
| [interprocess.sharedmemorybetweenprocesses.sharedmemory.windows_shared_memory Native windows shared memory] |
| </p> |
| </div> |
| <p> |
| For more information about managed shared memory capabilities, see |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/basic_managed_shared_me_id819329.html" title="Class template basic_managed_shared_memory">basic_managed_shared_memory</a></code> class reference. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_mapped_files"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_mapped_files" title="Managed Mapped File">Managed Mapped File</a> |
| </h3></div></div></div> |
| <div class="toc"><dl> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_mapped_files.managed_memory_common_mfile">Common Managed Mapped Files</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_mapped_files.constructing_managed_mapped_files">Constructing Managed Mapped Files</a></span></dt> |
| </dl></div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_mapped_files.managed_memory_common_mfile"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_mapped_files.managed_memory_common_mfile" title="Common Managed Mapped Files">Common Managed Mapped Files</a> |
| </h4></div></div></div> |
| <p> |
| As seen, <span class="bold"><strong>basic_managed_mapped_file</strong></span> offers a great variety of customization. But |
| for the average user, a common, default shared memory named object creation is needed. |
| Because of this, <span class="bold"><strong>Boost.Interprocess</strong></span> defines the most common managed mapped file |
| specializations: |
| </p> |
| <pre class="programlisting"><span class="comment">//Named object creation managed memory segment |
| </span><span class="comment">//All objects are constructed in the memory-mapped file |
| </span><span class="comment">// Names are c-strings, |
| </span><span class="comment">// Default memory management algorithm(rbtree_best_fit with no mutexes) |
| </span><span class="comment">// Name-object mappings are stored in the default index type (flat_map) |
| </span><span class="keyword">typedef</span> <span class="identifier">basic_managed_mapped_file</span> <span class="special"><</span> |
| <span class="keyword">char</span><span class="special">,</span> |
| <span class="identifier">rbtree_best_fit</span><span class="special"><</span><span class="identifier">mutex_family</span><span class="special">,</span> <span class="identifier">offset_ptr</span><span class="special"><</span><span class="keyword">void</span><span class="special">></span> <span class="special">>,</span> |
| <span class="identifier">flat_map_index</span> |
| <span class="special">></span> <span class="identifier">managed_mapped_file</span><span class="special">;</span> |
| |
| <span class="comment">//Named object creation managed memory segment |
| </span><span class="comment">//All objects are constructed in the memory-mapped file |
| </span><span class="comment">// Names are wide-strings, |
| </span><span class="comment">// Default memory management algorithm(rbtree_best_fit with no mutexes) |
| </span><span class="comment">// Name-object mappings are stored in the default index type (flat_map) |
| </span><span class="keyword">typedef</span> <span class="identifier">basic_managed_mapped_file</span><span class="special"><</span> |
| <span class="keyword">wchar_t</span><span class="special">,</span> |
| <span class="identifier">rbtree_best_fit</span><span class="special"><</span><span class="identifier">mutex_family</span><span class="special">,</span> <span class="identifier">offset_ptr</span><span class="special"><</span><span class="keyword">void</span><span class="special">></span> <span class="special">>,</span> |
| <span class="identifier">flat_map_index</span> |
| <span class="special">></span> <span class="identifier">wmanaged_mapped_file</span><span class="special">;</span> |
| </pre> |
| <p> |
| <code class="computeroutput"><span class="identifier">managed_mapped_file</span></code> allocates objects in a memory mapped files associated with a c-string |
| and <code class="computeroutput"><span class="identifier">wmanaged_mapped_file</span></code> allocates objects in a memory mapped file associated with a wchar_t null |
| terminated string. Both define the pointer type as <code class="computeroutput"><span class="identifier">offset_ptr</span><span class="special"><</span><span class="keyword">void</span><span class="special">></span></code> so they can be |
| used to map the file at different base addresses in different processes. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_mapped_files.constructing_managed_mapped_files"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_mapped_files.constructing_managed_mapped_files" title="Constructing Managed Mapped Files">Constructing Managed Mapped Files</a> |
| </h4></div></div></div> |
| <p> |
| Managed mapped file is an advanced class that combines a file |
| and a mapped region that covers all the file. That means that |
| when we <span class="bold"><strong>create</strong></span> a new managed mapped file: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| A new file is created. |
| |
| </li> |
| <li class="listitem"> |
| The whole file is mapped in the process' address space. |
| |
| </li> |
| <li class="listitem"> |
| Some helper objects are constructed (name-object index, internal synchronization |
| objects, internal variables...) in the mapped region to implement |
| managed memory segment features. |
| |
| </li> |
| </ul></div> |
| <p> |
| When we <span class="bold"><strong>open</strong></span> a managed mapped file |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| A file is opened. |
| |
| </li> |
| <li class="listitem"> |
| The whole file is mapped in the process' address space. |
| |
| </li> |
| </ul></div> |
| <p> |
| To use a managed mapped file, 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">managed_mapped_file</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <pre class="programlisting"><span class="comment">//1. Creates a new file |
| </span><span class="comment">// called "MyMappedFile". |
| </span><span class="comment">//2. Maps the whole file to this |
| </span><span class="comment">// process' address space. |
| </span><span class="comment">//3. Constructs some objects in the memory mapped |
| </span><span class="comment">// file to implement managed features. |
| </span><span class="comment">//!! If anything fails, throws interprocess_exception |
| </span><span class="comment">// |
| </span><span class="identifier">managed_mapped_file</span> <span class="identifier">mfile</span> <span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> <span class="string">"MyMappedFile"</span><span class="special">,</span> <span class="comment">//Mapped file name 65536); //Mapped file size |
| </span></pre> |
| <pre class="programlisting"><span class="comment">//1. Opens a file |
| </span><span class="comment">// called "MyMappedFile". |
| </span><span class="comment">//2. Maps the whole file to this |
| </span><span class="comment">// process' address space. |
| </span><span class="comment">//3. Obtains pointers to constructed internal objects |
| </span><span class="comment">// to implement managed features. |
| </span><span class="comment">//!! If anything fails, throws interprocess_exception |
| </span><span class="comment">// |
| </span><span class="identifier">managed_mapped_file</span> <span class="identifier">mfile</span> <span class="special">(</span><span class="identifier">open_only</span><span class="special">,</span> <span class="string">"MyMappedFile"</span><span class="special">);</span> <span class="comment">//Mapped file name[c++] |
| </span> |
| <span class="comment">//1. If the file was previously created |
| </span><span class="comment">// equivalent to "open_only". |
| </span><span class="comment">//2. Otherwise, equivalent to "open_only" (size is ignored) |
| </span><span class="comment">// |
| </span><span class="comment">//!! If anything fails, throws interprocess_exception |
| </span><span class="comment">// |
| </span><span class="identifier">managed_mapped_file</span> <span class="identifier">mfile</span> <span class="special">(</span><span class="identifier">open_or_create</span><span class="special">,</span> <span class="string">"MyMappedFile"</span><span class="special">,</span> <span class="comment">//Mapped file name 65536); //Mapped file size |
| </span></pre> |
| <p> |
| When the <code class="computeroutput"><span class="identifier">managed_mapped_file</span></code> object is destroyed, the file is |
| automatically unmapped, and all the resources are freed. To remove |
| the file from the filesystem you could use standard C <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">remove</span></code> |
| or <span class="bold"><strong>Boost.Filesystem</strong></span>'s <code class="computeroutput"><span class="identifier">remove</span><span class="special">()</span></code> functions, but file removing might fail |
| if any process still has the file mapped in memory or the file is open |
| by any process. |
| </p> |
| <p> |
| To obtain a more portable behaviour, use <code class="computeroutput"><span class="identifier">file_mapping</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span> <span class="special">*)</span></code> operation, which |
| will remove the file even if it's being mapped. However, removal will fail in some OS systems if |
| the file (eg. by C++ file streams) and no delete share permission was granted to the file. But in |
| most common cases <code class="computeroutput"><span class="identifier">file_mapping</span><span class="special">::</span><span class="identifier">remove</span></code> is portable enough. |
| </p> |
| </div> |
| <p> |
| For more information about managed mapped file capabilities, see |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/basic_managed_mapped_file.html" title="Class template basic_managed_mapped_file">basic_managed_mapped_file</a></code> class reference. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_memory_segment_features"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features" title="Managed Memory Segment Features">Managed Memory Segment Features</a> |
| </h3></div></div></div> |
| <div class="toc"><dl> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.allocate_deallocate">Allocating fragments of a managed memory segment</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.segment_offset">Obtaining handles to identify data</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.allocation_types">Object construction function family</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.anonymous">Anonymous instance construction</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.unique">Unique instance construction</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.synchronization">Synchronization guarantees</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.index_types">Index types for name/object mappings</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.managed_memory_segment_segment_manager">Segment Manager</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.managed_memory_segment_information">Obtaining information about a constructed object</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.managed_memory_segment_atomic_func">Executing an object function atomically</a></span></dt> |
| </dl></div> |
| <p> |
| The following features are common to all managed memory segment classes, but |
| we will use managed shared memory in our examples. We can do the same with |
| memory mapped files or other managed memory segment classes. |
| </p> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_memory_segment_features.allocate_deallocate"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.allocate_deallocate" title="Allocating fragments of a managed memory segment">Allocating fragments of a managed memory segment</a> |
| </h4></div></div></div> |
| <p> |
| If a basic raw-byte allocation is needed from a managed memory |
| segment, (for example, a managed shared memory), to implement |
| top-level interprocess communications, this class offers |
| <span class="bold"><strong>allocate</strong></span> and <span class="bold"><strong>deallocate</strong></span> functions. The allocation function |
| comes with throwing and no throwing versions. Throwing version throws |
| boost::interprocess::bad_alloc (which derives from <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bad_alloc</span></code>) |
| if there is no more memory and the non-throwing version returns 0 pointer. |
| </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="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">//Managed memory segment that allocates portions of a shared memory |
| </span> <span class="comment">//segment with the default management algorithm |
| </span> <span class="identifier">managed_shared_memory</span> <span class="identifier">managed_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">65536</span><span class="special">);</span> |
| |
| <span class="comment">//Allocate 100 bytes of memory from segment, throwing version |
| </span> <span class="keyword">void</span> <span class="special">*</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">managed_shm</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="comment">//Deallocate it |
| </span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">deallocate</span><span class="special">(</span><span class="identifier">ptr</span><span class="special">);</span> |
| |
| <span class="comment">//Non throwing version |
| </span> <span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">managed_shm</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="identifier">std</span><span class="special">::</span><span class="identifier">nothrow</span><span class="special">);</span> |
| |
| <span class="comment">//Deallocate it |
| </span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">deallocate</span><span class="special">(</span><span class="identifier">ptr</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.managed_memory_segments.managed_memory_segment_features.segment_offset"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.segment_offset" title="Obtaining handles to identify data">Obtaining handles to identify data</a> |
| </h4></div></div></div> |
| <p> |
| The class also offers conversions between absolute addresses that belong to |
| a managed memory segment and a handle that can be passed using any |
| interprocess mechanism. That handle can be transformed again to an absolute |
| address using a managed memory segment that also contains that object. |
| Handles can be used as keys between processes to identify allocated portions |
| of a managed memory segment or objects constructed in the managed segment. |
| </p> |
| <pre class="programlisting"><span class="comment">//Process A obtains the offset of the address |
| </span><span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">handle</span> <span class="identifier">handle</span> <span class="special">=</span> |
| <span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_handle_from_address</span><span class="special">(</span><span class="identifier">processA_address</span><span class="special">);</span> |
| |
| <span class="comment">//Process A sends this address using any mechanism to process B |
| </span> |
| <span class="comment">//Process B obtains the handle and transforms it again to an address |
| </span><span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">handle</span> <span class="identifier">handle</span> <span class="special">=</span> <span class="special">...</span> |
| <span class="keyword">void</span> <span class="special">*</span> <span class="identifier">processB_address</span> <span class="special">=</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_address_from_handle</span><span class="special">(</span><span class="identifier">handle</span><span class="special">);</span> |
| </pre> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_memory_segment_features.allocation_types"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.allocation_types" title="Object construction function family">Object construction function family</a> |
| </h4></div></div></div> |
| <p> |
| When constructing objects in a managed memory segment (managed shared memory, |
| managed mapped files...) associated with a name, the user has a varied object |
| construction family to "construct" or to "construct if not found". <span class="bold"><strong>Boost.Interprocess</strong></span> |
| can construct a single object or an array of objects. The array can be constructed with |
| the same parameters for all objects or we can define each parameter from a list of iterators: |
| </p> |
| <pre class="programlisting"><span class="comment">//!Allocates and constructs an object of type MyType (throwing version) |
| </span><span class="identifier">MyType</span> <span class="special">*</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">managed_memory_segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="identifier">MyType</span><span class="special">>(</span><span class="string">"Name"</span><span class="special">)</span> <span class="special">(</span><span class="identifier">par1</span><span class="special">,</span> <span class="identifier">par2</span><span class="special">...);</span> |
| |
| <span class="comment">//!Allocates and constructs an array of objects of type MyType (throwing version) |
| </span><span class="comment">//!Each object receives the same parameters (par1, par2, ...) |
| </span><span class="identifier">MyType</span> <span class="special">*</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">managed_memory_segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="identifier">MyType</span><span class="special">>(</span><span class="string">"Name"</span><span class="special">)[</span><span class="identifier">count</span><span class="special">](</span><span class="identifier">par1</span><span class="special">,</span> <span class="identifier">par2</span><span class="special">...);</span> |
| |
| <span class="comment">//!Tries to find a previously created object. If not present, allocates |
| </span><span class="comment">//!and constructs an object of type MyType (throwing version) |
| </span><span class="identifier">MyType</span> <span class="special">*</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">managed_memory_segment</span><span class="special">.</span><span class="identifier">find_or_construct</span><span class="special"><</span><span class="identifier">MyType</span><span class="special">>(</span><span class="string">"Name"</span><span class="special">)</span> <span class="special">(</span><span class="identifier">par1</span><span class="special">,</span> <span class="identifier">par2</span><span class="special">...);</span> |
| |
| <span class="comment">//!Tries to find a previously created object. If not present, allocates and |
| </span><span class="comment">//!constructs an array of objects of type MyType (throwing version). Each object |
| </span><span class="comment">//!receives the same parameters (par1, par2, ...) |
| </span><span class="identifier">MyType</span> <span class="special">*</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">managed_memory_segment</span><span class="special">.</span><span class="identifier">find_or_construct</span><span class="special"><</span><span class="identifier">MyType</span><span class="special">>(</span><span class="string">"Name"</span><span class="special">)[</span><span class="identifier">count</span><span class="special">](</span><span class="identifier">par1</span><span class="special">,</span> <span class="identifier">par2</span><span class="special">...);</span> |
| |
| <span class="comment">//!Allocates and constructs an array of objects of type MyType (throwing version) |
| </span><span class="comment">//!Each object receives parameters returned with the expression (*it1++, *it2++,... ) |
| </span><span class="identifier">MyType</span> <span class="special">*</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">managed_memory_segment</span><span class="special">.</span><span class="identifier">construct_it</span><span class="special"><</span><span class="identifier">MyType</span><span class="special">>(</span><span class="string">"Name"</span><span class="special">)[</span><span class="identifier">count</span><span class="special">](</span><span class="identifier">it1</span><span class="special">,</span> <span class="identifier">it2</span><span class="special">...);</span> |
| |
| <span class="comment">//!Tries to find a previously created object. If not present, allocates and constructs |
| </span><span class="comment">//!an array of objects of type MyType (throwing version). Each object receives |
| </span><span class="comment">//!parameters returned with the expression (*it1++, *it2++,... ) |
| </span><span class="identifier">MyType</span> <span class="special">*</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">managed_memory_segment</span><span class="special">.</span><span class="identifier">find_or_construct_it</span><span class="special"><</span><span class="identifier">MyType</span><span class="special">>(</span><span class="string">"Name"</span><span class="special">)[</span><span class="identifier">count</span><span class="special">](</span><span class="identifier">it1</span><span class="special">,</span> <span class="identifier">it2</span><span class="special">...);</span> |
| |
| <span class="comment">//!Tries to find a previously created object. Returns a pointer to the object and the |
| </span><span class="comment">//!count (if it is not an array, returns 1). If not present, the returned pointer is 0 |
| </span><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span><span class="identifier">MyType</span> <span class="special">*,</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">></span> <span class="identifier">ret</span> <span class="special">=</span> <span class="identifier">managed_memory_segment</span><span class="special">.</span><span class="identifier">find</span><span class="special"><</span><span class="identifier">MyType</span><span class="special">>(</span><span class="string">"Name"</span><span class="special">);</span> |
| |
| <span class="comment">//!Destroys the created object, returns false if not present |
| </span><span class="keyword">bool</span> <span class="identifier">destroyed</span> <span class="special">=</span> <span class="identifier">managed_memory_segment</span><span class="special">.</span><span class="identifier">destroy</span><span class="special"><</span><span class="identifier">MyType</span><span class="special">>(</span><span class="string">"Name"</span><span class="special">);</span> |
| |
| <span class="comment">//!Destroys the created object via pointer |
| </span><span class="identifier">managed_memory_segment</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">ptr</span><span class="special">);</span> |
| </pre> |
| <p> |
| All these functions have a non-throwing version, that |
| is invoked with an additional parameter std::nothrow. |
| For example, for simple object construction: |
| </p> |
| <pre class="programlisting"><span class="comment">//!Allocates and constructs an object of type MyType (no throwing version) |
| </span><span class="identifier">MyType</span> <span class="special">*</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">managed_memory_segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="identifier">MyType</span><span class="special">>(</span><span class="string">"Name"</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">nothrow</span><span class="special">)</span> <span class="special">(</span><span class="identifier">par1</span><span class="special">,</span> <span class="identifier">par2</span><span class="special">...);</span> |
| </pre> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_memory_segment_features.anonymous"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.anonymous" title="Anonymous instance construction">Anonymous instance construction</a> |
| </h4></div></div></div> |
| <p> |
| Sometimes, the user doesn't want to create class objects associated with a name. |
| For this purpose, <span class="bold"><strong>Boost.Interprocess</strong></span> can create anonymous objects in a managed |
| memory segment. All named object construction functions are available to construct |
| anonymous objects. To allocate an anonymous objects, the user must use |
| "boost::interprocess::anonymous_instance" name instead of a normal name: |
| </p> |
| <pre class="programlisting"><span class="identifier">MyType</span> <span class="special">*</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">managed_memory_segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="identifier">MyType</span><span class="special">>(</span><span class="identifier">anonymous_instance</span><span class="special">)</span> <span class="special">(</span><span class="identifier">par1</span><span class="special">,</span> <span class="identifier">par2</span><span class="special">...);</span> |
| |
| <span class="comment">//Other construct variants can also be used (including non-throwing ones) |
| </span><span class="special">...</span> |
| |
| <span class="comment">//We can only destroy the anonymous object via pointer |
| </span><span class="identifier">managed_memory_segment</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">ptr</span><span class="special">);</span> |
| </pre> |
| <p> |
| Find functions have no sense here, since anonymous objects have no name. |
| We can only destroy the anonymous object via pointer. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_memory_segment_features.unique"></a><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> |
| </h4></div></div></div> |
| <p> |
| Sometimes, the user wants to emulate a singleton in a managed memory segment. Obviously, |
| as the managed memory segment is constructed at run-time, the user must construct and |
| destroy this object explicitly. But how can the user be sure that the object is the only |
| object of its type in the managed memory segment? This can be emulated using |
| a named object and checking if it is present before trying to create one, but |
| all processes must agree in the object's name, that can also conflict with |
| other existing names. |
| </p> |
| <p> |
| To solve this, <span class="bold"><strong>Boost.Interprocess</strong></span> offers a "unique object" creation in a managed memory segment. |
| Only one instance of a class can be created in a managed memory segment using this |
| "unique object" service (you can create more named objects of this class, though) |
| so it makes easier the emulation of singleton-like objects across processes, for example, |
| to design pooled, shared memory allocators. The object can be searched using the type |
| of the class as a key. |
| </p> |
| <pre class="programlisting"><span class="comment">// Construct |
| </span><span class="identifier">MyType</span> <span class="special">*</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">managed_memory_segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="identifier">MyType</span><span class="special">>(</span><span class="identifier">unique_instance</span><span class="special">)</span> <span class="special">(</span><span class="identifier">par1</span><span class="special">,</span> <span class="identifier">par2</span><span class="special">...);</span> |
| |
| <span class="comment">// Find it |
| </span><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span><span class="identifier">MyType</span> <span class="special">*,</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">></span> <span class="identifier">ret</span> <span class="special">=</span> <span class="identifier">managed_memory_segment</span><span class="special">.</span><span class="identifier">find</span><span class="special"><</span><span class="identifier">MyType</span><span class="special">>(</span><span class="identifier">unique_instance</span><span class="special">);</span> |
| |
| <span class="comment">// Destroy it |
| </span><span class="identifier">managed_memory_segment</span><span class="special">.</span><span class="identifier">destroy</span><span class="special"><</span><span class="identifier">MyType</span><span class="special">>(</span><span class="identifier">unique_instance</span><span class="special">);</span> |
| |
| <span class="comment">// Other construct and find variants can also be used (including non-throwing ones) |
| </span><span class="comment">//... |
| </span></pre> |
| <pre class="programlisting"><span class="comment">// We can also destroy the unique object via pointer |
| </span><span class="identifier">MyType</span> <span class="special">*</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">managed_memory_segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="identifier">MyType</span><span class="special">>(</span><span class="identifier">unique_instance</span><span class="special">)</span> <span class="special">(</span><span class="identifier">par1</span><span class="special">,</span> <span class="identifier">par2</span><span class="special">...);</span> |
| <span class="identifier">managed_shared_memory</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">ptr</span><span class="special">);</span> |
| </pre> |
| <p> |
| The find function obtains a pointer to the only object of type T that can be created |
| using this "unique instance" mechanism. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_memory_segment_features.synchronization"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.synchronization" title="Synchronization guarantees">Synchronization guarantees</a> |
| </h4></div></div></div> |
| <p> |
| One of the features of named/unique allocations/searches/destructions is that |
| they are <span class="bold"><strong>atomic</strong></span>. Named allocations use the recursive synchronization scheme defined by the |
| internal <code class="computeroutput"><span class="identifier">mutex_family</span></code> typedef defined of the memory allocation algorithm template |
| parameter (<code class="computeroutput"><span class="identifier">MemoryAlgorithm</span></code>). That is, the mutex type used to synchronize |
| named/unique allocations is defined by the |
| <code class="computeroutput"><span class="identifier">MemoryAlgorithm</span><span class="special">::</span><span class="identifier">mutex_family</span><span class="special">::</span><span class="identifier">recursive_mutex_type</span></code> type. For shared memory, |
| and memory mapped file based managed segments this recursive mutex is defined |
| as <code class="computeroutput"><a class="link" href="../boost/interprocess/interprocess_recursive__id829088.html" title="Class interprocess_recursive_mutex">interprocess_recursive_mutex</a></code>. |
| </p> |
| <p> |
| If two processes can call: |
| </p> |
| <pre class="programlisting"><span class="identifier">MyType</span> <span class="special">*</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">managed_shared_memory</span><span class="special">.</span><span class="identifier">find_or_construct</span><span class="special"><</span><span class="identifier">MyType</span><span class="special">>(</span><span class="string">"Name"</span><span class="special">)[</span><span class="identifier">count</span><span class="special">](</span><span class="identifier">par1</span><span class="special">,</span> <span class="identifier">par2</span><span class="special">...);</span> |
| </pre> |
| <p> |
| at the same time, but only one process will create the object and the other will |
| obtain a pointer to the created object. |
| </p> |
| <p> |
| Raw allocation using <code class="computeroutput"><span class="identifier">allocate</span><span class="special">()</span></code> can be called also safely while executing |
| named/anonymous/unique allocations, just like when programming a multithreaded |
| application inserting an object in a mutex-protected map does not block other threads |
| from calling new[] while the map thread is searching the place where it has to insert the |
| new object. The synchronization does happen once the map finds the correct place and |
| it has to allocate raw memory to construct the new value. |
| </p> |
| <p> |
| This means that if we are creating or searching for a lot of named objects, |
| we only block creation/searches from other processes but we don't block another |
| process if that process is inserting elements in a shared memory vector. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_memory_segment_features.index_types"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.index_types" title="Index types for name/object mappings">Index types for name/object mappings</a> |
| </h4></div></div></div> |
| <p> |
| As seen, managed memory segments, when creating named objects, store the name/object |
| association in an index. The index is a map with the name of the object as a key and |
| a pointer to the object as the mapped type. The default specializations, |
| <span class="bold"><strong>managed_shared_memory</strong></span> and <span class="bold"><strong>wmanaged_shared_memory</strong></span>, use <span class="bold"><strong>flat_map_index</strong></span> as the index type. |
| </p> |
| <p> |
| Each index has its own characteristics, like search-time, insertion time, deletion time, |
| memory use, and memory allocation patterns. <span class="bold"><strong>Boost.Interprocess</strong></span> offers 3 index types |
| right now: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| <span class="bold"><strong>boost::interprocess::flat_map_index flat_map_index</strong></span>: Based on boost::interprocess::flat_map, an ordered |
| vector similar to Loki library's AssocVector class, offers great search time and |
| minimum memory use. But the vector must be reallocated when is full, so all data |
| must be copied to the new buffer. Ideal when insertions are mainly in initialization |
| time and in run-time we just need searches. |
| |
| </li> |
| <li class="listitem"> |
| <span class="bold"><strong>boost::interprocess::map_index map_index</strong></span>: Based on boost::interprocess::map, a managed memory ready |
| version of std::map. Since it's a node based container, it has no reallocations, the tree |
| must be just rebalanced sometimes. Offers equilibrated insertion/deletion/search |
| times with more overhead per node comparing to <span class="bold"><strong>boost::interprocess::flat_map_index</strong></span>. |
| Ideal when searches/insertions/deletions are in random order. |
| |
| </li> |
| <li class="listitem"> |
| <span class="bold"><strong>boost::interprocess::null_index null_index</strong></span>: This index is for people using a managed |
| memory segment just for raw memory buffer allocations and they don't make use |
| of named/unique allocations. This class is just empty and saves some space and |
| compilation time. |
| If you try to use named object creation with a managed memory segment using this |
| index, you will get a compilation error. |
| |
| </li> |
| </ul></div> |
| <p> |
| As an example, if we want to define new managed shared memory class |
| using <span class="bold"><strong>boost::interprocess::map</strong></span> as the index type we |
| just must specify [boost::interprocess::map_index map_index] as a template parameter: |
| </p> |
| <pre class="programlisting"><span class="comment">//This managed memory segment can allocate objects with: |
| </span><span class="comment">// -> a wchar_t string as key |
| </span><span class="comment">// -> boost::interprocess::rbtree_best_fit with process-shared mutexes |
| </span><span class="comment">// as memory allocation algorithm. |
| </span><span class="comment">// -> boost::interprocess::map<...> as the index to store name/object mappings |
| </span><span class="comment">// |
| </span><span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">basic_managed_shared_memory</span> |
| <span class="special"><</span> <span class="keyword">wchar_t</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">rbtree_best_fit</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">mutex_family</span><span class="special">,</span> <span class="identifier">offset_ptr</span><span class="special"><</span><span class="keyword">void</span><span class="special">></span> <span class="special">></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">map_index</span> |
| <span class="special">></span> <span class="identifier">my_managed_shared_memory</span><span class="special">;</span> |
| </pre> |
| <p> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> plans to offer an <span class="bold"><strong>unordered_map</strong></span> based index as soon as this |
| container is included in Boost. If these indexes are not enough for you, you can define |
| your own index type. To know how to do this, go to |
| <a class="link" href="customizing_interprocess.html#interprocess.customizing_interprocess.custom_indexes" title="Building custom indexes">Building custom indexes</a> section. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_memory_segment_features.managed_memory_segment_segment_manager"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.managed_memory_segment_segment_manager" title="Segment Manager">Segment Manager</a> |
| </h4></div></div></div> |
| <p> |
| All <span class="bold"><strong>Boost.Interprocess</strong></span> managed memory segment classes construct in their |
| respective memory segments (shared memory, memory mapped files, heap memory...) |
| some structures to implement the memory management algorithm, named allocations, |
| synchronization objects... All these objects are encapsulated in a single object |
| called <span class="bold"><strong>segment manager</strong></span>. A managed memory mapped file and a managed shared |
| memory use the same <span class="bold"><strong>segment manager</strong></span> to implement all managed memory segment |
| features, due to the fact that a <span class="bold"><strong>segment manager</strong></span> is a class that manages |
| a fixed size memory buffer. Since both shared memory or memory mapped files |
| are accessed though a mapped region, and a mapped region is a fixed size |
| memory buffer, a single <span class="bold"><strong>segment manager</strong></span> class can manage several managed |
| memory segment types. |
| </p> |
| <p> |
| Some <span class="bold"><strong>Boost.Interprocess</strong></span> classes require a pointer to the segment manager in |
| their constructors, and the segment manager can be obtained from any managed |
| memory segment using <code class="computeroutput"><span class="identifier">get_segment_manager</span></code> member: |
| </p> |
| <pre class="programlisting"><span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span> <span class="special">*</span><span class="identifier">seg_manager</span> <span class="special">=</span> |
| <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">();</span> |
| </pre> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_memory_segment_features.managed_memory_segment_information"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.managed_memory_segment_information" title="Obtaining information about a constructed object">Obtaining information about a constructed object</a> |
| </h4></div></div></div> |
| <p> |
| Once an object is constructed using <code class="computeroutput"><span class="identifier">construct</span><span class="special"><></span></code> function family, the |
| programmer can obtain information about the object using a pointer to the |
| object. The programmer can obtain the following information: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| Name of the object: If it's a named instance, the name used in the construction |
| function is returned, otherwise 0 is returned. |
| |
| </li> |
| <li class="listitem"> |
| Length of the object: Returns the number of elements of the object (1 if it's |
| a single value, >=1 if it's an array). |
| |
| </li> |
| <li class="listitem"> |
| The type of construction: Whether the object was constructed using a named, |
| unique or anonymous construction. |
| |
| </li> |
| </ul></div> |
| <p> |
| Here is an example showing this functionality: |
| </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">cassert</span><span class="special">></span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cstring</span><span class="special">></span> |
| |
| <span class="keyword">class</span> <span class="identifier">my_class</span> |
| <span class="special">{</span> |
| <span class="comment">//... |
| </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="identifier">managed_shared_memory</span> <span class="identifier">managed_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="keyword">sizeof</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">));</span> |
| |
| <span class="comment">//Construct objects |
| </span> <span class="identifier">my_class</span> <span class="special">*</span><span class="identifier">named_object</span> <span class="special">=</span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="identifier">my_class</span><span class="special">>(</span><span class="string">"Object name"</span><span class="special">)[</span><span class="number">1</span><span class="special">]();</span> |
| <span class="identifier">my_class</span> <span class="special">*</span><span class="identifier">unique_object</span> <span class="special">=</span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="identifier">my_class</span><span class="special">>(</span><span class="identifier">unique_instance</span><span class="special">)[</span><span class="number">2</span><span class="special">]();</span> |
| <span class="identifier">my_class</span> <span class="special">*</span><span class="identifier">anon_object</span> <span class="special">=</span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="identifier">my_class</span><span class="special">>(</span><span class="identifier">anonymous_instance</span><span class="special">)[</span><span class="number">3</span><span class="special">]();</span> |
| |
| <span class="comment">//Now test "get_instance_name" function. |
| </span> <span class="identifier">assert</span><span class="special">(</span><span class="number">0</span> <span class="special">==</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">strcmp</span><span class="special">(</span><span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">get_instance_name</span><span class="special">(</span><span class="identifier">named_object</span><span class="special">),</span> <span class="string">"Object name"</span><span class="special">));</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="number">0</span> <span class="special">==</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">get_instance_name</span><span class="special">(</span><span class="identifier">unique_object</span><span class="special">));</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="number">0</span> <span class="special">==</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">get_instance_name</span><span class="special">(</span><span class="identifier">anon_object</span><span class="special">));</span> |
| |
| <span class="comment">//Now test "get_instance_type" function. |
| </span> <span class="identifier">assert</span><span class="special">(</span><span class="identifier">named_type</span> <span class="special">==</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">get_instance_type</span><span class="special">(</span><span class="identifier">named_object</span><span class="special">));</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">unique_type</span> <span class="special">==</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">get_instance_type</span><span class="special">(</span><span class="identifier">unique_object</span><span class="special">));</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">anonymous_type</span> <span class="special">==</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">get_instance_type</span><span class="special">(</span><span class="identifier">anon_object</span><span class="special">));</span> |
| |
| <span class="comment">//Now test "get_instance_length" function. |
| </span> <span class="identifier">assert</span><span class="special">(</span><span class="number">1</span> <span class="special">==</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">get_instance_length</span><span class="special">(</span><span class="identifier">named_object</span><span class="special">));</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="number">2</span> <span class="special">==</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">get_instance_length</span><span class="special">(</span><span class="identifier">unique_object</span><span class="special">));</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="number">3</span> <span class="special">==</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">get_instance_length</span><span class="special">(</span><span class="identifier">anon_object</span><span class="special">));</span> |
| |
| <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">named_object</span><span class="special">);</span> |
| <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">unique_object</span><span class="special">);</span> |
| <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">anon_object</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.managed_memory_segments.managed_memory_segment_features.managed_memory_segment_atomic_func"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.managed_memory_segment_atomic_func" title="Executing an object function atomically">Executing an object function atomically</a> |
| </h4></div></div></div> |
| <p> |
| Sometimes the programmer must execute some code, and needs to execute it with the |
| guarantee that no other process or thread will create or destroy any named, unique |
| or anonymous object while executing the functor. A user might want to create several |
| named objects and initialize them, but those objects should be available for the rest of processes |
| at once. |
| </p> |
| <p> |
| To achieve this, the programmer can use the <code class="computeroutput"><span class="identifier">atomic_func</span><span class="special">()</span></code> function offered by |
| managed classes: |
| </p> |
| <pre class="programlisting"><span class="comment">//This object function will create several named objects |
| </span><span class="identifier">create_several_objects_func</span> <span class="identifier">func</span><span class="special">(/**/);</span> |
| |
| <span class="comment">//While executing the function, no other process will be |
| </span><span class="comment">//able to create or destroy objects |
| </span><span class="identifier">managed_memory</span><span class="special">.</span><span class="identifier">atomic_func</span><span class="special">(</span><span class="identifier">func</span><span class="special">);</span> |
| </pre> |
| <p> |
| Note that <code class="computeroutput"><span class="identifier">atomic_func</span></code> does not prevent other processes from allocating raw memory |
| or executing member functions for already constructed objects (e.g.: another process |
| might be pushing elements into a vector placed in the segment). The atomic function |
| only blocks named, unique and anonymous creation, search and destruction |
| (concurrent calls to <code class="computeroutput"><span class="identifier">construct</span><span class="special"><></span></code>, <code class="computeroutput"><span class="identifier">find</span><span class="special"><></span></code>, <code class="computeroutput"><span class="identifier">find_or_construct</span><span class="special"><></span></code>, <code class="computeroutput"><span class="identifier">destroy</span><span class="special"><></span></code>...) |
| from other processes. |
| </p> |
| </div> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h3 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_memory_segment_advanced_features"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_advanced_features" title="Managed Memory Segment Advanced Features">Managed Memory Segment Advanced Features</a> |
| </h3></div></div></div> |
| <div class="toc"><dl> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_advanced_features.managed_memory_segment_information">Obtaining information about the managed segment</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_advanced_features.growing_managed_memory">Growing managed segments</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_advanced_features.managed_memory_segment_advanced_index_functions">Advanced index functions</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_advanced_features.allocate_aligned">Allocating aligned memory portions</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_advanced_features.managed_memory_segment_multiple_allocations">Multiple allocation functions</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_advanced_features.managed_memory_segment_expand_in_place">Expand in place memory allocation</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_advanced_features.copy_on_write_read_only">Opening managed shared memory and mapped files with Copy On Write or Read Only modes</a></span></dt> |
| </dl></div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_memory_segment_advanced_features.managed_memory_segment_information"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_advanced_features.managed_memory_segment_information" title="Obtaining information about the managed segment">Obtaining information about the managed segment</a> |
| </h4></div></div></div> |
| <p> |
| These functions are available to obtain information about the managed memory segments: |
| </p> |
| <p> |
| Obtain the size of the memory segment: |
| </p> |
| <pre class="programlisting"><span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">get_size</span><span class="special">();</span> |
| </pre> |
| <p> |
| Obtain the number of free bytes of the segment: |
| </p> |
| <pre class="programlisting"><span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">get_free_memory</span><span class="special">();</span> |
| </pre> |
| <p> |
| Clear to zero the free memory: |
| </p> |
| <pre class="programlisting"><span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">zero_free_memory</span><span class="special">();</span> |
| </pre> |
| <p> |
| Know if all memory has been deallocated, false otherwise: |
| </p> |
| <pre class="programlisting"><span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">all_memory_deallocated</span><span class="special">();</span> |
| </pre> |
| <p> |
| Test internal structures of the managed segment. Returns true |
| if no errors are detected: |
| </p> |
| <pre class="programlisting"><span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">check_sanity</span><span class="special">();</span> |
| </pre> |
| <p> |
| Obtain the number of named and unique objects allocated in the segment: |
| </p> |
| <pre class="programlisting"><span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">get_num_named_objects</span><span class="special">();</span> |
| <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">get_num_unique_objects</span><span class="special">();</span> |
| </pre> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_memory_segment_advanced_features.growing_managed_memory"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_advanced_features.growing_managed_memory" title="Growing managed segments">Growing managed segments</a> |
| </h4></div></div></div> |
| <p> |
| Once a managed segment is created the managed segment can't be grown. The limitation |
| is not easily solvable: every process attached to the managed segment would need to |
| be stopped, notified of the new size, they would need to remap the managed segment |
| and continue working. Nearly impossible to achieve with a user-level library without |
| the help of the operating system kernel. |
| </p> |
| <p> |
| On the other hand, <span class="bold"><strong>Boost.Interprocess</strong></span> offers off-line segment growing. What does this |
| mean? That the segment can be grown if no process has mapped the managed segment. If the |
| application can find a moment where no process is attached it can grow or shrink to fit |
| the managed segment. |
| </p> |
| <p> |
| Here we have an example showing how to grow and shrink to fit |
| <code class="computeroutput"><a class="link" href="../boost_interprocess_reference.html#boost.interprocess.managed_shared_memory">managed_shared_memory</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">managed_mapped_file</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">class</span> <span class="identifier">MyClass</span> |
| <span class="special">{</span> |
| <span class="comment">//... |
| </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="special">{</span> |
| <span class="comment">//Create a managed shared memory |
| </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">1000</span><span class="special">);</span> |
| |
| <span class="comment">//Check size |
| </span> <span class="identifier">assert</span><span class="special">(</span><span class="identifier">shm</span><span class="special">.</span><span class="identifier">get_size</span><span class="special">()</span> <span class="special">==</span> <span class="number">1000</span><span class="special">);</span> |
| <span class="comment">//Construct a named object |
| </span> <span class="identifier">MyClass</span> <span class="special">*</span><span class="identifier">myclass</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">MyClass</span><span class="special">>(</span><span class="string">"MyClass"</span><span class="special">)();</span> |
| <span class="comment">//The managed segment is unmapped here |
| </span> <span class="special">}</span> |
| <span class="special">{</span> |
| <span class="comment">//Now that the segment is not mapped grow it adding extra 500 bytes |
| </span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">grow</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="number">500</span><span class="special">);</span> |
| |
| <span class="comment">//Map it again |
| </span> <span class="identifier">managed_shared_memory</span> <span class="identifier">shm</span><span class="special">(</span><span class="identifier">open_only</span><span class="special">,</span> <span class="string">"MySharedMemory"</span><span class="special">);</span> |
| <span class="comment">//Check size |
| </span> <span class="identifier">assert</span><span class="special">(</span><span class="identifier">shm</span><span class="special">.</span><span class="identifier">get_size</span><span class="special">()</span> <span class="special">==</span> <span class="number">1500</span><span class="special">);</span> |
| <span class="comment">//Check "MyClass" is still there |
| </span> <span class="identifier">MyClass</span> <span class="special">*</span><span class="identifier">myclass</span> <span class="special">=</span> <span class="identifier">shm</span><span class="special">.</span><span class="identifier">find</span><span class="special"><</span><span class="identifier">MyClass</span><span class="special">>(</span><span class="string">"MyClass"</span><span class="special">).</span><span class="identifier">first</span><span class="special">;</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">myclass</span> <span class="special">!=</span> <span class="number">0</span><span class="special">);</span> |
| <span class="comment">//The managed segment is unmapped here |
| </span> <span class="special">}</span> |
| <span class="special">{</span> |
| <span class="comment">//Now minimize the size of the segment |
| </span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">shrink_to_fit</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> |
| |
| <span class="comment">//Map it again |
| </span> <span class="identifier">managed_shared_memory</span> <span class="identifier">shm</span><span class="special">(</span><span class="identifier">open_only</span><span class="special">,</span> <span class="string">"MySharedMemory"</span><span class="special">);</span> |
| <span class="comment">//Check size |
| </span> <span class="identifier">assert</span><span class="special">(</span><span class="identifier">shm</span><span class="special">.</span><span class="identifier">get_size</span><span class="special">()</span> <span class="special"><</span> <span class="number">1000</span><span class="special">);</span> |
| <span class="comment">//Check "MyClass" is still there |
| </span> <span class="identifier">MyClass</span> <span class="special">*</span><span class="identifier">myclass</span> <span class="special">=</span> <span class="identifier">shm</span><span class="special">.</span><span class="identifier">find</span><span class="special"><</span><span class="identifier">MyClass</span><span class="special">>(</span><span class="string">"MyClass"</span><span class="special">).</span><span class="identifier">first</span><span class="special">;</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">myclass</span> <span class="special">!=</span> <span class="number">0</span><span class="special">);</span> |
| <span class="comment">//The managed segment is unmapped here |
| </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> |
| <code class="computeroutput"><a class="link" href="../boost_interprocess_reference.html#boost.interprocess.managed_mapped_file">managed_mapped_file</a></code> also |
| offers a similar function to grow or shrink_to_fit the managed file. |
| Please, remember that <span class="bold"><strong>no process should be modifying the file/shared memory while |
| the growing/shrinking process is performed</strong></span>. Otherwise, the managed segment will be |
| corrupted. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_memory_segment_advanced_features.managed_memory_segment_advanced_index_functions"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_advanced_features.managed_memory_segment_advanced_index_functions" title="Advanced index functions">Advanced index functions</a> |
| </h4></div></div></div> |
| <p> |
| As mentioned, the managed segment stores the information about named and unique |
| objects in two indexes. Depending on the type of those indexes, the index must |
| reallocate some auxiliary structures when new named or unique allocations are made. |
| For some indexes, if the user knows how many named or unique objects are going to |
| be created it's possible to preallocate some structures to obtain much better |
| performance. (If the index is an ordered vector it can preallocate memory to avoid |
| reallocations. If the index is a hash structure it can preallocate the bucket array). |
| </p> |
| <p> |
| The following functions reserve memory to make the subsequent allocation of |
| named or unique objects more efficient. These functions are only useful for |
| pseudo-intrusive or non-node indexes (like <code class="computeroutput"><span class="identifier">flat_map_index</span></code>, |
| <code class="computeroutput"><span class="identifier">iunordered_set_index</span></code>). These functions have no effect with the |
| default index (<code class="computeroutput"><span class="identifier">iset_index</span></code>) or other indexes (<code class="computeroutput"><span class="identifier">map_index</span></code>): |
| </p> |
| <pre class="programlisting"><span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">reserve_named_objects</span><span class="special">(</span><span class="number">1000</span><span class="special">);</span> |
| <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">reserve_unique_objects</span><span class="special">(</span><span class="number">1000</span><span class="special">);</span> |
| </pre> |
| <pre class="programlisting"><span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">reserve_named_objects</span><span class="special">(</span><span class="number">1000</span><span class="special">);</span> |
| <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">reserve_unique_objects</span><span class="special">(</span><span class="number">1000</span><span class="special">);</span> |
| </pre> |
| <p> |
| Managed memory segments also offer the possibility to iterate through |
| constructed named and unique objects for debugging purposes. <span class="bold"><strong>Caution: this |
| iteration is not thread-safe</strong></span> so the user should make sure that no other |
| thread is manipulating named or unique indexes (creating, erasing, |
| reserving...) in the segment. Other operations not involving indexes can |
| be concurrently executed (raw memory allocation/deallocations, for example). |
| </p> |
| <p> |
| The following functions return constant iterators to the range of named and |
| unique objects stored in the managed segment. Depending on the index type, |
| iterators might be invalidated after a named or unique |
| creation/erasure/reserve operation: |
| </p> |
| <pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">const_named_iterator</span> <span class="identifier">const_named_it</span><span class="special">;</span> |
| <span class="identifier">const_named_it</span> <span class="identifier">named_beg</span> <span class="special">=</span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">named_begin</span><span class="special">();</span> |
| <span class="identifier">const_named_it</span> <span class="identifier">named_end</span> <span class="special">=</span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">named_end</span><span class="special">();</span> |
| |
| <span class="keyword">typedef</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">const_unique_iterator</span> <span class="identifier">const_unique_it</span><span class="special">;</span> |
| <span class="identifier">const_unique_it</span> <span class="identifier">unique_beg</span> <span class="special">=</span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">unique_begin</span><span class="special">();</span> |
| <span class="identifier">const_unique_it</span> <span class="identifier">unique_end</span> <span class="special">=</span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">unique_end</span><span class="special">();</span> |
| |
| <span class="keyword">for</span><span class="special">(;</span> <span class="identifier">named_beg</span> <span class="special">!=</span> <span class="identifier">named_end</span><span class="special">;</span> <span class="special">++</span><span class="identifier">named_beg</span><span class="special">){</span> |
| <span class="comment">//A pointer to the name of the named object |
| </span> <span class="keyword">const</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">char_type</span> <span class="special">*</span><span class="identifier">name</span> <span class="special">=</span> <span class="identifier">named_beg</span><span class="special">-></span><span class="identifier">name</span><span class="special">();</span> |
| <span class="comment">//The length of the name |
| </span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">name_len</span> <span class="special">=</span> <span class="identifier">named_beg</span><span class="special">-></span><span class="identifier">name_length</span><span class="special">();</span> |
| <span class="comment">//A constant void pointer to the named object |
| </span> <span class="keyword">const</span> <span class="keyword">void</span> <span class="special">*</span><span class="identifier">value</span> <span class="special">=</span> <span class="identifier">named_beg</span><span class="special">-></span><span class="identifier">value</span><span class="special">();</span> |
| <span class="special">}</span> |
| |
| <span class="keyword">for</span><span class="special">(;</span> <span class="identifier">unique_beg</span> <span class="special">!=</span> <span class="identifier">unique_end</span><span class="special">;</span> <span class="special">++</span><span class="identifier">unique_beg</span><span class="special">){</span> |
| <span class="comment">//The typeid(T).name() of the unique object |
| </span> <span class="keyword">const</span> <span class="keyword">char</span> <span class="special">*</span><span class="identifier">typeid_name</span> <span class="special">=</span> <span class="identifier">unique_beg</span><span class="special">-></span><span class="identifier">name</span><span class="special">();</span> |
| <span class="comment">//The length of the name |
| </span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">name_len</span> <span class="special">=</span> <span class="identifier">unique_beg</span><span class="special">-></span><span class="identifier">name_length</span><span class="special">();</span> |
| <span class="comment">//A constant void pointer to the unique object |
| </span> <span class="keyword">const</span> <span class="keyword">void</span> <span class="special">*</span><span class="identifier">value</span> <span class="special">=</span> <span class="identifier">unique_beg</span><span class="special">-></span><span class="identifier">value</span><span class="special">();</span> |
| <span class="special">}</span> |
| </pre> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_memory_segment_advanced_features.allocate_aligned"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_advanced_features.allocate_aligned" title="Allocating aligned memory portions">Allocating aligned memory portions</a> |
| </h4></div></div></div> |
| <p> |
| Sometimes it's interesting to be able to allocate aligned fragments of memory |
| because of some hardware or software restrictions. Sometimes, having |
| aligned memory is a feature that can be used to improve several |
| memory algorithms. |
| </p> |
| <p> |
| This allocation is similar to the previously shown raw memory allocation but |
| it takes an additional parameter specifying the alignment. There is |
| a restriction for the alignment: <span class="bold"><strong>the alignment must be power of two</strong></span>. |
| </p> |
| <p> |
| If a user wants to allocate many aligned blocks (for example aligned to 128 bytes), |
| the size that minimizes the memory waste is a value that's is nearly a multiple |
| of that alignment (for example 2*128 - some bytes). The reason for this is that |
| every memory allocation usually needs some additional metadata in the first |
| bytes of the allocated buffer. If the user can know the value of "some bytes" |
| and if the first bytes of a free block of memory are used to fulfill the aligned |
| allocation, the rest of the block can be left also aligned and ready for the next |
| aligned allocation. Note that requesting <span class="bold"><strong>a size multiple of the alignment is not optimal</strong></span> |
| because lefts the next block of memory unaligned due to the needed metadata. |
| </p> |
| <p> |
| Once the programmer knows the size of the payload of every memory allocation, |
| he can request a size that will be optimal to allocate aligned chunks |
| of memory maximizing both the size of the |
| request <span class="bold"><strong>and</strong></span> the possibilities of future aligned allocations. This information |
| is stored in the PayloadPerAllocation constant of managed memory segments. |
| </p> |
| <p> |
| Here is a small example showing how aligned allocation is used: |
| </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">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">//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">//Managed memory segment that allocates portions of a shared memory |
| </span> <span class="comment">//segment with the default management algorithm |
| </span> <span class="identifier">managed_shared_memory</span> <span class="identifier">managed_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">65536</span><span class="special">);</span> |
| |
| <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">Alignment</span> <span class="special">=</span> <span class="number">128</span><span class="special">;</span> |
| |
| <span class="comment">//Allocate 100 bytes aligned to Alignment from segment, throwing version |
| </span> <span class="keyword">void</span> <span class="special">*</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">allocate_aligned</span><span class="special">(</span><span class="number">100</span><span class="special">,</span> <span class="identifier">Alignment</span><span class="special">);</span> |
| |
| <span class="comment">//Check alignment |
| </span> <span class="identifier">assert</span><span class="special">((</span><span class="keyword">static_cast</span><span class="special"><</span><span class="keyword">char</span><span class="special">*>(</span><span class="identifier">ptr</span><span class="special">)-</span><span class="keyword">static_cast</span><span class="special"><</span><span class="keyword">char</span><span class="special">*>(</span><span class="number">0</span><span class="special">))</span> <span class="special">%</span> <span class="identifier">Alignment</span> <span class="special">==</span> <span class="number">0</span><span class="special">);</span> |
| |
| <span class="comment">//Deallocate it |
| </span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">deallocate</span><span class="special">(</span><span class="identifier">ptr</span><span class="special">);</span> |
| |
| <span class="comment">//Non throwing version |
| </span> <span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">allocate_aligned</span><span class="special">(</span><span class="number">100</span><span class="special">,</span> <span class="identifier">Alignment</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">nothrow</span><span class="special">);</span> |
| |
| <span class="comment">//Check alignment |
| </span> <span class="identifier">assert</span><span class="special">((</span><span class="keyword">static_cast</span><span class="special"><</span><span class="keyword">char</span><span class="special">*>(</span><span class="identifier">ptr</span><span class="special">)-</span><span class="keyword">static_cast</span><span class="special"><</span><span class="keyword">char</span><span class="special">*>(</span><span class="number">0</span><span class="special">))</span> <span class="special">%</span> <span class="identifier">Alignment</span> <span class="special">==</span> <span class="number">0</span><span class="special">);</span> |
| |
| <span class="comment">//Deallocate it |
| </span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">deallocate</span><span class="special">(</span><span class="identifier">ptr</span><span class="special">);</span> |
| |
| <span class="comment">//If we want to efficiently allocate aligned blocks of memory |
| </span> <span class="comment">//use managed_shared_memory::PayloadPerAllocation value |
| </span> <span class="identifier">assert</span><span class="special">(</span><span class="identifier">Alignment</span> <span class="special">></span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">PayloadPerAllocation</span><span class="special">);</span> |
| |
| <span class="comment">//This allocation will maximize the size of the aligned memory |
| </span> <span class="comment">//and will increase the possibility of finding more aligned memory |
| </span> <span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">allocate_aligned</span> |
| <span class="special">(</span><span class="number">3</span><span class="special">*</span><span class="identifier">Alignment</span> <span class="special">-</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">PayloadPerAllocation</span><span class="special">,</span> <span class="identifier">Alignment</span><span class="special">);</span> |
| |
| <span class="comment">//Check alignment |
| </span> <span class="identifier">assert</span><span class="special">((</span><span class="keyword">static_cast</span><span class="special"><</span><span class="keyword">char</span><span class="special">*>(</span><span class="identifier">ptr</span><span class="special">)-</span><span class="keyword">static_cast</span><span class="special"><</span><span class="keyword">char</span><span class="special">*>(</span><span class="number">0</span><span class="special">))</span> <span class="special">%</span> <span class="identifier">Alignment</span> <span class="special">==</span> <span class="number">0</span><span class="special">);</span> |
| |
| <span class="comment">//Deallocate it |
| </span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">deallocate</span><span class="special">(</span><span class="identifier">ptr</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.managed_memory_segments.managed_memory_segment_advanced_features.managed_memory_segment_multiple_allocations"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_advanced_features.managed_memory_segment_multiple_allocations" title="Multiple allocation functions">Multiple allocation functions</a> |
| </h4></div></div></div> |
| <p> |
| If an application needs to allocate a lot of memory buffers but it needs |
| to deallocate them independently, the application is normally forced to loop |
| calling <code class="computeroutput"><span class="identifier">allocate</span><span class="special">()</span></code>. Managed memory segments offer an alternative function |
| to pack several allocations in a single call obtaining memory buffers that: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| are packed contiguously in memory (which improves locality) |
| |
| </li> |
| <li class="listitem"> |
| can be independently deallocated. |
| |
| </li> |
| </ul></div> |
| <p> |
| This allocation method is much faster |
| than calling <code class="computeroutput"><span class="identifier">allocate</span><span class="special">()</span></code> in a loop. The downside is that the segment |
| must provide a contiguous memory segment big enough to hold all the allocations. |
| Managed memory segments offer this functionality through <code class="computeroutput"><span class="identifier">allocate_many</span><span class="special">()</span></code> functions. |
| There are 2 types of <code class="computeroutput"><span class="identifier">allocate_many</span></code> functions: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| Allocation of N buffers of memory with the same size. |
| |
| </li> |
| <li class="listitem"> |
| Allocation ot N buffers of memory, each one of different size. |
| |
| </li> |
| </ul></div> |
| <pre class="programlisting"><span class="comment">//!Allocates n_elements of elem_size bytes. |
| </span><span class="identifier">multiallocation_iterator</span> <span class="identifier">allocate_many</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">elem_size</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">min_elements</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">preferred_elements</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="special">&</span><span class="identifier">received_elements</span><span class="special">);</span> |
| |
| <span class="comment">//!Allocates n_elements, each one of elem_sizes[i] bytes. |
| </span><span class="identifier">multiallocation_iterator</span> <span class="identifier">allocate_many</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="special">*</span><span class="identifier">elem_sizes</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">n_elements</span><span class="special">);</span> |
| |
| <span class="comment">//!Allocates n_elements of elem_size bytes. No throwing version. |
| </span><span class="identifier">multiallocation_iterator</span> <span class="identifier">allocate_many</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">elem_size</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">min_elements</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">preferred_elements</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="special">&</span><span class="identifier">received_elements</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">nothrow_t</span> <span class="identifier">nothrow</span><span class="special">);</span> |
| |
| <span class="comment">//!Allocates n_elements, each one of elem_sizes[i] bytes. No throwing version. |
| </span><span class="identifier">multiallocation_iterator</span> <span class="identifier">allocate_many</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="special">*</span><span class="identifier">elem_sizes</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">n_elements</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">nothrow_t</span> <span class="identifier">nothrow</span><span class="special">);</span> |
| </pre> |
| <p> |
| All functions return a <code class="computeroutput"><span class="identifier">multiallocation</span> <span class="identifier">iterator</span></code> that can be used to obtain |
| pointers to memory the user can overwrite. A <code class="computeroutput"><span class="identifier">multiallocation_iterator</span></code>: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| Becomes invalidated if the memory is pointing to is deallocated or |
| the next iterators (which previously were reachable with <code class="computeroutput"><span class="keyword">operator</span><span class="special">++</span></code>) |
| become invalid. |
| |
| </li> |
| <li class="listitem"> |
| Returned from <code class="computeroutput"><span class="identifier">allocate_many</span></code> can be checked in a boolean expression to |
| know if the allocation has been successful. |
| |
| </li> |
| <li class="listitem"> |
| A default constructed <code class="computeroutput"><span class="identifier">multiallocation</span> <span class="identifier">iterator</span></code> indicates |
| both an invalid iterator and the "end" iterator. |
| |
| </li> |
| <li class="listitem"> |
| Dereferencing an iterator (<code class="computeroutput"><span class="keyword">operator</span> <span class="special">*()</span></code>) returns a <code class="computeroutput"><span class="keyword">char</span> <span class="special">&</span></code> |
| referencing the first byte user can overwrite |
| in the memory buffer. |
| |
| </li> |
| <li class="listitem"> |
| The iterator category depends on the memory allocation algorithm, |
| but it's at least a forward iterator. |
| |
| </li> |
| </ul></div> |
| <p> |
| Here is a small example showing all this functionality: |
| </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">detail</span><span class="special">/</span><span class="identifier">move</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> <span class="comment">//boost::interprocess::move |
| </span><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cassert</span><span class="special">>//</span><span class="identifier">assert</span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cstring</span><span class="special">>//</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">memset</span> |
| <span class="preprocessor">#include</span> <span class="special"><</span><span class="keyword">new</span><span class="special">></span> <span class="comment">//std::nothrow |
| </span><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">vector</span><span class="special">></span> <span class="comment">//std::vector |
| </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="keyword">typedef</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">multiallocation_chain</span> <span class="identifier">multiallocation_chain</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">managed_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">65536</span><span class="special">);</span> |
| |
| <span class="comment">//Allocate 16 elements of 100 bytes in a single call. Non-throwing version. |
| </span> <span class="identifier">multiallocation_chain</span> <span class="identifier">chain</span><span class="special">(</span><span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">allocate_many</span><span class="special">(</span><span class="number">100</span><span class="special">,</span> <span class="number">16</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">nothrow</span><span class="special">));</span> |
| |
| <span class="comment">//Check if the memory allocation was successful |
| </span> <span class="keyword">if</span><span class="special">(</span><span class="identifier">chain</span><span class="special">.</span><span class="identifier">empty</span><span class="special">())</span> <span class="keyword">return</span> <span class="number">1</span><span class="special">;</span> |
| |
| <span class="comment">//Allocated buffers |
| </span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">void</span><span class="special">*></span> <span class="identifier">allocated_buffers</span><span class="special">;</span> |
| |
| <span class="comment">//Initialize our data |
| </span> <span class="keyword">while</span><span class="special">(!</span><span class="identifier">chain</span><span class="special">.</span><span class="identifier">empty</span><span class="special">()){</span> |
| <span class="keyword">void</span> <span class="special">*</span><span class="identifier">buf</span> <span class="special">=</span> <span class="identifier">chain</span><span class="special">.</span><span class="identifier">front</span><span class="special">();</span> |
| <span class="identifier">chain</span><span class="special">.</span><span class="identifier">pop_front</span><span class="special">();</span> |
| <span class="identifier">allocated_buffers</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">buf</span><span class="special">);</span> |
| <span class="comment">//The iterator must be incremented before overwriting memory |
| </span> <span class="comment">//because otherwise, the iterator is invalidated. |
| </span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">memset</span><span class="special">(</span><span class="identifier">buf</span><span class="special">,</span> <span class="number">0</span><span class="special">,</span> <span class="number">100</span><span class="special">);</span> |
| <span class="special">}</span> |
| |
| <span class="comment">//Now deallocate |
| </span> <span class="keyword">while</span><span class="special">(!</span><span class="identifier">allocated_buffers</span><span class="special">.</span><span class="identifier">empty</span><span class="special">()){</span> |
| <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">deallocate</span><span class="special">(</span><span class="identifier">allocated_buffers</span><span class="special">.</span><span class="identifier">back</span><span class="special">());</span> |
| <span class="identifier">allocated_buffers</span><span class="special">.</span><span class="identifier">pop_back</span><span class="special">();</span> |
| <span class="special">}</span> |
| |
| <span class="comment">//Allocate 10 buffers of different sizes in a single call. Throwing version |
| </span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">sizes</span><span class="special">[</span><span class="number">10</span><span class="special">];</span> |
| <span class="keyword">for</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</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">10</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span> |
| <span class="identifier">sizes</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">i</span><span class="special">*</span><span class="number">3</span><span class="special">;</span> |
| |
| <span class="identifier">chain</span> <span class="special">=</span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">allocate_many</span><span class="special">(</span><span class="identifier">sizes</span><span class="special">,</span> <span class="number">10</span><span class="special">);</span> |
| <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">deallocate_many</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">chain</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> |
| Allocating N buffers of the same size improves the performance of pools |
| and node containers (for example STL-like lists): when inserting a range of |
| forward iterators in a STL-like list, the insertion function can detect the |
| number of needed elements and allocate in a single call. The nodes still |
| can be deallocated. |
| </p> |
| <p> |
| Allocating N buffers of different sizes can be used to speed up allocation in |
| cases where several objects must always be allocated at the same time but |
| deallocated at different times. For example, a class might perform several initial |
| allocations (some header data for a network packet, for example) in its |
| constructor but also allocations of buffers that might be reallocated in the future |
| (the data to be sent through the network). Instead of allocating all the data |
| independently, the constructor might use <code class="computeroutput"><span class="identifier">allocate_many</span><span class="special">()</span></code> to speed up the |
| initialization, but it still can deallocate and expand the memory of the variable |
| size element. |
| </p> |
| <p> |
| In general, <code class="computeroutput"><span class="identifier">allocate_many</span></code> is useful with large values of N. Overuse |
| of <code class="computeroutput"><span class="identifier">allocate_many</span></code> can increase the effective memory usage, |
| because it can't reuse existing non-contiguous memory fragments that |
| might be available for some of the elements. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_memory_segment_advanced_features.managed_memory_segment_expand_in_place"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_advanced_features.managed_memory_segment_expand_in_place" title="Expand in place memory allocation">Expand in place memory allocation</a> |
| </h4></div></div></div> |
| <p> |
| When programming some data structures such as vectors, memory reallocation becomes |
| an important tool to improve performance. Managed memory segments offer an advanced |
| reallocation function that offers: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| Forward expansion: An allocated buffer can be expanded so that the end of the buffer |
| is moved further. New data can be written between the old end and the new end. |
| |
| </li> |
| <li class="listitem"> |
| Backwards expansion: An allocated buffer can be expanded so that the beginning of |
| the buffer is moved backwards. New data can be written between the new beginning |
| and the old beginning. |
| |
| </li> |
| <li class="listitem"> |
| Shrinking: An allocated buffer can be shrunk so that the end of the buffer |
| is moved backwards. The memory between the new end and the old end can be reused |
| for future allocations. |
| |
| </li> |
| </ul></div> |
| <p> |
| The expansion can be combined with the allocation of a new buffer if the expansion |
| fails obtaining a function with "expand, if fails allocate a new buffer" semantics. |
| </p> |
| <p> |
| Apart from this features, the function always returns the real size of the |
| allocated buffer, because many times, due to alignment issues the allocated |
| buffer a bit bigger than the requested size. Thus, the programmer can maximize |
| the memory use using <code class="computeroutput"><span class="identifier">allocation_command</span></code>. |
| </p> |
| <p> |
| Here is the declaration of the function: |
| </p> |
| <pre class="programlisting"><span class="keyword">enum</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">allocation_type</span> |
| <span class="special">{</span> |
| <span class="comment">//Bitwise OR (|) combinable values |
| </span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">allocate_new</span> <span class="special">=</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">expand_fwd</span> <span class="special">=</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">expand_bwd</span> <span class="special">=</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">shrink_in_place</span> <span class="special">=</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">nothrow_allocation</span> <span class="special">=</span> <span class="special">...</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="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span><span class="identifier">T</span> <span class="special">*,</span> <span class="keyword">bool</span><span class="special">></span> |
| <span class="identifier">allocation_command</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">allocation_type</span> <span class="identifier">command</span> |
| <span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">limit_size</span> |
| <span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">preferred_size</span> |
| <span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="special">&</span><span class="identifier">received_size</span> |
| <span class="special">,</span> <span class="identifier">T</span> <span class="special">*</span><span class="identifier">reuse_ptr</span> <span class="special">=</span> <span class="number">0</span><span class="special">);</span> |
| </pre> |
| <p> |
| <span class="bold"><strong>Preconditions for the function</strong></span>: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| If the parameter command contains the value <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">shrink_in_place</span></code> it can't |
| contain any of these values: <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">expand_fwd</span></code>, <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">expand_bwd</span></code>. |
| |
| </li> |
| <li class="listitem"> |
| If the parameter command contains <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">expand_fwd</span></code> or <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">expand_bwd</span></code>, the parameter |
| <code class="computeroutput"><span class="identifier">reuse_ptr</span></code> must be non-null and returned by a previous allocation function. |
| |
| </li> |
| <li class="listitem"> |
| If the parameter command contains the value <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">shrink_in_place</span></code>, the parameter |
| <code class="computeroutput"><span class="identifier">limit_size</span></code> must be equal or greater than the parameter <code class="computeroutput"><span class="identifier">preferred_size</span></code>. |
| |
| </li> |
| <li class="listitem"> |
| If the parameter <code class="computeroutput"><span class="identifier">command</span></code> contains any of these values: <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">expand_fwd</span></code> or <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">expand_bwd</span></code>, |
| the parameter <code class="computeroutput"><span class="identifier">limit_size</span></code> must be equal or less than the parameter <code class="computeroutput"><span class="identifier">preferred_size</span></code>. |
| |
| </li> |
| </ul></div> |
| <p> |
| <span class="bold"><strong>Which are the effects of this function:</strong></span> |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| If the parameter command contains the value <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">shrink_in_place</span></code>, the function |
| will try to reduce the size of the memory block referenced by pointer <code class="computeroutput"><span class="identifier">reuse_ptr</span></code> |
| to the value <code class="computeroutput"><span class="identifier">preferred_size</span></code> moving only the end of the block. |
| If it's not possible, it will try to reduce the size of the memory block as |
| much as possible as long as this results in <code class="computeroutput"><span class="identifier">size</span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span> <span class="special"><=</span> <span class="identifier">limit_size</span></code>. Success |
| is reported only if this results in <code class="computeroutput"><span class="identifier">preferred_size</span> <span class="special"><=</span> <span class="identifier">size</span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code> and <code class="computeroutput"><span class="identifier">size</span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span> <span class="special"><=</span> <span class="identifier">limit_size</span></code>. |
| |
| </li> |
| <li class="listitem"> |
| If the parameter <code class="computeroutput"><span class="identifier">command</span></code> only contains the value <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">expand_fwd</span></code> (with optional |
| additional <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">nothrow_allocation</span></code>), the allocator will try to increase the size of the |
| memory block referenced by pointer reuse moving only the end of the block to the |
| value <code class="computeroutput"><span class="identifier">preferred_size</span></code>. If it's not possible, it will try to increase the size |
| of the memory block as much as possible as long as this results in |
| <code class="computeroutput"><span class="identifier">size</span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span> <span class="special">>=</span> <span class="identifier">limit_size</span></code>. Success is reported only if this results in <code class="computeroutput"><span class="identifier">limit_size</span> <span class="special"><=</span> <span class="identifier">size</span><span class="special">(</span><span class="identifier">p</span><span class="special">)</span></code>. |
| |
| </li> |
| <li class="listitem"> |
| If the parameter <code class="computeroutput"><span class="identifier">command</span></code> only contains the value <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">expand_bwd</span></code> (with optional |
| additional <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">nothrow_allocation</span></code>), the allocator will try to increase the size of |
| the memory block referenced by pointer <code class="computeroutput"><span class="identifier">reuse_ptr</span></code> only moving the start of the |
| block to a returned new position <code class="computeroutput"><span class="identifier">new_ptr</span></code>. If it's not possible, it will try to |
| move the start of the block as much as possible as long as this results in |
| <code class="computeroutput"><span class="identifier">size</span><span class="special">(</span><span class="identifier">new_ptr</span><span class="special">)</span> <span class="special">>=</span> <span class="identifier">limit_size</span></code>. Success is reported only if this results in |
| <code class="computeroutput"><span class="identifier">limit_size</span> <span class="special"><=</span> <span class="identifier">size</span><span class="special">(</span><span class="identifier">new_ptr</span><span class="special">)</span></code>. |
| |
| </li> |
| <li class="listitem"> |
| If the parameter <code class="computeroutput"><span class="identifier">command</span></code> only contains the value <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">allocate_new</span></code> (with optional |
| additional <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">nothrow_allocation</span></code>), the allocator will try to allocate memory for |
| <code class="computeroutput"><span class="identifier">preferred_size</span></code> objects. If it's not possible it will try to allocate memory for |
| at least <code class="computeroutput"><span class="identifier">limit_size</span></code> objects. |
| |
| </li> |
| <li class="listitem"> |
| If the parameter <code class="computeroutput"><span class="identifier">command</span></code> only contains a combination of <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">expand_fwd</span></code> and |
| <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">allocate_new</span></code>, (with optional additional <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">nothrow_allocation</span></code>) the allocator will |
| try first the forward expansion. If this fails, it would try a new allocation. |
| |
| </li> |
| <li class="listitem"> |
| If the parameter <code class="computeroutput"><span class="identifier">command</span></code> only contains a combination of <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">expand_bwd</span></code> and |
| <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">allocate_new</span></code> (with optional additional <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">nothrow_allocation</span></code>), the allocator will |
| try first to obtain <code class="computeroutput"><span class="identifier">preferred_size</span></code> objects using both methods if necessary. |
| If this fails, it will try to obtain <code class="computeroutput"><span class="identifier">limit_size</span></code> objects using both methods if |
| necessary. |
| |
| </li> |
| <li class="listitem"> |
| If the parameter <code class="computeroutput"><span class="identifier">command</span></code> only contains a combination of <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">expand_fwd</span></code> and |
| <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">expand_bwd</span></code> (with optional additional <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">nothrow_allocation</span></code>), the allocator will |
| try first forward expansion. If this fails it will try to obtain preferred_size |
| objects using backwards expansion or a combination of forward and backwards expansion. |
| If this fails, it will try to obtain <code class="computeroutput"><span class="identifier">limit_size</span></code> objects using both methods if |
| necessary. |
| |
| </li> |
| <li class="listitem"> |
| If the parameter <code class="computeroutput"><span class="identifier">command</span></code> only contains a combination of allocation_new, |
| <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">expand_fwd</span></code> and <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">expand_bwd</span></code>, (with optional additional <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">nothrow_allocation</span></code>) |
| the allocator will try first forward expansion. If this fails it will try to obtain |
| preferred_size objects using new allocation, backwards expansion or a combination of |
| forward and backwards expansion. If this fails, it will try to obtain <code class="computeroutput"><span class="identifier">limit_size</span></code> |
| objects using the same methods. |
| |
| </li> |
| <li class="listitem"> |
| The allocator always writes the size or the expanded/allocated/shrunk memory block |
| in <code class="computeroutput"><span class="identifier">received_size</span></code>. On failure the allocator writes in <code class="computeroutput"><span class="identifier">received_size</span></code> a possibly |
| successful <code class="computeroutput"><span class="identifier">limit_size</span></code> parameter for a new call. |
| |
| </li> |
| </ul></div> |
| <p> |
| <span class="bold"><strong>Throws an exception if two conditions are met:</strong></span> |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| The allocator is unable to allocate/expand/shrink the memory or there is an |
| error in preconditions |
| |
| </li> |
| <li class="listitem"> |
| The parameter command does not contain <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">nothrow_allocation</span></code>. |
| |
| </li> |
| </ul></div> |
| <p> |
| <span class="bold"><strong>This function returns:</strong></span> |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| The address of the allocated memory or the new address of the expanded memory |
| as the first member of the pair. If the parameter command contains |
| <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">nothrow_allocation</span></code> the first member will be 0 |
| if the allocation/expansion fails or there is an error in preconditions. |
| |
| </li> |
| <li class="listitem"> |
| The second member of the pair will be false if the memory has been allocated, |
| true if the memory has been expanded. If the first member is 0, the second member |
| has an undefined value. |
| |
| </li> |
| </ul></div> |
| <p> |
| <span class="bold"><strong>Notes:</strong></span> |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| If the user chooses <code class="computeroutput"><span class="keyword">char</span></code> as template argument the returned buffer will |
| be suitably aligned to hold any type. |
| |
| </li> |
| <li class="listitem"> |
| If the user chooses <code class="computeroutput"><span class="keyword">char</span></code> as template argument and a backwards expansion is |
| performed, although properly aligned, the returned buffer might not be |
| suitable because the distance between the new beginning and the old beginning |
| might not multiple of the type the user wants to construct, since due to internal |
| restrictions the expansion can be slightly bigger than the requested bytes. <span class="bold"><strong>When |
| performing backwards expansion, if you have already constructed objects in the |
| old buffer, make sure to specify correctly the type.</strong></span> |
| |
| </li> |
| </ul></div> |
| <p> |
| Here is a small example that shows the use of <code class="computeroutput"><span class="identifier">allocation_command</span></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">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">//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">//Managed memory segment that allocates portions of a shared memory |
| </span> <span class="comment">//segment with the default management algorithm |
| </span> <span class="identifier">managed_shared_memory</span> <span class="identifier">managed_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="keyword">sizeof</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">));</span> |
| |
| <span class="comment">//Allocate at least 100 bytes, 1000 bytes if possible |
| </span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">received_size</span><span class="special">,</span> <span class="identifier">min_size</span> <span class="special">=</span> <span class="number">100</span><span class="special">,</span> <span class="identifier">preferred_size</span> <span class="special">=</span> <span class="number">1000</span><span class="special">;</span> |
| <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="special">*</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">allocation_command</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">></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">allocate_new</span><span class="special">,</span> <span class="identifier">min_size</span><span class="special">,</span> <span class="identifier">preferred_size</span><span class="special">,</span> <span class="identifier">received_size</span><span class="special">).</span><span class="identifier">first</span><span class="special">;</span> |
| |
| <span class="comment">//Received size must be bigger than min_size |
| </span> <span class="identifier">assert</span><span class="special">(</span><span class="identifier">received_size</span> <span class="special">>=</span> <span class="identifier">min_size</span><span class="special">);</span> |
| |
| <span class="comment">//Get free memory |
| </span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">free_memory_after_allocation</span> <span class="special">=</span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">get_free_memory</span><span class="special">();</span> |
| |
| <span class="comment">//Now write the data |
| </span> <span class="keyword">for</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</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="identifier">received_size</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span> <span class="identifier">ptr</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">i</span><span class="special">;</span> |
| |
| <span class="comment">//Now try to triplicate the buffer. We won't admit an expansion |
| </span> <span class="comment">//lower to the double of the original buffer. |
| </span> <span class="comment">//This "should" be successful since no other class is allocating |
| </span> <span class="comment">//memory from the segment |
| </span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">expanded_size</span><span class="special">;</span> |
| <span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="special">*,</span> <span class="keyword">bool</span><span class="special">></span> <span class="identifier">ret</span> <span class="special">=</span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">allocation_command</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">expand_fwd</span><span class="special">,</span> <span class="identifier">received_size</span><span class="special">*</span><span class="number">2</span><span class="special">,</span> <span class="identifier">received_size</span><span class="special">*</span><span class="number">3</span><span class="special">,</span> <span class="identifier">expanded_size</span><span class="special">,</span> <span class="identifier">ptr</span><span class="special">);</span> |
| |
| <span class="comment">//Check invariants |
| </span> <span class="identifier">assert</span><span class="special">(</span><span class="identifier">ret</span><span class="special">.</span><span class="identifier">second</span> <span class="special">==</span> <span class="keyword">true</span><span class="special">);</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">ret</span><span class="special">.</span><span class="identifier">first</span> <span class="special">==</span> <span class="identifier">ptr</span><span class="special">);</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">expanded_size</span> <span class="special">>=</span> <span class="identifier">received_size</span><span class="special">*</span><span class="number">2</span><span class="special">);</span> |
| |
| <span class="comment">//Get free memory and compare |
| </span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">free_memory_after_expansion</span> <span class="special">=</span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">get_free_memory</span><span class="special">();</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">free_memory_after_expansion</span> <span class="special"><</span> <span class="identifier">free_memory_after_allocation</span><span class="special">);</span> |
| |
| <span class="comment">//Write new values |
| </span> <span class="keyword">for</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">i</span> <span class="special">=</span> <span class="identifier">received_size</span><span class="special">;</span> <span class="identifier">i</span> <span class="special"><</span> <span class="identifier">expanded_size</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span> <span class="identifier">ptr</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">i</span><span class="special">;</span> |
| |
| <span class="comment">//Try to shrink approximately to min_size, but the new size |
| </span> <span class="comment">//should be smaller than min_size*2. |
| </span> <span class="comment">//This "should" be successful since no other class is allocating |
| </span> <span class="comment">//memory from the segment |
| </span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">shrunk_size</span><span class="special">;</span> |
| <span class="identifier">ret</span> <span class="special">=</span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">allocation_command</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">shrink_in_place</span><span class="special">,</span> <span class="identifier">min_size</span><span class="special">*</span><span class="number">2</span><span class="special">,</span> <span class="identifier">min_size</span><span class="special">,</span> <span class="identifier">shrunk_size</span><span class="special">,</span> <span class="identifier">ptr</span><span class="special">);</span> |
| |
| <span class="comment">//Check invariants |
| </span> <span class="identifier">assert</span><span class="special">(</span><span class="identifier">ret</span><span class="special">.</span><span class="identifier">second</span> <span class="special">==</span> <span class="keyword">true</span><span class="special">);</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">ret</span><span class="special">.</span><span class="identifier">first</span> <span class="special">==</span> <span class="identifier">ptr</span><span class="special">);</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">shrunk_size</span> <span class="special"><=</span> <span class="identifier">min_size</span><span class="special">*</span><span class="number">2</span><span class="special">);</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">shrunk_size</span> <span class="special">>=</span> <span class="identifier">min_size</span><span class="special">);</span> |
| |
| <span class="comment">//Get free memory and compare |
| </span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">free_memory_after_shrinking</span> <span class="special">=</span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">get_free_memory</span><span class="special">();</span> |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">free_memory_after_shrinking</span> <span class="special">></span> <span class="identifier">free_memory_after_expansion</span><span class="special">);</span> |
| |
| <span class="comment">//Deallocate the buffer |
| </span> <span class="identifier">managed_shm</span><span class="special">.</span><span class="identifier">deallocate</span><span class="special">(</span><span class="identifier">ptr</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> |
| <code class="computeroutput"><span class="identifier">allocation_command</span></code> is a very powerful function that can lead to important |
| performance gains. It's specially useful when programming vector-like data |
| structures where the programmer can minimize both the number of allocation |
| requests and the memory waste. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_memory_segment_advanced_features.copy_on_write_read_only"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_advanced_features.copy_on_write_read_only" title="Opening managed shared memory and mapped files with Copy On Write or Read Only modes">Opening managed shared memory and mapped files with Copy On Write or Read Only modes</a> |
| </h4></div></div></div> |
| <p> |
| When mapping a memory segment based on shared memory or files, there is an option to |
| open them using <span class="bold"><strong>open_copy_on_write</strong></span> option. This option is similar to <code class="computeroutput"><span class="identifier">open_only</span></code> but |
| every change the programmer does with this managed segment is kept private to this process |
| and is not translated to the underlying device (shared memory or file). |
| </p> |
| <p> |
| The underlying shared memory or file is opened as read-only so several processes can |
| share an initial managed segment and make private changes to it. If many processes |
| open a managed segment in copy on write mode and not modified pages from the managed |
| segment will be shared between all those processes, with considerable memory savings. |
| </p> |
| <p> |
| Opening managed shared memory and mapped files with <span class="bold"><strong>open_read_only</strong></span> maps the |
| underlying device in memory with <span class="bold"><strong>read-only</strong></span> attributes. This means that any attempt |
| to write that memory, either creating objects or locking any mutex might result in an |
| page-fault error (and thus, program termination) from the OS. Read-only mode opens |
| the underlying device (shared memory, file...) in read-only mode and |
| can result in considerable memory savings if several processes just want to process |
| a managed memory segment without modifying it. Read-only mode operations are limited: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| Read-only mode must be used only from managed classes. If the programmer obtains |
| the segment manager and tries to use it directly it might result in an access violation. |
| The reason for this is that the segment manager is placed in the underlying device |
| and does not nothing about the mode it's been mapped in memory. |
| |
| </li> |
| <li class="listitem"> |
| Only const member functions from managed segments should be used. |
| |
| </li> |
| <li class="listitem"> |
| Additionally, the <code class="computeroutput"><span class="identifier">find</span><span class="special"><></span></code> member function avoids using internal locks and can be |
| used to look for named and unique objects. |
| |
| </li> |
| </ul></div> |
| <p> |
| Here is an example that shows the use of these two open modes: |
| </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_mapped_file</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">fstream</span><span class="special">></span> <span class="comment">//std::fstream |
| </span><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iterator</span><span class="special">>//</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">distance</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">//Try to erase any previous managed segment with the same name |
| </span> <span class="identifier">file_mapping</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MyManagedFile"</span><span class="special">);</span> |
| <span class="identifier">file_mapping</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MyManagedFile2"</span><span class="special">);</span> |
| <span class="identifier">remove_file_on_destroy</span> <span class="identifier">destroyer1</span><span class="special">(</span><span class="string">"MyManagedFile"</span><span class="special">);</span> |
| <span class="identifier">remove_file_on_destroy</span> <span class="identifier">destroyer2</span><span class="special">(</span><span class="string">"MyManagedFile2"</span><span class="special">);</span> |
| |
| <span class="special">{</span> |
| <span class="comment">//Create an named integer in a managed mapped file |
| </span> <span class="identifier">managed_mapped_file</span> <span class="identifier">managed_file</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> <span class="string">"MyManagedFile"</span><span class="special">,</span> <span class="number">65536</span><span class="special">);</span> |
| <span class="identifier">managed_file</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="string">"MyInt"</span><span class="special">)(</span><span class="number">0u</span><span class="special">);</span> |
| |
| <span class="comment">//Now create a copy on write version |
| </span> <span class="identifier">managed_mapped_file</span> <span class="identifier">managed_file_cow</span><span class="special">(</span><span class="identifier">open_copy_on_write</span><span class="special">,</span> <span class="string">"MyManagedFile"</span><span class="special">);</span> |
| |
| <span class="comment">//Erase the int and create a new one |
| </span> <span class="keyword">if</span><span class="special">(!</span><span class="identifier">managed_file_cow</span><span class="special">.</span><span class="identifier">destroy</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="string">"MyInt"</span><span class="special">))</span> |
| <span class="keyword">throw</span> <span class="keyword">int</span><span class="special">(</span><span class="number">0</span><span class="special">);</span> |
| <span class="identifier">managed_file_cow</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="string">"MyInt2"</span><span class="special">);</span> |
| |
| <span class="comment">//Check changes |
| </span> <span class="keyword">if</span><span class="special">(</span><span class="identifier">managed_file_cow</span><span class="special">.</span><span class="identifier">find</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="string">"MyInt"</span><span class="special">).</span><span class="identifier">first</span> <span class="special">&&</span> <span class="special">!</span><span class="identifier">managed_file_cow</span><span class="special">.</span><span class="identifier">find</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="string">"MyInt2"</span><span class="special">).</span><span class="identifier">first</span><span class="special">)</span> |
| <span class="keyword">throw</span> <span class="keyword">int</span><span class="special">(</span><span class="number">0</span><span class="special">);</span> |
| |
| <span class="comment">//Check the original is intact |
| </span> <span class="keyword">if</span><span class="special">(!</span><span class="identifier">managed_file</span><span class="special">.</span><span class="identifier">find</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="string">"MyInt"</span><span class="special">).</span><span class="identifier">first</span> <span class="special">&&</span> <span class="identifier">managed_file</span><span class="special">.</span><span class="identifier">find</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="string">"MyInt2"</span><span class="special">).</span><span class="identifier">first</span><span class="special">)</span> |
| <span class="keyword">throw</span> <span class="keyword">int</span><span class="special">(</span><span class="number">0</span><span class="special">);</span> |
| |
| <span class="special">{</span> <span class="comment">//Dump the modified copy on write segment to a file |
| </span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">fstream</span> <span class="identifier">file</span><span class="special">(</span><span class="string">"MyManagedFile2"</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">out</span> <span class="special">|</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ios_base</span><span class="special">::</span><span class="identifier">binary</span><span class="special">);</span> |
| <span class="keyword">if</span><span class="special">(!</span><span class="identifier">file</span><span class="special">)</span> |
| <span class="keyword">throw</span> <span class="keyword">int</span><span class="special">(</span><span class="number">0</span><span class="special">);</span> |
| <span class="identifier">file</span><span class="special">.</span><span class="identifier">write</span><span class="special">(</span><span class="keyword">static_cast</span><span class="special"><</span><span class="keyword">const</span> <span class="keyword">char</span> <span class="special">*>(</span><span class="identifier">managed_file_cow</span><span class="special">.</span><span class="identifier">get_address</span><span class="special">()),</span> <span class="identifier">managed_file_cow</span><span class="special">.</span><span class="identifier">get_size</span><span class="special">());</span> |
| <span class="special">}</span> |
| |
| <span class="comment">//Now open the modified file and test changes |
| </span> <span class="identifier">managed_mapped_file</span> <span class="identifier">managed_file_cow2</span><span class="special">(</span><span class="identifier">open_only</span><span class="special">,</span> <span class="string">"MyManagedFile2"</span><span class="special">);</span> |
| <span class="keyword">if</span><span class="special">(</span><span class="identifier">managed_file_cow2</span><span class="special">.</span><span class="identifier">find</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="string">"MyInt"</span><span class="special">).</span><span class="identifier">first</span> <span class="special">&&</span> <span class="special">!</span><span class="identifier">managed_file_cow2</span><span class="special">.</span><span class="identifier">find</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="string">"MyInt2"</span><span class="special">).</span><span class="identifier">first</span><span class="special">)</span> |
| <span class="keyword">throw</span> <span class="keyword">int</span><span class="special">(</span><span class="number">0</span><span class="special">);</span> |
| <span class="special">}</span> |
| <span class="special">{</span> |
| <span class="comment">//Now create a read-only version |
| </span> <span class="identifier">managed_mapped_file</span> <span class="identifier">managed_file_ro</span><span class="special">(</span><span class="identifier">open_read_only</span><span class="special">,</span> <span class="string">"MyManagedFile"</span><span class="special">);</span> |
| |
| <span class="comment">//Check the original is intact |
| </span> <span class="keyword">if</span><span class="special">(!</span><span class="identifier">managed_file_ro</span><span class="special">.</span><span class="identifier">find</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="string">"MyInt"</span><span class="special">).</span><span class="identifier">first</span> <span class="special">&&</span> <span class="identifier">managed_file_ro</span><span class="special">.</span><span class="identifier">find</span><span class="special"><</span><span class="keyword">int</span><span class="special">>(</span><span class="string">"MyInt2"</span><span class="special">).</span><span class="identifier">first</span><span class="special">)</span> |
| <span class="keyword">throw</span> <span class="keyword">int</span><span class="special">(</span><span class="number">0</span><span class="special">);</span> |
| |
| <span class="comment">//Check the number of named objects using the iterators |
| </span> <span class="keyword">if</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">distance</span><span class="special">(</span><span class="identifier">managed_file_ro</span><span class="special">.</span><span class="identifier">named_begin</span><span class="special">(),</span> <span class="identifier">managed_file_ro</span><span class="special">.</span><span class="identifier">named_end</span><span class="special">())</span> <span class="special">!=</span> <span class="number">1</span> <span class="special">&&</span> |
| <span class="identifier">std</span><span class="special">::</span><span class="identifier">distance</span><span class="special">(</span><span class="identifier">managed_file_ro</span><span class="special">.</span><span class="identifier">unique_begin</span><span class="special">(),</span> <span class="identifier">managed_file_ro</span><span class="special">.</span><span class="identifier">unique_end</span><span class="special">())</span> <span class="special">!=</span> <span class="number">0</span> <span class="special">)</span> |
| <span class="keyword">throw</span> <span class="keyword">int</span><span class="special">(</span><span class="number">0</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.managed_memory_segments.managed_heap_memory_external_buffer"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_heap_memory_external_buffer" title="Managed Heap Memory And Managed External Buffer">Managed Heap Memory And Managed External Buffer</a> |
| </h3></div></div></div> |
| <div class="toc"><dl> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_heap_memory_external_buffer.managed_external_buffer">Managed External Buffer: Constructing all Boost.Interprocess objects in a user provided buffer</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_heap_memory_external_buffer.managed_heap_memory">Managed Heap Memory: Boost.Interprocess machinery in heap memory</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_heap_memory_external_buffer.managed_heap_memory_external_buffer_diff">Differences between managed memory segments</a></span></dt> |
| <dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_heap_memory_external_buffer.shared_message_queue_ex">Example: Serializing a database through the message queue</a></span></dt> |
| </dl></div> |
| <p> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> offers managed shared memory between processes using |
| <code class="computeroutput"><span class="identifier">managed_shared_memory</span></code> or <code class="computeroutput"><span class="identifier">managed_mapped_file</span></code>. Two processes just map the same |
| the memory mappable resource and read from and write to that object. |
| </p> |
| <p> |
| Many times, we don't want to use that shared memory approach and we prefer |
| to send serialized data through network, local socket or message queues. Serialization |
| can be done through <span class="bold"><strong>Boost.Serialization</strong></span> or similar library. However, if two processes |
| share the same ABI (application binary interface), we could use the same object and |
| container construction capabilities of <code class="computeroutput"><span class="identifier">managed_shared_memory</span></code> or <code class="computeroutput"><span class="identifier">managed_heap_memory</span></code> |
| to build all the information in a single buffer that will be sent, for example, |
| though message queues. The receiver would just copy the data to a local buffer, and it |
| could read or modify it directly without deserializing the data . This approach can be |
| much more efficient that a complex serialization mechanism. |
| </p> |
| <p> |
| Applications for <span class="bold"><strong>Boost.Interprocess</strong></span> services using non-shared memory buffers: |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| Create and use STL compatible containers and allocators, |
| in systems where dynamic memory is not recommendable. |
| |
| </li> |
| <li class="listitem"> |
| <p class="simpara"> |
| Build complex, easily serializable databases in a single buffer: |
| |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="circle"> |
| <li class="listitem"> |
| To share data between threads |
| |
| </li> |
| <li class="listitem"> |
| To save and load information from/to files. |
| |
| </li> |
| </ul></div> |
| </li> |
| <li class="listitem"> |
| Duplicate information (containers, allocators, etc...) just copying the contents of |
| one buffer to another one. |
| |
| </li> |
| <li class="listitem"> |
| Send complex information and objects/databases using serial/inter-process/network |
| communications. |
| |
| </li> |
| </ul></div> |
| <p> |
| To help with this management, <span class="bold"><strong>Boost.Interprocess</strong></span> provides two useful classes, |
| <code class="computeroutput"><span class="identifier">basic_managed_heap_memory</span></code> and <code class="computeroutput"><span class="identifier">basic_managed_external_buffer</span></code>: |
| </p> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_heap_memory_external_buffer.managed_external_buffer"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_heap_memory_external_buffer.managed_external_buffer" title="Managed External Buffer: Constructing all Boost.Interprocess objects in a user provided buffer">Managed External Buffer: Constructing all Boost.Interprocess objects in a user provided buffer</a> |
| </h4></div></div></div> |
| <p> |
| Sometimes, the user wants to create simple objects, STL compatible containers, STL compatible |
| strings and more, all in a single buffer. This buffer could be a big static buffer, |
| a memory-mapped auxiliary device or any other user buffer. |
| </p> |
| <p> |
| This would allow an easy serialization and we-ll just need to copy the buffer to duplicate |
| all the objects created in the original buffer, including complex objects like |
| maps, lists.... <span class="bold"><strong>Boost.Interprocess</strong></span> offers managed memory segment classes to handle user |
| provided buffers that allow the same functionality as shared memory classes: |
| </p> |
| <pre class="programlisting"><span class="comment">//Named object creation managed memory segment |
| </span><span class="comment">//All objects are constructed in a user provided buffer |
| </span><span class="keyword">template</span> <span class="special"><</span> |
| <span class="keyword">class</span> <span class="identifier">CharType</span><span class="special">,</span> |
| <span class="keyword">class</span> <span class="identifier">MemoryAlgorithm</span><span class="special">,</span> |
| <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">IndexConfig</span><span class="special">></span> <span class="keyword">class</span> <span class="identifier">IndexType</span> |
| <span class="special">></span> |
| <span class="keyword">class</span> <span class="identifier">basic_managed_external_buffer</span><span class="special">;</span> |
| |
| <span class="comment">//Named object creation managed memory segment |
| </span><span class="comment">//All objects are constructed in a user provided buffer |
| </span><span class="comment">// Names are c-strings, |
| </span><span class="comment">// Default memory management algorithm |
| </span><span class="comment">// (rbtree_best_fit with no mutexes and relative pointers) |
| </span><span class="comment">// Name-object mappings are stored in the default index type (flat_map) |
| </span><span class="keyword">typedef</span> <span class="identifier">basic_managed_external_buffer</span> <span class="special"><</span> |
| <span class="keyword">char</span><span class="special">,</span> |
| <span class="identifier">rbtree_best_fit</span><span class="special"><</span><span class="identifier">null_mutex_family</span><span class="special">,</span> <span class="identifier">offset_ptr</span><span class="special"><</span><span class="keyword">void</span><span class="special">></span> <span class="special">>,</span> |
| <span class="identifier">flat_map_index</span> |
| <span class="special">></span> <span class="identifier">managed_external_buffer</span><span class="special">;</span> |
| |
| <span class="comment">//Named object creation managed memory segment |
| </span><span class="comment">//All objects are constructed in a user provided buffer |
| </span><span class="comment">// Names are wide-strings, |
| </span><span class="comment">// Default memory management algorithm |
| </span><span class="comment">// (rbtree_best_fit with no mutexes and relative pointers) |
| </span><span class="comment">// Name-object mappings are stored in the default index type (flat_map) |
| </span><span class="keyword">typedef</span> <span class="identifier">basic_managed_external_buffer</span><span class="special"><</span> |
| <span class="keyword">wchar_t</span><span class="special">,</span> |
| <span class="identifier">rbtree_best_fit</span><span class="special"><</span><span class="identifier">null_mutex_family</span><span class="special">,</span> <span class="identifier">offset_ptr</span><span class="special"><</span><span class="keyword">void</span><span class="special">></span> <span class="special">>,</span> |
| <span class="identifier">flat_map_index</span> |
| <span class="special">></span> <span class="identifier">wmanaged_external_buffer</span><span class="special">;</span> |
| </pre> |
| <p> |
| To use a managed external buffer, 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">managed_external_buffer</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <p> |
| Let's see an example of the use of managed_external_buffer: |
| </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_external_buffer</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">list</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">cstring</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">aligned_storage</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">//Create the static memory who will store all objects |
| </span> <span class="keyword">const</span> <span class="keyword">int</span> <span class="identifier">memsize</span> <span class="special">=</span> <span class="number">65536</span><span class="special">;</span> |
| |
| <span class="keyword">static</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">aligned_storage</span><span class="special"><</span><span class="identifier">memsize</span><span class="special">>::</span><span class="identifier">type</span> <span class="identifier">static_buffer</span><span class="special">;</span> |
| |
| <span class="comment">//This managed memory will construct objects associated with |
| </span> <span class="comment">//a wide string in the static buffer |
| </span> <span class="identifier">wmanaged_external_buffer</span> <span class="identifier">objects_in_static_memory</span> |
| <span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> <span class="special">&</span><span class="identifier">static_buffer</span><span class="special">,</span> <span class="identifier">memsize</span><span class="special">);</span> |
| |
| <span class="comment">//We optimize resources to create 100 named objects in the static buffer |
| </span> <span class="identifier">objects_in_static_memory</span><span class="special">.</span><span class="identifier">reserve_named_objects</span><span class="special">(</span><span class="number">100</span><span class="special">);</span> |
| |
| <span class="comment">//Alias an integer node allocator type |
| </span> <span class="comment">//This allocator will allocate memory inside the static buffer |
| </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">wmanaged_external_buffer</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">></span> |
| <span class="identifier">allocator_t</span><span class="special">;</span> |
| |
| <span class="comment">//Alias a STL compatible list to be constructed in the static buffer |
| </span> <span class="keyword">typedef</span> <span class="identifier">list</span><span class="special"><</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">allocator_t</span><span class="special">></span> <span class="identifier">MyBufferList</span><span class="special">;</span> |
| |
| <span class="comment">//The list must be initialized with the allocator |
| </span> <span class="comment">//All objects created with objects_in_static_memory will |
| </span> <span class="comment">//be stored in the static_buffer! |
| </span> <span class="identifier">MyBufferList</span> <span class="special">*</span><span class="identifier">list</span> <span class="special">=</span> <span class="identifier">objects_in_static_memory</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="identifier">MyBufferList</span><span class="special">>(</span><span class="identifier">L</span><span class="string">"MyList"</span><span class="special">)</span> |
| <span class="special">(</span><span class="identifier">objects_in_static_memory</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| <span class="comment">//Since the allocation algorithm from wmanaged_external_buffer uses relative |
| </span> <span class="comment">//pointers and all the pointers constructed int the static memory point |
| </span> <span class="comment">//to objects in the same segment, we can create another static buffer |
| </span> <span class="comment">//from the first one and duplicate all the data. |
| </span> <span class="keyword">static</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">aligned_storage</span><span class="special"><</span><span class="identifier">memsize</span><span class="special">>::</span><span class="identifier">type</span> <span class="identifier">static_buffer2</span><span class="special">;</span> |
| <span class="identifier">std</span><span class="special">::</span><span class="identifier">memcpy</span><span class="special">(&</span><span class="identifier">static_buffer2</span><span class="special">,</span> <span class="special">&</span><span class="identifier">static_buffer</span><span class="special">,</span> <span class="identifier">memsize</span><span class="special">);</span> |
| |
| <span class="comment">//Now open the duplicated managed memory passing the memory as argument |
| </span> <span class="identifier">wmanaged_external_buffer</span> <span class="identifier">objects_in_static_memory2</span> |
| <span class="special">(</span><span class="identifier">open_only</span><span class="special">,</span> <span class="special">&</span><span class="identifier">static_buffer2</span><span class="special">,</span> <span class="identifier">memsize</span><span class="special">);</span> |
| |
| <span class="comment">//Check that "MyList" has been duplicated in the second buffer |
| </span> <span class="keyword">if</span><span class="special">(!</span><span class="identifier">objects_in_static_memory2</span><span class="special">.</span><span class="identifier">find</span><span class="special"><</span><span class="identifier">MyBufferList</span><span class="special">>(</span><span class="identifier">L</span><span class="string">"MyList"</span><span class="special">).</span><span class="identifier">first</span><span class="special">)</span> |
| <span class="keyword">return</span> <span class="number">1</span><span class="special">;</span> |
| |
| <span class="comment">//Destroy the lists from the static buffers |
| </span> <span class="identifier">objects_in_static_memory</span><span class="special">.</span><span class="identifier">destroy</span><span class="special"><</span><span class="identifier">MyBufferList</span><span class="special">>(</span><span class="identifier">L</span><span class="string">"MyList"</span><span class="special">);</span> |
| <span class="identifier">objects_in_static_memory2</span><span class="special">.</span><span class="identifier">destroy</span><span class="special"><</span><span class="identifier">MyBufferList</span><span class="special">>(</span><span class="identifier">L</span><span class="string">"MyList"</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> |
| <span class="bold"><strong>Boost.Interprocess</strong></span> STL compatible allocators can also be used to place STL |
| compatible containers in the user segment. |
| </p> |
| <p> |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/basic_managed_external__id818699.html" title="Class template basic_managed_external_buffer">basic_managed_external_buffer</a></code> can |
| be also useful to build small databases for embedded systems limiting the size of |
| the used memory to a predefined memory chunk, instead of letting the database |
| fragment the heap memory. |
| </p> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_heap_memory_external_buffer.managed_heap_memory"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_heap_memory_external_buffer.managed_heap_memory" title="Managed Heap Memory: Boost.Interprocess machinery in heap memory">Managed Heap Memory: Boost.Interprocess machinery in heap memory</a> |
| </h4></div></div></div> |
| <p> |
| The use of heap memory (new/delete) to obtain a buffer where the user wants to store all |
| his data is very common, so <span class="bold"><strong>Boost.Interprocess</strong></span> provides some specialized |
| classes that work exclusively with heap memory. |
| </p> |
| <p> |
| These are the classes: |
| </p> |
| <pre class="programlisting"><span class="comment">//Named object creation managed memory segment |
| </span><span class="comment">//All objects are constructed in a single buffer allocated via new[] |
| </span><span class="keyword">template</span> <span class="special"><</span> |
| <span class="keyword">class</span> <span class="identifier">CharType</span><span class="special">,</span> |
| <span class="keyword">class</span> <span class="identifier">MemoryAlgorithm</span><span class="special">,</span> |
| <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">IndexConfig</span><span class="special">></span> <span class="keyword">class</span> <span class="identifier">IndexType</span> |
| <span class="special">></span> |
| <span class="keyword">class</span> <span class="identifier">basic_managed_heap_memory</span><span class="special">;</span> |
| |
| <span class="comment">//Named object creation managed memory segment |
| </span><span class="comment">//All objects are constructed in a single buffer allocated via new[] |
| </span><span class="comment">// Names are c-strings, |
| </span><span class="comment">// Default memory management algorithm |
| </span><span class="comment">// (rbtree_best_fit with no mutexes and relative pointers) |
| </span><span class="comment">// Name-object mappings are stored in the default index type (flat_map) |
| </span><span class="keyword">typedef</span> <span class="identifier">basic_managed_heap_memory</span> <span class="special"><</span> |
| <span class="keyword">char</span><span class="special">,</span> |
| <span class="identifier">rbtree_best_fit</span><span class="special"><</span><span class="identifier">null_mutex_family</span><span class="special">>,</span> |
| <span class="identifier">flat_map_index</span> |
| <span class="special">></span> <span class="identifier">managed_heap_memory</span><span class="special">;</span> |
| |
| <span class="comment">//Named object creation managed memory segment |
| </span><span class="comment">//All objects are constructed in a single buffer allocated via new[] |
| </span><span class="comment">// Names are wide-strings, |
| </span><span class="comment">// Default memory management algorithm |
| </span><span class="comment">// (rbtree_best_fit with no mutexes and relative pointers) |
| </span><span class="comment">// Name-object mappings are stored in the default index type (flat_map) |
| </span><span class="keyword">typedef</span> <span class="identifier">basic_managed_heap_memory</span><span class="special"><</span> |
| <span class="keyword">wchar_t</span><span class="special">,</span> |
| <span class="identifier">rbtree_best_fit</span><span class="special"><</span><span class="identifier">null_mutex_family</span><span class="special">>,</span> |
| <span class="identifier">flat_map_index</span> |
| <span class="special">></span> <span class="identifier">wmanaged_heap_memory</span><span class="special">;</span> |
| </pre> |
| <p> |
| To use a managed heap memory, 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">managed_heap_memory</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> |
| </pre> |
| <p> |
| The use is exactly the same as |
| <code class="computeroutput"><a class="link" href="../boost/interprocess/basic_managed_external__id818699.html" title="Class template basic_managed_external_buffer">basic_managed_external_buffer</a></code>, |
| except that memory is created by |
| the managed memory segment itself using dynamic (new/delete) memory. |
| </p> |
| <p> |
| <span class="bold"><strong>basic_managed_heap_memory</strong></span> also offers a <code class="computeroutput"><span class="identifier">grow</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">extra_bytes</span><span class="special">)</span></code> function that |
| tries to resize internal heap memory so that we have room for more objects. |
| But <span class="bold"><strong>be careful</strong></span>, if memory is reallocated, the old buffer will be copied into |
| the new one so all the objects will be binary-copied to the new buffer. |
| To be able to use this function, all pointers constructed in the heap buffer that |
| point to objects in the heap buffer must be relative pointers (for example <code class="computeroutput"><span class="identifier">offset_ptr</span></code>). |
| Otherwise, the result is undefined. Here is 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">containers</span><span class="special">/</span><span class="identifier">list</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_heap_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">cstddef</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">typedef</span> <span class="identifier">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="keyword">int</span><span class="special">,</span> <span class="identifier">managed_heap_memory</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">></span> <span class="special">></span> |
| <span class="identifier">MyList</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">//We will create a buffer of 1000 bytes to store a list |
| </span> <span class="identifier">managed_heap_memory</span> <span class="identifier">heap_memory</span><span class="special">(</span><span class="number">1000</span><span class="special">);</span> |
| |
| <span class="identifier">MyList</span> <span class="special">*</span> <span class="identifier">mylist</span> <span class="special">=</span> <span class="identifier">heap_memory</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="identifier">MyList</span><span class="special">>(</span><span class="string">"MyList"</span><span class="special">)</span> |
| <span class="special">(</span><span class="identifier">heap_memory</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| |
| <span class="comment">//Obtain handle, that identifies the list in the buffer |
| </span> <span class="identifier">managed_heap_memory</span><span class="special">::</span><span class="identifier">handle_t</span> <span class="identifier">list_handle</span> <span class="special">=</span> <span class="identifier">heap_memory</span><span class="special">.</span><span class="identifier">get_handle_from_address</span><span class="special">(</span><span class="identifier">mylist</span><span class="special">);</span> |
| |
| <span class="comment">//Fill list until there is no more memory in the buffer |
| </span> <span class="keyword">try</span><span class="special">{</span> |
| <span class="keyword">while</span><span class="special">(</span><span class="number">1</span><span class="special">)</span> <span class="special">{</span> |
| <span class="identifier">mylist</span><span class="special">-></span><span class="identifier">insert</span><span class="special">(</span><span class="identifier">mylist</span><span class="special">-></span><span class="identifier">begin</span><span class="special">(),</span> <span class="number">0</span><span class="special">);</span> |
| <span class="special">}</span> |
| <span class="special">}</span> |
| <span class="keyword">catch</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">bad_alloc</span> <span class="special">&){</span> |
| <span class="comment">//memory is full |
| </span> <span class="special">}</span> |
| <span class="comment">//Let's obtain the size of the list |
| </span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">old_size</span> <span class="special">=</span> <span class="identifier">mylist</span><span class="special">-></span><span class="identifier">size</span><span class="special">();</span> |
| |
| <span class="comment">//To make the list bigger, let's increase the heap buffer |
| </span> <span class="comment">//in 1000 bytes more. |
| </span> <span class="identifier">heap_memory</span><span class="special">.</span><span class="identifier">grow</span><span class="special">(</span><span class="number">1000</span><span class="special">);</span> |
| |
| <span class="comment">//If memory has been reallocated, the old pointer is invalid, so |
| </span> <span class="comment">//use previously obtained handle to find the new pointer. |
| </span> <span class="identifier">mylist</span> <span class="special">=</span> <span class="keyword">static_cast</span><span class="special"><</span><span class="identifier">MyList</span> <span class="special">*></span> |
| <span class="special">(</span><span class="identifier">heap_memory</span><span class="special">.</span><span class="identifier">get_address_from_handle</span><span class="special">(</span><span class="identifier">list_handle</span><span class="special">));</span> |
| |
| <span class="comment">//Fill list until there is no more memory in the buffer |
| </span> <span class="keyword">try</span><span class="special">{</span> |
| <span class="keyword">while</span><span class="special">(</span><span class="number">1</span><span class="special">)</span> <span class="special">{</span> |
| <span class="identifier">mylist</span><span class="special">-></span><span class="identifier">insert</span><span class="special">(</span><span class="identifier">mylist</span><span class="special">-></span><span class="identifier">begin</span><span class="special">(),</span> <span class="number">0</span><span class="special">);</span> |
| <span class="special">}</span> |
| <span class="special">}</span> |
| <span class="keyword">catch</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">bad_alloc</span> <span class="special">&){</span> |
| <span class="comment">//memory is full |
| </span> <span class="special">}</span> |
| |
| <span class="comment">//Let's obtain the new size of the list |
| </span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">new_size</span> <span class="special">=</span> <span class="identifier">mylist</span><span class="special">-></span><span class="identifier">size</span><span class="special">();</span> |
| |
| <span class="identifier">assert</span><span class="special">(</span><span class="identifier">new_size</span> <span class="special">></span> <span class="identifier">old_size</span><span class="special">);</span> |
| |
| <span class="comment">//Destroy list |
| </span> <span class="identifier">heap_memory</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">mylist</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.managed_memory_segments.managed_heap_memory_external_buffer.managed_heap_memory_external_buffer_diff"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_heap_memory_external_buffer.managed_heap_memory_external_buffer_diff" title="Differences between managed memory segments">Differences between managed memory segments</a> |
| </h4></div></div></div> |
| <p> |
| All managed memory segments have similar capabilities |
| (memory allocation inside the memory segment, named object construction...), |
| but there are some remarkable differences between <span class="bold"><strong>managed_shared_memory</strong></span>, |
| <span class="bold"><strong>managed_mapped_file</strong></span> and <span class="bold"><strong>managed_heap_memory</strong></span>, <span class="bold"><strong>managed_external_file</strong></span>. |
| </p> |
| <div class="itemizedlist"><ul class="itemizedlist" type="disc"> |
| <li class="listitem"> |
| Default specializations of managed shared memory and mapped file use process-shared |
| mutexes. Heap memory and external buffer have no internal synchronization by default. |
| The cause is that the first two are thought to be shared between processes (although |
| memory mapped files could be used just to obtain a persistent object data-base for a |
| process) whereas the last two are thought to be used inside one process to construct |
| a serialized named object data-base that can be sent though serial interprocess |
| communications (like message queues, localhost network...). |
| |
| </li> |
| <li class="listitem"> |
| The first two create a system-global object (a shared memory object or a file) shared |
| by several processes, whereas the last two are objects that don't create system-wide |
| resources. |
| |
| </li> |
| </ul></div> |
| </div> |
| <div class="section"> |
| <div class="titlepage"><div><div><h4 class="title"> |
| <a name="interprocess.managed_memory_segments.managed_heap_memory_external_buffer.shared_message_queue_ex"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_heap_memory_external_buffer.shared_message_queue_ex" title="Example: Serializing a database through the message queue">Example: Serializing a database through the message queue</a> |
| </h4></div></div></div> |
| <p> |
| To see the utility of managed heap memory and managed external buffer classes, |
| the following example shows how a message queue can be used to serialize a whole |
| database constructed in a memory buffer using <span class="bold"><strong>Boost.Interprocess</strong></span>, send the database |
| through a message queue and duplicated in another buffer: |
| </p> |
| <p> |
| |
| </p> |
| <pre class="programlisting"><span class="comment">//This test creates a in memory data-base using Interprocess machinery and |
| </span><span class="comment">//serializes it through a message queue. Then rebuilds the data-base in |
| </span><span class="comment">//another buffer and checks it against the original data-base |
| </span><span class="keyword">bool</span> <span class="identifier">test_serialize_db</span><span class="special">()</span> |
| <span class="special">{</span> |
| <span class="comment">//Typedef data to create a Interprocess map |
| </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">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">></span> <span class="identifier">MyPair</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">less</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">></span> <span class="identifier">MyLess</span><span class="special">;</span> |
| <span class="keyword">typedef</span> <span class="identifier">node_allocator</span><span class="special"><</span><span class="identifier">MyPair</span><span class="special">,</span> <span class="identifier">managed_external_buffer</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="keyword">typedef</span> <span class="identifier">map</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">,</span> |
| <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</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">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">>,</span> |
| <span class="identifier">node_allocator_t</span><span class="special">></span> |
| <span class="identifier">MyMap</span><span class="special">;</span> |
| |
| <span class="comment">//Some constants |
| </span> <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">BufferSize</span> <span class="special">=</span> <span class="number">65536</span><span class="special">;</span> |
| <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">MaxMsgSize</span> <span class="special">=</span> <span class="number">100</span><span class="special">;</span> |
| |
| <span class="comment">//Allocate a memory buffer to hold the destiny database using vector<char> |
| </span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">char</span><span class="special">></span> <span class="identifier">buffer_destiny</span><span class="special">(</span><span class="identifier">BufferSize</span><span class="special">,</span> <span class="number">0</span><span class="special">);</span> |
| |
| <span class="identifier">message_queue</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="identifier">test</span><span class="special">::</span><span class="identifier">get_process_id_name</span><span class="special">());</span> |
| <span class="special">{</span> |
| <span class="comment">//Create the message-queues |
| </span> <span class="identifier">message_queue</span> <span class="identifier">mq1</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> <span class="identifier">test</span><span class="special">::</span><span class="identifier">get_process_id_name</span><span class="special">(),</span> <span class="number">1</span><span class="special">,</span> <span class="identifier">MaxMsgSize</span><span class="special">);</span> |
| |
| <span class="comment">//Open previously created message-queue simulating other process |
| </span> <span class="identifier">message_queue</span> <span class="identifier">mq2</span><span class="special">(</span><span class="identifier">open_only</span><span class="special">,</span> <span class="identifier">test</span><span class="special">::</span><span class="identifier">get_process_id_name</span><span class="special">());</span> |
| |
| <span class="comment">//A managed heap memory to create the origin database |
| </span> <span class="identifier">managed_heap_memory</span> <span class="identifier">db_origin</span><span class="special">(</span><span class="identifier">buffer_destiny</span><span class="special">.</span><span class="identifier">size</span><span class="special">());</span> |
| |
| <span class="comment">//Construct the map in the first buffer |
| </span> <span class="identifier">MyMap</span> <span class="special">*</span><span class="identifier">map1</span> <span class="special">=</span> <span class="identifier">db_origin</span><span class="special">.</span><span class="identifier">construct</span><span class="special"><</span><span class="identifier">MyMap</span><span class="special">>(</span><span class="string">"MyMap"</span><span class="special">)</span> |
| <span class="special">(</span><span class="identifier">MyLess</span><span class="special">(),</span> |
| <span class="identifier">db_origin</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span> |
| <span class="keyword">if</span><span class="special">(!</span><span class="identifier">map1</span><span class="special">)</span> |
| <span class="keyword">return</span> <span class="keyword">false</span><span class="special">;</span> |
| |
| <span class="comment">//Fill map1 until is full |
| </span> <span class="keyword">try</span><span class="special">{</span> |
| <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> |
| <span class="keyword">while</span><span class="special">(</span><span class="number">1</span><span class="special">){</span> |
| <span class="special">(*</span><span class="identifier">map1</span><span class="special">)[</span><span class="identifier">i</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">i</span><span class="special">;</span> |
| <span class="special">++</span><span class="identifier">i</span><span class="special">;</span> |
| <span class="special">}</span> |
| <span class="special">}</span> |
| <span class="keyword">catch</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">bad_alloc</span> <span class="special">&){}</span> |
| |
| <span class="comment">//Data control data sending through the message queue |
| </span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">sent</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> |
| <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">recvd</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> |
| <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">total_recvd</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> |
| <span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">priority</span><span class="special">;</span> |
| |
| <span class="comment">//Send whole first buffer through the mq1, read it |
| </span> <span class="comment">//through mq2 to the second buffer |
| </span> <span class="keyword">while</span><span class="special">(</span><span class="number">1</span><span class="special">){</span> |
| <span class="comment">//Send a fragment of buffer1 through mq1 |
| </span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">bytes_to_send</span> <span class="special">=</span> <span class="identifier">MaxMsgSize</span> <span class="special"><</span> <span class="special">(</span><span class="identifier">db_origin</span><span class="special">.</span><span class="identifier">get_size</span><span class="special">()</span> <span class="special">-</span> <span class="identifier">sent</span><span class="special">)</span> <span class="special">?</span> |
| <span class="identifier">MaxMsgSize</span> <span class="special">:</span> <span class="special">(</span><span class="identifier">db_origin</span><span class="special">.</span><span class="identifier">get_size</span><span class="special">()</span> <span class="special">-</span> <span class="identifier">sent</span><span class="special">);</span> |
| <span class="identifier">mq1</span><span class="special">.</span><span class="identifier">send</span><span class="special">(</span> <span class="special">&</span><span class="keyword">static_cast</span><span class="special"><</span><span class="keyword">char</span><span class="special">*>(</span><span class="identifier">db_origin</span><span class="special">.</span><span class="identifier">get_address</span><span class="special">())[</span><span class="identifier">sent</span><span class="special">]</span> |
| <span class="special">,</span> <span class="identifier">bytes_to_send</span> |
| <span class="special">,</span> <span class="number">0</span><span class="special">);</span> |
| <span class="identifier">sent</span> <span class="special">+=</span> <span class="identifier">bytes_to_send</span><span class="special">;</span> |
| <span class="comment">//Receive the fragment through mq2 to buffer_destiny |
| </span> <span class="identifier">mq2</span><span class="special">.</span><span class="identifier">receive</span><span class="special">(</span> <span class="special">&</span><span class="identifier">buffer_destiny</span><span class="special">[</span><span class="identifier">total_recvd</span><span class="special">]</span> |
| <span class="special">,</span> <span class="identifier">BufferSize</span> <span class="special">-</span> <span class="identifier">recvd</span> |
| <span class="special">,</span> <span class="identifier">recvd</span> |
| <span class="special">,</span> <span class="identifier">priority</span><span class="special">);</span> |
| <span class="identifier">total_recvd</span> <span class="special">+=</span> <span class="identifier">recvd</span><span class="special">;</span> |
| |
| <span class="comment">//Check if we have received all the buffer |
| </span> <span class="keyword">if</span><span class="special">(</span><span class="identifier">total_recvd</span> <span class="special">==</span> <span class="identifier">BufferSize</span><span class="special">){</span> |
| <span class="keyword">break</span><span class="special">;</span> |
| <span class="special">}</span> |
| <span class="special">}</span> |
| |
| <span class="comment">//The buffer will contain a copy of the original database |
| </span> <span class="comment">//so let's interpret the buffer with managed_external_buffer |
| </span> <span class="identifier">managed_external_buffer</span> <span class="identifier">db_destiny</span><span class="special">(</span><span class="identifier">open_only</span><span class="special">,</span> <span class="special">&</span><span class="identifier">buffer_destiny</span><span class="special">[</span><span class="number">0</span><span class="special">],</span> <span class="identifier">BufferSize</span><span class="special">);</span> |
| |
| <span class="comment">//Let's find the map |
| </span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special"><</span><span class="identifier">MyMap</span> <span class="special">*,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">></span> <span class="identifier">ret</span> <span class="special">=</span> <span class="identifier">db_destiny</span><span class="special">.</span><span class="identifier">find</span><span class="special"><</span><span class="identifier">MyMap</span><span class="special">>(</span><span class="string">"MyMap"</span><span class="special">);</span> |
| <span class="identifier">MyMap</span> <span class="special">*</span><span class="identifier">map2</span> <span class="special">=</span> <span class="identifier">ret</span><span class="special">.</span><span class="identifier">first</span><span class="special">;</span> |
| |
| <span class="comment">//Check if we have found it |
| </span> <span class="keyword">if</span><span class="special">(!</span><span class="identifier">map2</span><span class="special">){</span> |
| <span class="keyword">return</span> <span class="keyword">false</span><span class="special">;</span> |
| <span class="special">}</span> |
| |
| <span class="comment">//Check if it is a single variable (not an array) |
| </span> <span class="keyword">if</span><span class="special">(</span><span class="identifier">ret</span><span class="special">.</span><span class="identifier">second</span> <span class="special">!=</span> <span class="number">1</span><span class="special">){</span> |
| <span class="keyword">return</span> <span class="keyword">false</span><span class="special">;</span> |
| <span class="special">}</span> |
| |
| <span class="comment">//Now let's compare size |
| </span> <span class="keyword">if</span><span class="special">(</span><span class="identifier">map1</span><span class="special">-></span><span class="identifier">size</span><span class="special">()</span> <span class="special">!=</span> <span class="identifier">map2</span><span class="special">-></span><span class="identifier">size</span><span class="special">()){</span> |
| <span class="keyword">return</span> <span class="keyword">false</span><span class="special">;</span> |
| <span class="special">}</span> |
| |
| <span class="comment">//Now let's compare all db values |
| </span> <span class="keyword">for</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="identifier">num_elements</span> <span class="special">=</span> <span class="identifier">map1</span><span class="special">-></span><span class="identifier">size</span><span class="special">();</span> <span class="identifier">i</span> <span class="special"><</span> <span class="identifier">num_elements</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span> |
| <span class="keyword">if</span><span class="special">((*</span><span class="identifier">map1</span><span class="special">)[</span><span class="identifier">i</span><span class="special">]</span> <span class="special">!=</span> <span class="special">(*</span><span class="identifier">map2</span><span class="special">)[</span><span class="identifier">i</span><span class="special">]){</span> |
| <span class="keyword">return</span> <span class="keyword">false</span><span class="special">;</span> |
| <span class="special">}</span> |
| <span class="special">}</span> |
| |
| <span class="comment">//Destroy maps from db-s |
| </span> <span class="identifier">db_origin</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">map1</span><span class="special">);</span> |
| <span class="identifier">db_destiny</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">map2</span><span class="special">);</span> |
| <span class="special">}</span> |
| <span class="identifier">message_queue</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="identifier">test</span><span class="special">::</span><span class="identifier">get_process_id_name</span><span class="special">());</span> |
| <span class="keyword">return</span> <span class="keyword">true</span><span class="special">;</span> |
| <span class="special">}</span> |
| </pre> |
| <p> |
| </p> |
| </div> |
| </div> |
| </div> |
| <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> |
| <td align="left"></td> |
| <td align="right"><div class="copyright-footer">Copyright © 2005 - 2010 Ion Gaztanaga<p> |
| Distributed under the Boost Software License, Version 1.0. (See accompanying |
| file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) |
| </p> |
| </div></td> |
| </tr></table> |
| <hr> |
| <div class="spirit-nav"> |
| <a accesskey="p" href="synchronization_mechanisms.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="allocators_containers.html"><img src="../../../doc/src/images/next.png" alt="Next"></a> |
| </div> |
| </body> |
| </html> |