2498 lines
251 KiB
HTML
2498 lines
251 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||
<html>
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
<title>Managed Memory Segments</title>
|
||
<link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css">
|
||
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
|
||
<link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset">
|
||
<link rel="up" href="../interprocess.html" title="Chapter 18. 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 class="toc">
|
||
<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 class="toc">
|
||
<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" style="list-style-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" style="list-style-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" style="list-style-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">
|
||
<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:
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-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 class="toc">
|
||
<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>
|
||
<dt><span class="section"><a href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_shared_memory.xsi_managed_memory_common_shm">Using
|
||
XSI (system V) 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" style="list-style-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" style="list-style-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" (size is ignored).</span>
|
||
<span class="comment">//2. Otherwise, equivalent to "create_only"</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>
|
||
managed memory. This is achieved through the <code class="computeroutput"><a class="link" href="../boost/interprocess/basic_ma_idm45189372627568.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_ma_idm45189372715616.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 <a class="link" href="sharedmemorybetweenprocesses.html#interprocess.sharedmemorybetweenprocesses.sharedmemory.windows_shared_memory" title="Native windows shared memory">Native
|
||
windows shared memory</a>.
|
||
</p>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.managed_memory_segments.managed_shared_memory.xsi_managed_memory_common_shm"></a><a class="link" href="managed_memory_segments.html#interprocess.managed_memory_segments.managed_shared_memory.xsi_managed_memory_common_shm" title="Using XSI (system V) shared memory">Using
|
||
XSI (system V) shared memory</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
Unix users might also want to use XSI (system V) 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>
|
||
managed memory. This is achieved through the <code class="computeroutput"><a class="link" href="../boost/interprocess/basic_ma_idm45189372561968.html" title="Class template basic_managed_xsi_shared_memory">basic_managed_xsi_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_xsi_shared_memory</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
<p>
|
||
This class has nearly the same interface as <code class="computeroutput"><a class="link" href="../boost/interprocess/basic_ma_idm45189372715616.html" title="Class template basic_managed_shared_memory">basic_managed_shared_memory</a></code>
|
||
but uses XSI shared memory as backend.
|
||
</p>
|
||
</div>
|
||
<p>
|
||
For more information about managed XSI shared memory capabilities, see <code class="computeroutput"><a class="link" href="../boost/interprocess/basic_ma_idm45189372561968.html" title="Class template basic_managed_xsi_shared_memory">basic_managed_xsi_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 class="toc">
|
||
<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" style="list-style-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" style="list-style-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="comment">//Mapped file name</span>
|
||
<span class="special">,</span> <span class="number">65536</span><span class="special">);</span> <span class="comment">//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</span>
|
||
</pre>
|
||
<pre class="programlisting"><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="comment">//Mapped file name</span>
|
||
<span class="special">,</span> <span class="number">65536</span><span class="special">);</span> <span class="comment">//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 class="toc">
|
||
<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/interpro_idm45189371318128.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" style="list-style-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" style="list-style-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">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">unique_object</span><span class="special">),</span> <span class="keyword">typeid</span><span class="special">(</span><span class="identifier">my_class</span><span class="special">).</span><span class="identifier">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">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 class="toc">
|
||
<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/managed_shared_memory.html" title="Type definition 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/managed_mapped_file.html" title="Type definition 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>
|
||
<div class="caution"><table border="0" summary="Caution">
|
||
<tr>
|
||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Caution]" src="../../../doc/src/images/caution.png"></td>
|
||
<th align="left">Caution</th>
|
||
</tr>
|
||
<tr><td align="left" valign="top"><p>
|
||
This feature is experimental, interface and ABI are unstable
|
||
</p></td></tr>
|
||
</table></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" style="list-style-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" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
Allocation of N buffers of memory with the same size.
|
||
</li>
|
||
<li class="listitem">
|
||
Allocation of N buffers of memory, each one of different size.
|
||
</li>
|
||
</ul></div>
|
||
<pre class="programlisting"><span class="comment">//!Allocates n_elements of elem_bytes bytes.</span>
|
||
<span class="comment">//!Throws bad_alloc on failure. chain.size() is not increased on failure.</span>
|
||
<span class="keyword">void</span> <span class="identifier">allocate_many</span><span class="special">(</span><span class="identifier">size_type</span> <span class="identifier">elem_bytes</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">n_elements</span><span class="special">,</span> <span class="identifier">multiallocation_chain</span> <span class="special">&</span><span class="identifier">chain</span><span class="special">);</span>
|
||
|
||
<span class="comment">//!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes.</span>
|
||
<span class="comment">//!Throws bad_alloc on failure. chain.size() is not increased on failure.</span>
|
||
<span class="keyword">void</span> <span class="identifier">allocate_many</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">size_type</span> <span class="special">*</span><span class="identifier">element_lengths</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">n_elements</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">sizeof_element</span><span class="special">,</span> <span class="identifier">multiallocation_chain</span> <span class="special">&</span><span class="identifier">chain</span><span class="special">);</span>
|
||
|
||
<span class="comment">//!Allocates n_elements of elem_bytes bytes.</span>
|
||
<span class="comment">//!Non-throwing version. chain.size() is not increased on failure.</span>
|
||
<span class="keyword">void</span> <span class="identifier">allocate_many</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">nothrow_t</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">elem_bytes</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">n_elements</span><span class="special">,</span> <span class="identifier">multiallocation_chain</span> <span class="special">&</span><span class="identifier">chain</span><span class="special">);</span>
|
||
|
||
<span class="comment">//!Allocates n_elements, each one of</span>
|
||
<span class="comment">//!element_lengths[i]*sizeof_element bytes.</span>
|
||
<span class="comment">//!Non-throwing version. chain.size() is not increased on failure.</span>
|
||
<span class="keyword">void</span> <span class="identifier">allocate_many</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">nothrow_t</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">size_type</span> <span class="special">*</span><span class="identifier">elem_sizes</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">n_elements</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">sizeof_element</span><span class="special">,</span> <span class="identifier">multiallocation_chain</span> <span class="special">&</span><span class="identifier">chain</span><span class="special">);</span>
|
||
|
||
<span class="comment">//!Deallocates all elements contained in chain.</span>
|
||
<span class="comment">//!Never throws.</span>
|
||
<span class="keyword">void</span> <span class="identifier">deallocate_many</span><span class="special">(</span><span class="identifier">multiallocation_chain</span> <span class="special">&</span><span class="identifier">chain</span><span class="special">);</span>
|
||
</pre>
|
||
<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">move</span><span class="special">/</span><span class="identifier">utility_core</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span> <span class="comment">//boost::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="identifier">std</span><span class="special">::</span><span class="identifier">nothrow</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">chain</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">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">managed_shared_memory</span><span class="special">::</span><span class="identifier">size_type</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">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="number">1</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">deallocate_many</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" style="list-style-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">size_type</span> <span class="special">&</span><span class="identifier">prefer_in_recvd_out_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>
|
||
</pre>
|
||
<p>
|
||
<span class="bold"><strong>Preconditions for the function</strong></span>:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-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" style="list-style-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" style="list-style-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" style="list-style-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" style="list-style-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">managed_shared_memory</span><span class="special">::</span><span class="identifier">size_type</span> <span class="identifier">min_size</span> <span class="special">=</span> <span class="number">100</span><span class="special">;</span>
|
||
<span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">size_type</span> <span class="identifier">first_received_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">hint</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="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">first_received_size</span><span class="special">,</span> <span class="identifier">hint</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">first_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">managed_shared_memory</span><span class="special">::</span><span class="identifier">size_type</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">first_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">min_size</span> <span class="special">=</span> <span class="identifier">first_received_size</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">size_type</span> <span class="identifier">expanded_size</span> <span class="special">=</span> <span class="identifier">first_received_size</span><span class="special">*</span><span class="number">3</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_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">min_size</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">ptr</span> <span class="special">!=</span> <span class="number">0</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">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">first_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">managed_shared_memory</span><span class="special">::</span><span class="identifier">size_type</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">first_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">managed_shared_memory</span><span class="special">::</span><span class="identifier">size_type</span> <span class="identifier">shrunk_size</span> <span class="special">=</span> <span class="identifier">min_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">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">ptr</span> <span class="special">!=</span> <span class="number">0</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">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">managed_shared_memory</span><span class="special">::</span><span class="identifier">size_type</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" style="list-style-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">//Define file names</span>
|
||
<span class="keyword">const</span> <span class="keyword">char</span> <span class="special">*</span><span class="identifier">ManagedFile</span> <span class="special">=</span> <span class="string">"MyManagedFile"</span><span class="special">;</span>
|
||
<span class="keyword">const</span> <span class="keyword">char</span> <span class="special">*</span><span class="identifier">ManagedFile2</span> <span class="special">=</span> <span class="string">"MyManagedFile2"</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="identifier">ManagedFile</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="identifier">ManagedFile2</span><span class="special">);</span>
|
||
<span class="identifier">remove_file_on_destroy</span> <span class="identifier">destroyer1</span><span class="special">(</span><span class="identifier">ManagedFile</span><span class="special">);</span>
|
||
<span class="identifier">remove_file_on_destroy</span> <span class="identifier">destroyer2</span><span class="special">(</span><span class="identifier">ManagedFile2</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="identifier">ManagedFile</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="identifier">ManagedFile</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="identifier">ManagedFile2</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="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">streamsize</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="identifier">ManagedFile2</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="identifier">ManagedFile</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 class="toc">
|
||
<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" style="list-style-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">
|
||
Build complex, easily serializable databases in a single buffer:
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-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_ma_idm45189372857664.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_ma_idm45189372857664.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">MyList</span><span class="special">::</span><span class="identifier">size_type</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">MyList</span><span class="special">::</span><span class="identifier">size_type</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" style="list-style-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">message_queue</span><span class="special">::</span><span class="identifier">size_type</span> <span class="identifier">recvd</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">size_type</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">managed_external_buffer</span><span class="special">::</span><span class="identifier">size_type</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="identifier">MyMap</span><span class="special">::</span><span class="identifier">size_type</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="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">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-2015 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>
|