[DEV] add v1.76.0

This commit is contained in:
2021-10-05 21:37:46 +02:00
parent a97e9ae7d4
commit d0115b733d
45133 changed files with 4744437 additions and 1026325 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -0,0 +1,488 @@
<!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>Customizing Boost.Interprocess</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="architecture.html" title="Architecture and internals">
<link rel="next" href="acknowledgements_notes.html" title="Acknowledgements, notes and links">
</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="architecture.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="acknowledgements_notes.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.customizing_interprocess"></a><a class="link" href="customizing_interprocess.html" title="Customizing Boost.Interprocess">Customizing Boost.Interprocess</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="customizing_interprocess.html#interprocess.customizing_interprocess.custom_interprocess_alloc">Writing
a new shared memory allocation algorithm</a></span></dt>
<dt><span class="section"><a href="customizing_interprocess.html#interprocess.customizing_interprocess.custom_allocators">Building
custom STL compatible allocators for Boost.Interprocess</a></span></dt>
<dt><span class="section"><a href="customizing_interprocess.html#interprocess.customizing_interprocess.custom_indexes">Building
custom indexes</a></span></dt>
</dl></div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.customizing_interprocess.custom_interprocess_alloc"></a><a class="link" href="customizing_interprocess.html#interprocess.customizing_interprocess.custom_interprocess_alloc" title="Writing a new shared memory allocation algorithm">Writing
a new shared memory allocation algorithm</a>
</h3></div></div></div>
<p>
If the default algorithm does not satisfy user requirements, it's easy to
provide different algorithms like bitmapping or more advanced segregated
lists to meet requirements. The class implementing the algorithm must be
compatible with shared memory, so it shouldn't have any virtual function
or virtual inheritance or any indirect base class with virtual function or
inheritance.
</p>
<p>
This is the interface to be implemented:
</p>
<pre class="programlisting"><span class="keyword">class</span> <span class="identifier">my_algorithm</span>
<span class="special">{</span>
<span class="keyword">public</span><span class="special">:</span>
<span class="comment">//!The mutex type to be used by the rest of Interprocess framework</span>
<span class="keyword">typedef</span> <span class="identifier">implementation_defined</span> <span class="identifier">mutex_family</span><span class="special">;</span>
<span class="comment">//!The pointer type to be used by the rest of Interprocess framework</span>
<span class="keyword">typedef</span> <span class="identifier">implementation_defined</span> <span class="identifier">void_pointer</span><span class="special">;</span>
<span class="comment">//!Constructor. "size" is the total size of the managed memory segment,</span>
<span class="comment">//!"extra_hdr_bytes" indicates the extra bytes after the sizeof(my_algorithm)</span>
<span class="comment">//!that the allocator should not use at all.</span>
<span class="identifier">my_algorithm</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">size</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">extra_hdr_bytes</span><span class="special">);</span>
<span class="comment">//!Obtains the minimum size needed by the algorithm</span>
<span class="keyword">static</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">get_min_size</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">extra_hdr_bytes</span><span class="special">);</span>
<span class="comment">//!Allocates bytes, returns 0 if there is not more memory</span>
<span class="keyword">void</span><span class="special">*</span> <span class="identifier">allocate</span> <span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">nbytes</span><span class="special">);</span>
<span class="comment">//!Deallocates previously allocated bytes</span>
<span class="keyword">void</span> <span class="identifier">deallocate</span> <span class="special">(</span><span class="keyword">void</span> <span class="special">*</span><span class="identifier">adr</span><span class="special">);</span>
<span class="comment">//!Returns the size of the memory segment</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">get_size</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
<span class="comment">//!Increases managed memory in extra_size bytes more</span>
<span class="keyword">void</span> <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_size</span><span class="special">);</span>
<span class="comment">/*...*/</span>
<span class="special">};</span>
</pre>
<p>
Let's see the public typedefs to define:
</p>
<pre class="programlisting"><span class="keyword">typedef</span> <span class="comment">/* . . . */</span> <span class="identifier">void_pointer</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="comment">/* . . . */</span> <span class="identifier">mutex_family</span><span class="special">;</span>
</pre>
<p>
The <code class="computeroutput"><span class="identifier">void_pointer</span></code> typedef
specifies the pointer type to be used in the <span class="bold"><strong>Boost.Interprocess</strong></span>
framework that uses the algorithm. For example, if we define
</p>
<pre class="programlisting"><span class="keyword">typedef</span> <span class="keyword">void</span> <span class="special">*</span> <span class="identifier">void_pointer</span><span class="special">;</span>
</pre>
<p>
all <span class="bold"><strong>Boost.Interprocess</strong></span> framework using this
algorithm will use raw pointers as members. But if we define:
</p>
<pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">offset_ptr</span><span class="special">&lt;</span><span class="keyword">void</span><span class="special">&gt;</span> <span class="identifier">void_pointer</span><span class="special">;</span>
</pre>
<p>
then all <span class="bold"><strong>Boost.Interprocess</strong></span> framework will
use relative pointers.
</p>
<p>
The <code class="computeroutput"><span class="identifier">mutex_family</span></code> is a structure
containing typedefs for different interprocess_mutex types to be used in
the <span class="bold"><strong>Boost.Interprocess</strong></span> framework. For example
the defined
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">mutex_family</span>
<span class="special">{</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">interprocess_mutex</span> <span class="identifier">mutex_type</span><span class="special">;</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">interprocess_recursive_mutex</span> <span class="identifier">recursive_mutex_type</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p>
defines all interprocess_mutex types using boost::interprocess interprocess_mutex
types. The user can specify the desired mutex family.
</p>
<pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">mutex_family</span> <span class="identifier">mutex_family</span><span class="special">;</span>
</pre>
<p>
The new algorithm (let's call it <span class="bold"><strong>my_algorithm</strong></span>)
must implement all the functions that boost::interprocess::rbtree_best_fit
class offers:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>my_algorithm</strong></span>'s constructor must take
2 arguments:
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; ">
<li class="listitem">
<span class="bold"><strong>size</strong></span> indicates the total size
of the managed memory segment, and <span class="bold"><strong>my_algorithm</strong></span>
object will be always constructed a at offset 0 of the memory segment.
</li>
<li class="listitem">
The <span class="bold"><strong>extra_hdr_bytes</strong></span> parameter
indicates the number of bytes after the offset <code class="computeroutput"><span class="keyword">sizeof</span><span class="special">(</span><span class="identifier">my_algorithm</span><span class="special">)</span></code> that <span class="bold"><strong>my_algorithm</strong></span>
can't use at all. This extra bytes will be used to store additional
data that should not be overwritten. So, <span class="bold"><strong>my_algorithm</strong></span>
will be placed at address XXX of the memory segment, and will manage
the <span class="bold"><strong>[XXX + sizeof(my_algorithm) + extra_hdr_bytes,
XXX + size)</strong></span> range of the segment.
</li>
</ul></div>
</li>
<li class="listitem">
The <span class="bold"><strong>get_min_size()</strong></span> function should return
the minimum space the algorithm needs to be valid with the passed <span class="bold"><strong>extra_hdr_bytes</strong></span> parameter. This function will
be used to check if the memory segment is big enough to place the algorithm
there.
</li>
<li class="listitem">
The <span class="bold"><strong>allocate()</strong></span> function must return
0 if there is no more available memory. The memory returned by <span class="bold"><strong>my_algorithm</strong></span> must be aligned to the most restrictive
memory alignment of the system. This function should be executed with
the synchronization capabilities offered by <code class="computeroutput"><span class="keyword">typename</span>
<span class="identifier">mutex_family</span><span class="special">::</span><span class="identifier">mutex_type</span></code> interprocess_mutex. That
means, that if we define <code class="computeroutput"><span class="keyword">typedef</span>
<span class="identifier">mutex_family</span> <span class="identifier">mutex_family</span><span class="special">;</span></code> then this function should offer the
same synchronization as if it was surrounded by an interprocess_mutex
lock/unlock. Normally, this is implemented using a member of type <code class="computeroutput"><span class="identifier">mutex_family</span><span class="special">::</span><span class="identifier">mutex_type</span></code>, but it could be done using
atomic instructions or lock free algorithms.
</li>
<li class="listitem">
The <span class="bold"><strong>deallocate()</strong></span> function must make
the returned buffer available for new allocations. This function should
offer the same synchronization as <code class="computeroutput"><span class="identifier">allocate</span><span class="special">()</span></code>.
</li>
<li class="listitem">
The <span class="bold"><strong>size()</strong></span> function will return the
passed <span class="bold"><strong>size</strong></span> parameter in the constructor.
So, <span class="bold"><strong>my_algorithm</strong></span> should store the size
internally.
</li>
<li class="listitem">
The <span class="bold"><strong>grow()</strong></span> function will expand the
managed memory by <span class="bold"><strong>my_algorithm</strong></span> in <span class="bold"><strong>extra_size</strong></span> bytes. So <span class="bold"><strong>size()</strong></span>
function should return the updated size, and the new managed memory range
will be (if the address where the algorithm is constructed is XXX):
<span class="bold"><strong>[XXX + sizeof(my_algorithm) + extra_hdr_bytes,
XXX + old_size + extra_size)</strong></span>. This function should offer the
same synchronization as <code class="computeroutput"><span class="identifier">allocate</span><span class="special">()</span></code>.
</li>
</ul></div>
<p>
That's it. Now we can create new managed shared memory that uses our new
algorithm:
</p>
<pre class="programlisting"><span class="comment">//Managed memory segment to allocate named (c-string) objects</span>
<span class="comment">//using a user-defined memory allocation algorithm</span>
<span class="identifier">basic_managed_shared_memory</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">,</span>
<span class="special">,</span><span class="identifier">my_algorithm</span>
<span class="special">,</span><span class="identifier">flat_map_index</span><span class="special">&gt;</span>
<span class="identifier">my_managed_shared_memory</span><span class="special">;</span>
</pre>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.customizing_interprocess.custom_allocators"></a><a class="link" href="customizing_interprocess.html#interprocess.customizing_interprocess.custom_allocators" title="Building custom STL compatible allocators for Boost.Interprocess">Building
custom STL compatible allocators for Boost.Interprocess</a>
</h3></div></div></div>
<p>
If provided STL-like allocators don't satisfy user needs, the user can implement
another STL compatible allocator using raw memory allocation and named object
construction functions. The user can this way implement more suitable allocation
schemes on top of basic shared memory allocation schemes, just like more
complex allocators are built on top of new/delete functions.
</p>
<p>
When using a managed memory segment, <span class="bold"><strong>get_segment_manager()</strong></span>
function returns a pointer to the segment manager. With this pointer, the
raw memory allocation and named object construction functions can be called
directly:
</p>
<pre class="programlisting"><span class="comment">//Create the managed shared memory and initialize resources</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">//segment name</span>
<span class="special">,</span><span class="number">65536</span><span class="special">);</span> <span class="comment">//segment size in bytes</span>
<span class="comment">//Obtain the segment manager</span>
<span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span> <span class="special">*</span><span class="identifier">segment_mngr</span>
<span class="special">=</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">();</span>
<span class="comment">//With the segment manager, now we have access to all allocation functions</span>
<span class="identifier">segment_mngr</span><span class="special">-&gt;</span><span class="identifier">deallocate</span><span class="special">(</span><span class="identifier">segment_mngr</span><span class="special">-&gt;</span><span class="identifier">allocate</span><span class="special">(</span><span class="number">32</span><span class="special">));</span>
<span class="identifier">segment_mngr</span><span class="special">-&gt;</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="string">"My_Int"</span><span class="special">)[</span><span class="number">32</span><span class="special">](</span><span class="number">0</span><span class="special">);</span>
<span class="identifier">segment_mngr</span><span class="special">-&gt;</span><span class="identifier">destroy</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;(</span><span class="string">"My_Int"</span><span class="special">);</span>
<span class="comment">//Initialize the custom, managed memory segment compatible</span>
<span class="comment">//allocator with the segment manager.</span>
<span class="comment">//</span>
<span class="comment">//MySTLAllocator uses segment_mngr-&gt;xxx functions to</span>
<span class="comment">//implement its allocation scheme</span>
<span class="identifier">MySTLAllocator</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">stl_alloc</span><span class="special">(</span><span class="identifier">segment_mngr</span><span class="special">);</span>
<span class="comment">//Alias a new vector type that uses the custom STL compatible allocator</span>
<span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">MySTLAllocator</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="identifier">MyVect</span><span class="special">;</span>
<span class="comment">//Construct the vector in shared memory with the allocator as constructor parameter</span>
<span class="identifier">segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">MyVect</span><span class="special">&gt;(</span><span class="string">"MyVect_instance"</span><span class="special">)(</span><span class="identifier">stl_alloc</span><span class="special">);</span>
</pre>
<p>
The user can create new STL compatible allocators that use the segment manager
to access to all memory management/object construction functions. All <span class="bold"><strong>Boost.Interprocess</strong></span>' STL compatible allocators are
based on this approach. <span class="bold"><strong>Remember</strong></span> that to
be compatible with managed memory segments, allocators should define their
<span class="bold"><strong>pointer</strong></span> typedef as the same pointer family
as <code class="computeroutput"><span class="identifier">segment_manager</span><span class="special">::</span><span class="identifier">void_pointer</span></code> typedef. This means that if
<code class="computeroutput"><span class="identifier">segment_manager</span><span class="special">::</span><span class="identifier">void_pointer</span></code> is <code class="computeroutput"><span class="identifier">offset_ptr</span><span class="special">&lt;</span><span class="keyword">void</span><span class="special">&gt;</span></code>,
<code class="computeroutput"><span class="identifier">MySTLAllocator</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span></code> should
define <code class="computeroutput"><span class="identifier">pointer</span></code> as <code class="computeroutput"><span class="identifier">offset_ptr</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span></code>. The
reason for this is that allocators are members of containers, and if we want
to put the container in a managed memory segment, the allocator should be
ready for that.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.customizing_interprocess.custom_indexes"></a><a class="link" href="customizing_interprocess.html#interprocess.customizing_interprocess.custom_indexes" title="Building custom indexes">Building
custom indexes</a>
</h3></div></div></div>
<p>
The managed memory segment uses a name/object index to speed up object searching
and creation. Default specializations of managed memory segments (<code class="computeroutput"><span class="identifier">managed_shared_memory</span></code> for example), use
<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">flat_map</span></code> as index.
</p>
<p>
However, the index type can be chosen via template parameter, so that the
user can define its own index type if he needs that. To construct a new index
type, the user must create a class with the following guidelines:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
The interface of the index must follow the common public interface of
std::map and std::tr1::unordered_map including public typedefs. The
<code class="computeroutput"><span class="identifier">value_type</span></code> typedef can
be of type:
</li></ul></div>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="identifier">key_type</span><span class="special">,</span> <span class="identifier">mapped_type</span><span class="special">&gt;</span>
</pre>
<p>
or
</p>
<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="keyword">const</span> <span class="identifier">key_type</span><span class="special">,</span> <span class="identifier">mapped_type</span><span class="special">&gt;</span>
</pre>
<p>
so that ordered arrays or deques can be used as index types. Some known classes
following this basic interface are <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">unordered_map</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">flat_map</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">map</span></code>.
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
The class must be a class template taking only a traits struct of this
type:
</li></ul></div>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">index_traits</span>
<span class="special">{</span>
<span class="keyword">typedef</span> <span class="comment">/*...*/</span> <span class="identifier">key_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="comment">/*...*/</span> <span class="identifier">mapped_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="comment">/*...*/</span> <span class="identifier">segment_manager</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">IndexTraits</span><span class="special">&gt;</span>
<span class="keyword">class</span> <span class="identifier">my_index_type</span><span class="special">;</span>
</pre>
<p>
The <code class="computeroutput"><span class="identifier">key_type</span></code> typedef of the
passed <code class="computeroutput"><span class="identifier">index_traits</span></code> will
be a specialization of the following class:
</p>
<pre class="programlisting"><span class="comment">//!The key of the named allocation information index. Stores a to</span>
<span class="comment">//!a null string and the length of the string to speed up sorting</span>
<span class="keyword">template</span><span class="special">&lt;...&gt;</span>
<span class="keyword">struct</span> <span class="identifier">index_key</span>
<span class="special">{</span>
<span class="keyword">typedef</span> <span class="comment">/*...*/</span> <span class="identifier">char_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="comment">/*...*/</span> <span class="identifier">const_char_ptr_t</span><span class="special">;</span>
<span class="comment">//Pointer to the object's name (null terminated)</span>
<span class="identifier">const_char_ptr_t</span> <span class="identifier">mp_str</span><span class="special">;</span>
<span class="comment">//Length of the name buffer (null NOT included)</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">m_len</span><span class="special">;</span>
<span class="comment">//!Constructor of the key</span>
<span class="identifier">index_key</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">CharT</span> <span class="special">*</span><span class="identifier">name</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">length</span><span class="special">);</span>
<span class="comment">//!Less than function for index ordering</span>
<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">&lt;</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">index_key</span> <span class="special">&amp;</span> <span class="identifier">right</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
<span class="comment">//!Equal to function for index ordering</span>
<span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">==</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">index_key</span> <span class="special">&amp;</span> <span class="identifier">right</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p>
The <code class="computeroutput"><span class="identifier">mapped_type</span></code> is not directly
modified by the customized index but it is needed to define the index type.
The <span class="bold"><strong>segment_manager</strong></span> will be the type of
the segment manager that will manage the index. <code class="computeroutput"><span class="identifier">segment_manager</span></code>
will define interesting internal types like <code class="computeroutput"><span class="identifier">void_pointer</span></code>
or <code class="computeroutput"><span class="identifier">mutex_family</span></code>.
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
The constructor of the customized index type must take a pointer to segment_manager
as constructor argument:
</li></ul></div>
<pre class="programlisting"><span class="identifier">constructor</span><span class="special">(</span><span class="identifier">segment_manager</span> <span class="special">*</span><span class="identifier">segment_mngr</span><span class="special">);</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
The index must provide a memory reservation function, that optimizes
the index if the user knows the number of elements to be inserted in
the index:
</li></ul></div>
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">reserve</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">n</span><span class="special">);</span>
</pre>
<p>
For example, the index type <code class="computeroutput"><span class="identifier">flat_map_index</span></code>
based in <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">flat_map</span></code> is just defined as:
</p>
<p>
</p>
<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">interprocess</span> <span class="special">{</span>
<span class="preprocessor">#ifndef</span> <span class="identifier">BOOST_INTERPROCESS_DOXYGEN_INVOKED</span>
<span class="comment">//!Helper class to define typedefs from IndexTraits</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">MapConfig</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">flat_map_index_aux</span>
<span class="special">{</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">MapConfig</span><span class="special">::</span><span class="identifier">key_type</span> <span class="identifier">key_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">MapConfig</span><span class="special">::</span><span class="identifier">mapped_type</span> <span class="identifier">mapped_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">MapConfig</span><span class="special">::</span>
<span class="identifier">segment_manager_base</span> <span class="identifier">segment_manager_base</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">&lt;</span><span class="identifier">key_type</span><span class="special">&gt;</span> <span class="identifier">key_less</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="identifier">key_type</span><span class="special">,</span> <span class="identifier">mapped_type</span><span class="special">&gt;</span> <span class="identifier">value_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">allocator</span><span class="special">&lt;</span><span class="identifier">value_type</span>
<span class="special">,</span><span class="identifier">segment_manager_base</span><span class="special">&gt;</span> <span class="identifier">allocator_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">flat_map</span><span class="special">&lt;</span><span class="identifier">key_type</span><span class="special">,</span> <span class="identifier">mapped_type</span><span class="special">,</span>
<span class="identifier">key_less</span><span class="special">,</span> <span class="identifier">allocator_type</span><span class="special">&gt;</span> <span class="identifier">index_t</span><span class="special">;</span>
<span class="special">};</span>
<span class="preprocessor">#endif</span> <span class="comment">//#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED</span>
<span class="comment">//!Index type based in flat_map. Just derives from flat_map and</span>
<span class="comment">//!defines the interface needed by managed memory segments.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">MapConfig</span><span class="special">&gt;</span>
<span class="keyword">class</span> <span class="identifier">flat_map_index</span>
<span class="comment">//Derive class from flat_map specialization</span>
<span class="special">:</span> <span class="keyword">public</span> <span class="identifier">flat_map_index_aux</span><span class="special">&lt;</span><span class="identifier">MapConfig</span><span class="special">&gt;::</span><span class="identifier">index_t</span>
<span class="special">{</span>
<span class="preprocessor">#if</span> <span class="special">!</span><span class="identifier">defined</span><span class="special">(</span><span class="identifier">BOOST_INTERPROCESS_DOXYGEN_INVOKED</span><span class="special">)</span>
<span class="keyword">typedef</span> <span class="identifier">flat_map_index_aux</span><span class="special">&lt;</span><span class="identifier">MapConfig</span><span class="special">&gt;</span> <span class="identifier">index_aux</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">index_aux</span><span class="special">::</span><span class="identifier">index_t</span> <span class="identifier">base_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">index_aux</span><span class="special">::</span>
<span class="identifier">segment_manager_base</span> <span class="identifier">segment_manager_base</span><span class="special">;</span>
<span class="preprocessor">#endif</span> <span class="comment">//#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED</span>
<span class="keyword">public</span><span class="special">:</span>
<span class="comment">//!Constructor. Takes a pointer to the segment manager. Can throw</span>
<span class="identifier">flat_map_index</span><span class="special">(</span><span class="identifier">segment_manager_base</span> <span class="special">*</span><span class="identifier">segment_mngr</span><span class="special">)</span>
<span class="special">:</span> <span class="identifier">base_type</span><span class="special">(</span><span class="keyword">typename</span> <span class="identifier">index_aux</span><span class="special">::</span><span class="identifier">key_less</span><span class="special">(),</span>
<span class="keyword">typename</span> <span class="identifier">index_aux</span><span class="special">::</span><span class="identifier">allocator_type</span><span class="special">(</span><span class="identifier">segment_mngr</span><span class="special">))</span>
<span class="special">{}</span>
<span class="comment">//!This reserves memory to optimize the insertion of n elements in the index</span>
<span class="keyword">void</span> <span class="identifier">reserve</span><span class="special">(</span><span class="keyword">typename</span> <span class="identifier">segment_manager_base</span><span class="special">::</span><span class="identifier">size_type</span> <span class="identifier">n</span><span class="special">)</span>
<span class="special">{</span> <span class="identifier">base_type</span><span class="special">::</span><span class="identifier">reserve</span><span class="special">(</span><span class="identifier">n</span><span class="special">);</span> <span class="special">}</span>
<span class="comment">//!This frees all unnecessary memory</span>
<span class="keyword">void</span> <span class="identifier">shrink_to_fit</span><span class="special">()</span>
<span class="special">{</span> <span class="identifier">base_type</span><span class="special">::</span><span class="identifier">shrink_to_fit</span><span class="special">();</span> <span class="special">}</span>
<span class="special">};</span>
<span class="special">}}</span> <span class="comment">//namespace boost { namespace interprocess</span>
</pre>
<p>
</p>
<p>
If the user is defining a node container based index (a container whose iterators
are not invalidated when inserting or erasing other elements), <span class="bold"><strong>Boost.Interprocess</strong></span> can optimize named object destruction
when destructing via pointer. <span class="bold"><strong>Boost.Interprocess</strong></span>
can store an iterator next to the object and instead of using the name of
the object to erase the index entry, it uses the iterator, which is a faster
operation. So if you are creating a new node container based index (for example,
a tree), you should define an specialization 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">is_node_index</span><span class="special">&lt;...&gt;</span></code> defined in <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">detail</span><span class="special">/</span><span class="identifier">utilities</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span></code>:
</p>
<pre class="programlisting"><span class="comment">//!Trait classes to detect if an index is a node</span>
<span class="comment">//!index. This allows more efficient operations</span>
<span class="comment">//!when deallocating named objects.</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">MapConfig</span><span class="special">&gt;</span>
<span class="keyword">struct</span> <span class="identifier">is_node_index</span>
<span class="special">&lt;</span><span class="identifier">my_index</span><span class="special">&lt;</span><span class="identifier">MapConfig</span><span class="special">&gt;</span> <span class="special">&gt;</span>
<span class="special">{</span>
<span class="keyword">static</span> <span class="keyword">const</span> <span class="keyword">bool</span> <span class="identifier">value</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span>
<span class="special">};</span>
</pre>
<p>
Interprocess also defines other index types:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>boost::map_index</strong></span> uses <span class="bold"><strong>boost::interprocess::map</strong></span>
as index type.
</li>
<li class="listitem">
<span class="bold"><strong>boost::null_index</strong></span> that uses an dummy
index type if the user just needs anonymous allocations and wants to
save some space and class instantiations.
</li>
</ul></div>
<p>
Defining a new managed memory segment that uses the new index is easy. For
example, a new managed shared memory that uses the new index:
</p>
<pre class="programlisting"><span class="comment">//!Defines a managed shared memory with a c-strings as</span>
<span class="comment">//!a keys, the red-black tree best fit algorithm (with process-shared mutexes</span>
<span class="comment">//!and offset_ptr pointers) as raw shared memory management algorithm</span>
<span class="comment">//!and a custom index</span>
<span class="keyword">typedef</span>
<span class="identifier">basic_managed_shared_memory</span> <span class="special">&lt;</span>
<span class="keyword">char</span><span class="special">,</span>
<span class="identifier">rbtree_best_fit</span><span class="special">&lt;</span><span class="identifier">mutex_family</span><span class="special">&gt;,</span>
<span class="identifier">my_index_type</span>
<span class="special">&gt;</span>
<span class="identifier">my_managed_shared_memory</span><span class="special">;</span>
</pre>
</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="architecture.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="acknowledgements_notes.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,804 @@
<!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>Ownership smart pointers</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="streams.html" title="Direct iostream formatting: vectorstream and bufferstream">
<link rel="next" href="architecture.html" title="Architecture and internals">
</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="streams.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="architecture.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.interprocess_smart_ptr"></a><a class="link" href="interprocess_smart_ptr.html" title="Ownership smart pointers">Ownership smart pointers</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="interprocess_smart_ptr.html#interprocess.interprocess_smart_ptr.intrusive_ptr">Intrusive
pointer</a></span></dt>
<dt><span class="section"><a href="interprocess_smart_ptr.html#interprocess.interprocess_smart_ptr.scoped_ptr">Scoped
pointer</a></span></dt>
<dt><span class="section"><a href="interprocess_smart_ptr.html#interprocess.interprocess_smart_ptr.shared_ptr">Shared
pointer and weak pointer</a></span></dt>
<dt><span class="section"><a href="interprocess_smart_ptr.html#interprocess.interprocess_smart_ptr.unique_ptr">Unique
pointer</a></span></dt>
</dl></div>
<p>
C++ users know the importance of ownership smart pointers when dealing with
resources. Boost offers a wide range of such type of pointers: <code class="computeroutput"><span class="identifier">intrusive_ptr</span><span class="special">&lt;&gt;</span></code>,
<code class="computeroutput"><span class="identifier">scoped_ptr</span><span class="special">&lt;&gt;</span></code>,
<code class="computeroutput"><span class="identifier">shared_ptr</span><span class="special">&lt;&gt;</span></code>...
</p>
<p>
When building complex shared memory/memory mapped files structures, programmers
would like to use also the advantages of these smart pointers. The problem
is that Boost and C++ TR1 smart pointers are not ready to be used for shared
memory. The cause is that those smart pointers contain raw pointers and they
use virtual functions, something that is not possible if you want to place
your data in shared memory. The virtual function limitation makes even impossible
to achieve the same level of functionality of Boost and TR1 with <span class="bold"><strong>Boost.Interprocess</strong></span> smart pointers.
</p>
<p>
Interprocess ownership smart pointers are mainly "smart pointers containing
smart pointers", so we can specify the pointer type they contain.
</p>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.interprocess_smart_ptr.intrusive_ptr"></a><a class="link" href="interprocess_smart_ptr.html#interprocess.interprocess_smart_ptr.intrusive_ptr" title="Intrusive pointer">Intrusive
pointer</a>
</h3></div></div></div>
<p>
<code class="computeroutput"><a class="link" href="../boost/interprocess/intrusive_ptr.html" title="Class template intrusive_ptr">boost::interprocess::intrusive_ptr</a></code>
is the generalization of <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">intrusive_ptr</span><span class="special">&lt;&gt;</span></code> to allow non-raw pointers as intrusive
pointer members. As the well-known <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">intrusive_ptr</span></code>
we must specify the pointee type but we also must also specify the pointer
type to be stored in the intrusive_ptr:
</p>
<pre class="programlisting"><span class="comment">//!The intrusive_ptr class template stores a pointer to an object</span>
<span class="comment">//!with an embedded reference count. intrusive_ptr is parameterized on</span>
<span class="comment">//!T (the type of the object pointed to) and VoidPointer(a void pointer type</span>
<span class="comment">//!that defines the type of pointer that intrusive_ptr will store).</span>
<span class="comment">//!intrusive_ptr&lt;T, void *&gt; defines a class with a T* member whereas</span>
<span class="comment">//!intrusive_ptr&lt;T, offset_ptr&lt;void&gt; &gt; defines a class with a offset_ptr&lt;T&gt; member.</span>
<span class="comment">//!Relies on unqualified calls to:</span>
<span class="comment">//!</span>
<span class="comment">//!void intrusive_ptr_add_ref(T * p);</span>
<span class="comment">//!void intrusive_ptr_release(T * p);</span>
<span class="comment">//!</span>
<span class="comment">//!with (p != 0)</span>
<span class="comment">//!</span>
<span class="comment">//!The object is responsible for destroying itself.</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">VoidPointer</span><span class="special">&gt;</span>
<span class="keyword">class</span> <span class="identifier">intrusive_ptr</span><span class="special">;</span>
</pre>
<p>
So <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">intrusive_ptr</span><span class="special">&lt;</span><span class="identifier">MyClass</span><span class="special">,</span> <span class="keyword">void</span><span class="special">*&gt;</span></code>
is equivalent to <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">intrusive_ptr</span><span class="special">&lt;</span><span class="identifier">MyClass</span><span class="special">&gt;</span></code>.
But if we want to place the intrusive_ptr in shared memory we must specify
a relative pointer type like <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">intrusive_ptr</span><span class="special">&lt;</span><span class="identifier">MyClass</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">offset_ptr</span><span class="special">&lt;</span><span class="keyword">void</span><span class="special">&gt;</span>
<span class="special">&gt;</span></code>
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">smart_ptr</span><span class="special">/</span><span class="identifier">intrusive_ptr</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span>
<span class="keyword">namespace</span> <span class="identifier">N</span> <span class="special">{</span>
<span class="comment">//A class that has an internal reference count</span>
<span class="keyword">class</span> <span class="identifier">reference_counted_class</span>
<span class="special">{</span>
<span class="keyword">private</span><span class="special">:</span>
<span class="comment">//Non-copyable</span>
<span class="identifier">reference_counted_class</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">reference_counted_class</span> <span class="special">&amp;);</span>
<span class="comment">//Non-assignable</span>
<span class="identifier">reference_counted_class</span> <span class="special">&amp;</span> <span class="keyword">operator</span><span class="special">=(</span><span class="keyword">const</span> <span class="identifier">reference_counted_class</span> <span class="special">&amp;);</span>
<span class="comment">//A typedef to save typing</span>
<span class="keyword">typedef</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span> <span class="identifier">segment_manager</span><span class="special">;</span>
<span class="comment">//This is the reference count</span>
<span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">m_use_count</span><span class="special">;</span>
<span class="comment">//The segment manager allows deletion from shared memory segment</span>
<span class="identifier">offset_ptr</span><span class="special">&lt;</span><span class="identifier">segment_manager</span><span class="special">&gt;</span> <span class="identifier">mp_segment_manager</span><span class="special">;</span>
<span class="keyword">public</span><span class="special">:</span>
<span class="comment">//Constructor</span>
<span class="identifier">reference_counted_class</span><span class="special">(</span><span class="identifier">segment_manager</span> <span class="special">*</span><span class="identifier">s_mngr</span><span class="special">)</span>
<span class="special">:</span> <span class="identifier">m_use_count</span><span class="special">(</span><span class="number">0</span><span class="special">),</span> <span class="identifier">mp_segment_manager</span><span class="special">(</span><span class="identifier">s_mngr</span><span class="special">){}</span>
<span class="comment">//Destructor</span>
<span class="special">~</span><span class="identifier">reference_counted_class</span><span class="special">(){}</span>
<span class="keyword">public</span><span class="special">:</span>
<span class="comment">//Returns the reference count</span>
<span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">use_count</span><span class="special">()</span> <span class="keyword">const</span>
<span class="special">{</span> <span class="keyword">return</span> <span class="identifier">m_use_count</span><span class="special">;</span> <span class="special">}</span>
<span class="comment">//Adds a reference</span>
<span class="keyword">inline</span> <span class="keyword">friend</span> <span class="keyword">void</span> <span class="identifier">intrusive_ptr_add_ref</span><span class="special">(</span><span class="identifier">reference_counted_class</span> <span class="special">*</span> <span class="identifier">p</span><span class="special">)</span>
<span class="special">{</span> <span class="special">++</span><span class="identifier">p</span><span class="special">-&gt;</span><span class="identifier">m_use_count</span><span class="special">;</span> <span class="special">}</span>
<span class="comment">//Releases a reference</span>
<span class="keyword">inline</span> <span class="keyword">friend</span> <span class="keyword">void</span> <span class="identifier">intrusive_ptr_release</span><span class="special">(</span><span class="identifier">reference_counted_class</span> <span class="special">*</span> <span class="identifier">p</span><span class="special">)</span>
<span class="special">{</span> <span class="keyword">if</span><span class="special">(--</span><span class="identifier">p</span><span class="special">-&gt;</span><span class="identifier">m_use_count</span> <span class="special">==</span> <span class="number">0</span><span class="special">)</span> <span class="identifier">p</span><span class="special">-&gt;</span><span class="identifier">mp_segment_manager</span><span class="special">-&gt;</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">p</span><span class="special">);</span> <span class="special">}</span>
<span class="special">};</span>
<span class="special">}</span> <span class="comment">//namespace N {</span>
<span class="comment">//A class that has an intrusive pointer to reference_counted_class</span>
<span class="keyword">class</span> <span class="identifier">intrusive_ptr_owner</span>
<span class="special">{</span>
<span class="keyword">typedef</span> <span class="identifier">intrusive_ptr</span><span class="special">&lt;</span><span class="identifier">N</span><span class="special">::</span><span class="identifier">reference_counted_class</span><span class="special">,</span>
<span class="identifier">offset_ptr</span><span class="special">&lt;</span><span class="keyword">void</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="identifier">intrusive_ptr_t</span><span class="special">;</span>
<span class="identifier">intrusive_ptr_t</span> <span class="identifier">m_intrusive_ptr</span><span class="special">;</span>
<span class="keyword">public</span><span class="special">:</span>
<span class="comment">//Takes a pointer to the reference counted class</span>
<span class="identifier">intrusive_ptr_owner</span><span class="special">(</span><span class="identifier">N</span><span class="special">::</span><span class="identifier">reference_counted_class</span> <span class="special">*</span><span class="identifier">ptr</span><span class="special">)</span>
<span class="special">:</span> <span class="identifier">m_intrusive_ptr</span><span class="special">(</span><span class="identifier">ptr</span><span class="special">){}</span>
<span class="special">};</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
<span class="special">{</span>
<span class="comment">//Remove shared memory on construction and destruction</span>
<span class="keyword">struct</span> <span class="identifier">shm_remove</span>
<span class="special">{</span>
<span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span>
<span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span>
<span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span>
<span class="comment">//Create shared memory</span>
<span class="identifier">managed_shared_memory</span> <span class="identifier">shmem</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> <span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="number">10000</span><span class="special">);</span>
<span class="comment">//Create the unique reference counted object in shared memory</span>
<span class="identifier">N</span><span class="special">::</span><span class="identifier">reference_counted_class</span> <span class="special">*</span><span class="identifier">ref_counted</span> <span class="special">=</span>
<span class="identifier">shmem</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">N</span><span class="special">::</span><span class="identifier">reference_counted_class</span><span class="special">&gt;</span>
<span class="special">(</span><span class="string">"ref_counted"</span><span class="special">)(</span><span class="identifier">shmem</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span>
<span class="comment">//Create an array of ten intrusive pointer owners in shared memory</span>
<span class="identifier">intrusive_ptr_owner</span> <span class="special">*</span><span class="identifier">intrusive_owner_array</span> <span class="special">=</span>
<span class="identifier">shmem</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">intrusive_ptr_owner</span><span class="special">&gt;</span>
<span class="special">(</span><span class="identifier">anonymous_instance</span><span class="special">)[</span><span class="number">10</span><span class="special">](</span><span class="identifier">ref_counted</span><span class="special">);</span>
<span class="comment">//Now test that reference count is ten</span>
<span class="keyword">if</span><span class="special">(</span><span class="identifier">ref_counted</span><span class="special">-&gt;</span><span class="identifier">use_count</span><span class="special">()</span> <span class="special">!=</span> <span class="number">10</span><span class="special">)</span>
<span class="keyword">return</span> <span class="number">1</span><span class="special">;</span>
<span class="comment">//Now destroy the array of intrusive pointer owners</span>
<span class="comment">//This should destroy every intrusive_ptr and because of</span>
<span class="comment">//that reference_counted_class will be destroyed</span>
<span class="identifier">shmem</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">intrusive_owner_array</span><span class="special">);</span>
<span class="comment">//Now the reference counted object should have been destroyed</span>
<span class="keyword">if</span><span class="special">(</span><span class="identifier">shmem</span><span class="special">.</span><span class="identifier">find</span><span class="special">&lt;</span><span class="identifier">intrusive_ptr_owner</span><span class="special">&gt;(</span><span class="string">"ref_counted"</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">//Success!</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><h3 class="title">
<a name="interprocess.interprocess_smart_ptr.scoped_ptr"></a><a class="link" href="interprocess_smart_ptr.html#interprocess.interprocess_smart_ptr.scoped_ptr" title="Scoped pointer">Scoped
pointer</a>
</h3></div></div></div>
<p>
<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">scoped_ptr</span><span class="special">&lt;&gt;</span></code>
is the big brother of <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">scoped_ptr</span><span class="special">&lt;&gt;</span></code>, which adds a custom deleter to specify
how the pointer passed to the scoped_ptr must be destroyed. Also, the <code class="computeroutput"><span class="identifier">pointer</span></code> typedef of the deleter will specify
the pointer type stored by scoped_ptr.
</p>
<pre class="programlisting"><span class="comment">//!scoped_ptr stores a pointer to a dynamically allocated object.</span>
<span class="comment">//!The object pointed to is guaranteed to be deleted, either on destruction</span>
<span class="comment">//!of the scoped_ptr, or via an explicit reset. The user can avoid this</span>
<span class="comment">//!deletion using release().</span>
<span class="comment">//!scoped_ptr is parameterized on T (the type of the object pointed to) and</span>
<span class="comment">//!Deleter (the functor to be executed to delete the internal pointer).</span>
<span class="comment">//!The internal pointer will be of the same pointer type as typename</span>
<span class="comment">//!Deleter::pointer type (that is, if typename Deleter::pointer is</span>
<span class="comment">//!offset_ptr&lt;void&gt;, the internal pointer will be offset_ptr&lt;T&gt;).</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Deleter</span><span class="special">&gt;</span>
<span class="keyword">class</span> <span class="identifier">scoped_ptr</span><span class="special">;</span>
</pre>
<p>
<code class="computeroutput"><span class="identifier">scoped_ptr</span><span class="special">&lt;&gt;</span></code>
comes handy to implement <span class="bold"><strong>rollbacks</strong></span> with
exceptions: if an exception is thrown or we call <code class="computeroutput"><span class="keyword">return</span></code>
in the scope of <code class="computeroutput"><span class="identifier">scoped_ptr</span><span class="special">&lt;&gt;</span></code> the deleter is automatically called
so that <span class="bold"><strong>the deleter can be considered as a rollback</strong></span>
function. If all goes well, we call <code class="computeroutput"><span class="identifier">release</span><span class="special">()</span></code> member function to avoid rollback when
the <code class="computeroutput"><span class="identifier">scoped_ptr</span></code> goes out of
scope.
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">smart_ptr</span><span class="special">/</span><span class="identifier">scoped_ptr</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</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">class</span> <span class="identifier">my_class</span>
<span class="special">{};</span>
<span class="keyword">class</span> <span class="identifier">my_exception</span>
<span class="special">{};</span>
<span class="comment">//A functor that destroys the shared memory object</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span>
<span class="keyword">class</span> <span class="identifier">my_deleter</span>
<span class="special">{</span>
<span class="keyword">private</span><span class="special">:</span>
<span class="comment">//A typedef to save typing</span>
<span class="keyword">typedef</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span> <span class="identifier">segment_manager</span><span class="special">;</span>
<span class="comment">//This my_deleter is created in the stack, not in shared memory,</span>
<span class="comment">//so we can use raw pointers</span>
<span class="identifier">segment_manager</span> <span class="special">*</span><span class="identifier">mp_segment_manager</span><span class="special">;</span>
<span class="keyword">public</span><span class="special">:</span>
<span class="comment">//This typedef will specify the pointer type that</span>
<span class="comment">//scoped_ptr will store</span>
<span class="keyword">typedef</span> <span class="identifier">T</span> <span class="special">*</span><span class="identifier">pointer</span><span class="special">;</span>
<span class="comment">//Constructor</span>
<span class="identifier">my_deleter</span><span class="special">(</span><span class="identifier">segment_manager</span> <span class="special">*</span><span class="identifier">s_mngr</span><span class="special">)</span>
<span class="special">:</span> <span class="identifier">mp_segment_manager</span><span class="special">(</span><span class="identifier">s_mngr</span><span class="special">){}</span>
<span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">pointer</span> <span class="identifier">object_to_delete</span><span class="special">)</span>
<span class="special">{</span> <span class="identifier">mp_segment_manager</span><span class="special">-&gt;</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">object_to_delete</span><span class="special">);</span> <span class="special">}</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">//Create shared memory</span>
<span class="comment">//Remove shared memory on construction and destruction</span>
<span class="keyword">struct</span> <span class="identifier">shm_remove</span>
<span class="special">{</span>
<span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span>
<span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span>
<span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span>
<span class="identifier">managed_shared_memory</span> <span class="identifier">shmem</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> <span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="number">10000</span><span class="special">);</span>
<span class="comment">//In the first try, there will be no exceptions</span>
<span class="comment">//in the second try we will throw an exception</span>
<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="number">2</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
<span class="comment">//Create an object in shared memory</span>
<span class="identifier">my_class</span> <span class="special">*</span> <span class="identifier">my_object</span> <span class="special">=</span> <span class="identifier">shmem</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">my_class</span><span class="special">&gt;(</span><span class="string">"my_object"</span><span class="special">)();</span>
<span class="identifier">my_class</span> <span class="special">*</span> <span class="identifier">my_object2</span> <span class="special">=</span> <span class="identifier">shmem</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">my_class</span><span class="special">&gt;(</span><span class="identifier">anonymous_instance</span><span class="special">)();</span>
<span class="identifier">shmem</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">my_object2</span><span class="special">);</span>
<span class="comment">//Since the next shared memory allocation can throw</span>
<span class="comment">//assign it to a scoped_ptr so that if an exception occurs</span>
<span class="comment">//we destroy the object automatically</span>
<span class="identifier">my_deleter</span><span class="special">&lt;</span><span class="identifier">my_class</span><span class="special">&gt;</span> <span class="identifier">d</span><span class="special">(</span><span class="identifier">shmem</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span>
<span class="keyword">try</span><span class="special">{</span>
<span class="identifier">scoped_ptr</span><span class="special">&lt;</span><span class="identifier">my_class</span><span class="special">,</span> <span class="identifier">my_deleter</span><span class="special">&lt;</span><span class="identifier">my_class</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="identifier">s_ptr</span><span class="special">(</span><span class="identifier">my_object</span><span class="special">,</span> <span class="identifier">d</span><span class="special">);</span>
<span class="comment">//Let's emulate a exception capable operation</span>
<span class="comment">//In the second try, throw an exception</span>
<span class="keyword">if</span><span class="special">(</span><span class="identifier">i</span> <span class="special">==</span> <span class="number">1</span><span class="special">){</span>
<span class="keyword">throw</span><span class="special">(</span><span class="identifier">my_exception</span><span class="special">());</span>
<span class="special">}</span>
<span class="comment">//If we have passed the dangerous zone</span>
<span class="comment">//we can release the scoped pointer</span>
<span class="comment">//to avoid destruction</span>
<span class="identifier">s_ptr</span><span class="special">.</span><span class="identifier">release</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">my_exception</span> <span class="special">&amp;){}</span>
<span class="comment">//Here, scoped_ptr is destroyed</span>
<span class="comment">//so it we haven't thrown an exception</span>
<span class="comment">//the object should be there, otherwise, destroyed</span>
<span class="keyword">if</span><span class="special">(</span><span class="identifier">i</span> <span class="special">==</span> <span class="number">0</span><span class="special">){</span>
<span class="comment">//Make sure the object is alive</span>
<span class="keyword">if</span><span class="special">(!</span><span class="identifier">shmem</span><span class="special">.</span><span class="identifier">find</span><span class="special">&lt;</span><span class="identifier">my_class</span><span class="special">&gt;(</span><span class="string">"my_object"</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="special">}</span>
<span class="comment">//Now we can use it and delete it manually</span>
<span class="identifier">shmem</span><span class="special">.</span><span class="identifier">destroy</span><span class="special">&lt;</span><span class="identifier">my_class</span><span class="special">&gt;(</span><span class="string">"my_object"</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">else</span><span class="special">{</span>
<span class="comment">//Make sure the object has been deleted</span>
<span class="keyword">if</span><span class="special">(</span><span class="identifier">shmem</span><span class="special">.</span><span class="identifier">find</span><span class="special">&lt;</span><span class="identifier">my_class</span><span class="special">&gt;(</span><span class="string">"my_object"</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="special">}</span>
<span class="special">}</span>
<span class="special">}</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.interprocess_smart_ptr.shared_ptr"></a><a class="link" href="interprocess_smart_ptr.html#interprocess.interprocess_smart_ptr.shared_ptr" title="Shared pointer and weak pointer">Shared
pointer and weak pointer</a>
</h3></div></div></div>
<p>
<span class="bold"><strong>Boost.Interprocess</strong></span> also offers the possibility
of creating non-intrusive reference-counted objects in managed shared memory
or mapped files.
</p>
<p>
Unlike <a href="http://www.boost.org/libs/smart_ptr/shared_ptr.htm" target="_top">boost::shared_ptr</a>,
due to limitations of mapped segments <code class="computeroutput"><a class="link" href="../boost/interprocess/shared_ptr.html" title="Class template shared_ptr">boost::interprocess::shared_ptr</a></code>
cannot take advantage of virtual functions to maintain the same shared pointer
type while providing user-defined allocators and deleters. The allocator
and the deleter are template parameters of the shared pointer.
</p>
<p>
Since the reference count and other auxiliary data needed by <code class="computeroutput"><a class="link" href="../boost/interprocess/shared_ptr.html" title="Class template shared_ptr">shared_ptr</a></code>
must be created also in the managed segment, and the deleter has to delete
the object from the segment, the user must specify an allocator object and
a deleter object when constructing a non-empty instance of <code class="computeroutput"><a class="link" href="../boost/interprocess/shared_ptr.html" title="Class template shared_ptr">shared_ptr</a></code>,
just like <span class="bold"><strong>Boost.Interprocess</strong></span> containers
need to pass allocators in their constructors.
</p>
<p>
Here is the declaration of <code class="computeroutput"><a class="link" href="../boost/interprocess/shared_ptr.html" title="Class template shared_ptr">shared_ptr</a></code>:
</p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">VoidAllocator</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Deleter</span><span class="special">&gt;</span>
<span class="keyword">class</span> <span class="identifier">shared_ptr</span><span class="special">;</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
T is the type of the pointed type.
</li>
<li class="listitem">
VoidAllocator is the allocator to be used to allocate auxiliary elements
such as the reference count, the deleter... The internal <code class="computeroutput"><span class="identifier">pointer</span></code> typedef of the allocator will
determine the type of pointer that shared_ptr will internally use, so
allocators defining <code class="computeroutput"><span class="identifier">pointer</span></code>
as <code class="computeroutput"><span class="identifier">offset_ptr</span><span class="special">&lt;</span><span class="keyword">void</span><span class="special">&gt;</span></code>
will make all internal pointers used by <code class="computeroutput"><span class="identifier">shared_ptr</span></code>
to be also relative pointers. See <code class="computeroutput"><a class="link" href="../boost/interprocess/allocator.html" title="Class template allocator">boost::interprocess::allocator</a></code>
for a working allocator.
</li>
<li class="listitem">
Deleter is the function object that will be used to destroy the pointed
object when the last reference to the object is destroyed. The deleter
functor will take a pointer to T of the same category as the void pointer
defined by <code class="computeroutput"><span class="identifier">VoidAllocator</span><span class="special">::</span><span class="identifier">pointer</span></code>.
See <code class="computeroutput"><a class="link" href="../boost/interprocess/deleter.html" title="Class template deleter">boost::interprocess::deleter</a></code>
for a generic deleter that erases a object from a managed segment.
</li>
</ul></div>
<p>
With correctly specified parameters, <span class="bold"><strong>Boost.Interprocess</strong></span>
users can create objects in shared memory that hold shared pointers pointing
to other objects also in shared memory, obtaining the benefits of reference
counting. Let's see how to create a shared pointer in a managed shared memory:
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">smart_ptr</span><span class="special">/</span><span class="identifier">shared_ptr</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">smart_ptr</span><span class="special">/</span><span class="identifier">deleter</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cassert</span><span class="special">&gt;</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">//This is type of the object we want to share</span>
<span class="keyword">class</span> <span class="identifier">MyType</span>
<span class="special">{};</span>
<span class="keyword">typedef</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span> <span class="identifier">segment_manager_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">allocator</span><span class="special">&lt;</span><span class="keyword">void</span><span class="special">,</span> <span class="identifier">segment_manager_type</span><span class="special">&gt;</span> <span class="identifier">void_allocator_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">deleter</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">,</span> <span class="identifier">segment_manager_type</span><span class="special">&gt;</span> <span class="identifier">deleter_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">shared_ptr</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">,</span> <span class="identifier">void_allocator_type</span><span class="special">,</span> <span class="identifier">deleter_type</span><span class="special">&gt;</span> <span class="identifier">my_shared_ptr</span><span class="special">;</span>
<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span>
<span class="special">{</span>
<span class="comment">//Remove shared memory on construction and destruction</span>
<span class="keyword">struct</span> <span class="identifier">shm_remove</span>
<span class="special">{</span>
<span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span>
<span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span>
<span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span>
<span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> <span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="number">4096</span><span class="special">);</span>
<span class="comment">//Create a shared pointer in shared memory</span>
<span class="comment">//pointing to a newly created object in the segment</span>
<span class="identifier">my_shared_ptr</span> <span class="special">&amp;</span><span class="identifier">shared_ptr_instance</span> <span class="special">=</span>
<span class="special">*</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">my_shared_ptr</span><span class="special">&gt;(</span><span class="string">"shared ptr"</span><span class="special">)</span>
<span class="comment">//Arguments to construct the shared pointer</span>
<span class="special">(</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">&gt;(</span><span class="string">"object to share"</span><span class="special">)()</span> <span class="comment">//object to own</span>
<span class="special">,</span> <span class="identifier">void_allocator_type</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">())</span> <span class="comment">//allocator</span>
<span class="special">,</span> <span class="identifier">deleter_type</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">())</span> <span class="comment">//deleter</span>
<span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">shared_ptr_instance</span><span class="special">.</span><span class="identifier">use_count</span><span class="special">()</span> <span class="special">==</span> <span class="number">1</span><span class="special">);</span>
<span class="comment">//Destroy "shared ptr". "object to share" will be automatically destroyed</span>
<span class="identifier">segment</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(&amp;</span><span class="identifier">shared_ptr_instance</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/shared_ptr.html" title="Class template shared_ptr">boost::interprocess::shared_ptr</a></code>
is very flexible and configurable (we can specify the allocator and the deleter,
for example), but as shown the creation of a shared pointer in managed segments
need too much typing.
</p>
<p>
To simplify this usage, <code class="computeroutput"><a class="link" href="../boost/interprocess/shared_ptr.html" title="Class template shared_ptr">boost::interprocess::shared_ptr</a></code>
header offers a shared pointer definition helper class (<code class="computeroutput"><a class="link" href="../boost/interprocess/managed_shared_ptr.html" title="Struct template managed_shared_ptr">managed_shared_ptr</a></code>)
and a function (<code class="computeroutput"><a class="link" href="../boost/interprocess/make_man_idm45189371714944.html" title="Function template make_managed_shared_ptr">make_managed_shared_ptr</a></code>)
to easily construct a shared pointer from a type allocated in a managed segment
with an allocator that will allocate the reference count also in the managed
segment and a deleter that will erase the object from the segment.
</p>
<p>
These utilities will use a <span class="bold"><strong>Boost.Interprocess</strong></span>
allocator (<code class="computeroutput"><a class="link" href="../boost/interprocess/allocator.html" title="Class template allocator">boost::interprocess::allocator</a></code>)
and deleter (<code class="computeroutput"><a class="link" href="../boost/interprocess/deleter.html" title="Class template deleter">boost::interprocess::deleter</a></code>)
to do their job. The definition of the previous shared pointer could be simplified
to the following:
</p>
<pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">managed_shared_ptr</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">,</span> <span class="identifier">managed_shared_memory</span><span class="special">&gt;::</span><span class="identifier">type</span> <span class="identifier">my_shared_ptr</span><span class="special">;</span>
</pre>
<p>
And the creation of a shared pointer can be simplified to this:
</p>
<pre class="programlisting"><span class="identifier">my_shared_ptr</span> <span class="identifier">sh_ptr</span> <span class="special">=</span> <span class="identifier">make_managed_shared_ptr</span>
<span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">&gt;(</span><span class="string">"object to share"</span><span class="special">)(),</span> <span class="identifier">segment</span><span class="special">);</span>
</pre>
<p>
<span class="bold"><strong>Boost.Interprocess</strong></span> also offers a weak pointer
named <code class="computeroutput"><a class="link" href="../boost/interprocess/weak_ptr.html" title="Class template weak_ptr">weak_ptr</a></code>
(with its corresponding <code class="computeroutput"><a class="link" href="../boost/interprocess/managed_weak_ptr.html" title="Struct template managed_weak_ptr">managed_weak_ptr</a></code>
and <code class="computeroutput"><a class="link" href="../boost/interprocess/make_managed_weak_ptr.html" title="Function template make_managed_weak_ptr">make_managed_weak_ptr</a></code>
utilities) to implement non-owning observers of an object owned by <code class="computeroutput"><a class="link" href="../boost/interprocess/shared_ptr.html" title="Class template shared_ptr">shared_ptr</a></code>.
</p>
<p>
Now let's see a detailed example of the use of <code class="computeroutput"><a class="link" href="../boost/interprocess/shared_ptr.html" title="Class template shared_ptr">shared_ptr</a></code>:
and <code class="computeroutput"><a class="link" href="../boost/interprocess/weak_ptr.html" title="Class template weak_ptr">weak_ptr</a></code>
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">smart_ptr</span><span class="special">/</span><span class="identifier">shared_ptr</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">smart_ptr</span><span class="special">/</span><span class="identifier">weak_ptr</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cassert</span><span class="special">&gt;</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">//This is type of the object we want to share</span>
<span class="keyword">struct</span> <span class="identifier">type_to_share</span>
<span class="special">{};</span>
<span class="comment">//This is the type of a shared pointer to the previous type</span>
<span class="comment">//that will be built in the mapped file</span>
<span class="keyword">typedef</span> <span class="identifier">managed_shared_ptr</span><span class="special">&lt;</span><span class="identifier">type_to_share</span><span class="special">,</span> <span class="identifier">managed_mapped_file</span><span class="special">&gt;::</span><span class="identifier">type</span> <span class="identifier">shared_ptr_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">managed_weak_ptr</span><span class="special">&lt;</span><span class="identifier">type_to_share</span><span class="special">,</span> <span class="identifier">managed_mapped_file</span><span class="special">&gt;::</span><span class="identifier">type</span> <span class="identifier">weak_ptr_type</span><span class="special">;</span>
<span class="comment">//This is a type holding a shared pointer</span>
<span class="keyword">struct</span> <span class="identifier">shared_ptr_owner</span>
<span class="special">{</span>
<span class="identifier">shared_ptr_owner</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">shared_ptr_type</span> <span class="special">&amp;</span><span class="identifier">other_shared_ptr</span><span class="special">)</span>
<span class="special">:</span> <span class="identifier">shared_ptr_</span><span class="special">(</span><span class="identifier">other_shared_ptr</span><span class="special">)</span>
<span class="special">{}</span>
<span class="identifier">shared_ptr_owner</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">shared_ptr_owner</span> <span class="special">&amp;</span><span class="identifier">other_owner</span><span class="special">)</span>
<span class="special">:</span> <span class="identifier">shared_ptr_</span><span class="special">(</span><span class="identifier">other_owner</span><span class="special">.</span><span class="identifier">shared_ptr_</span><span class="special">)</span>
<span class="special">{}</span>
<span class="identifier">shared_ptr_type</span> <span class="identifier">shared_ptr_</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="comment">//Define file names</span>
<span class="keyword">const</span> <span class="keyword">char</span> <span class="special">*</span><span class="identifier">MappedFile</span> <span class="special">=</span> <span class="string">"MyMappedFile"</span><span class="special">;</span>
<span class="comment">//Destroy any previous file with the name to be used.</span>
<span class="keyword">struct</span> <span class="identifier">file_remove</span>
<span class="special">{</span>
<span class="identifier">file_remove</span><span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span> <span class="special">*</span><span class="identifier">MappedFile</span><span class="special">)</span>
<span class="special">:</span> <span class="identifier">MappedFile_</span><span class="special">(</span><span class="identifier">MappedFile</span><span class="special">)</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">MappedFile_</span><span class="special">);</span> <span class="special">}</span>
<span class="special">~</span><span class="identifier">file_remove</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">MappedFile_</span><span class="special">);</span> <span class="special">}</span>
<span class="keyword">const</span> <span class="keyword">char</span> <span class="special">*</span><span class="identifier">MappedFile_</span><span class="special">;</span>
<span class="special">}</span> <span class="identifier">remover</span><span class="special">(</span><span class="identifier">MappedFile</span><span class="special">);</span>
<span class="special">{</span>
<span class="identifier">managed_mapped_file</span> <span class="identifier">file</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> <span class="identifier">MappedFile</span><span class="special">,</span> <span class="number">65536</span><span class="special">);</span>
<span class="comment">//Construct the shared type in the file and</span>
<span class="comment">//pass ownership to this local shared pointer</span>
<span class="identifier">shared_ptr_type</span> <span class="identifier">local_shared_ptr</span> <span class="special">=</span> <span class="identifier">make_managed_shared_ptr</span>
<span class="special">(</span><span class="identifier">file</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">type_to_share</span><span class="special">&gt;(</span><span class="string">"object to share"</span><span class="special">)(),</span> <span class="identifier">file</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">local_shared_ptr</span><span class="special">.</span><span class="identifier">use_count</span><span class="special">()</span> <span class="special">==</span> <span class="number">1</span><span class="special">);</span>
<span class="comment">//Share ownership of the object between local_shared_ptr and a new "owner1"</span>
<span class="identifier">shared_ptr_owner</span> <span class="special">*</span><span class="identifier">owner1</span> <span class="special">=</span>
<span class="identifier">file</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">shared_ptr_owner</span><span class="special">&gt;(</span><span class="string">"owner1"</span><span class="special">)(</span><span class="identifier">local_shared_ptr</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">local_shared_ptr</span><span class="special">.</span><span class="identifier">use_count</span><span class="special">()</span> <span class="special">==</span> <span class="number">2</span><span class="special">);</span>
<span class="comment">//local_shared_ptr releases object ownership</span>
<span class="identifier">local_shared_ptr</span><span class="special">.</span><span class="identifier">reset</span><span class="special">();</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">local_shared_ptr</span><span class="special">.</span><span class="identifier">use_count</span><span class="special">()</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">owner1</span><span class="special">-&gt;</span><span class="identifier">shared_ptr_</span><span class="special">.</span><span class="identifier">use_count</span><span class="special">()</span> <span class="special">==</span> <span class="number">1</span><span class="special">);</span>
<span class="comment">//Share ownership of the object between "owner1" and a new "owner2"</span>
<span class="identifier">shared_ptr_owner</span> <span class="special">*</span><span class="identifier">owner2</span> <span class="special">=</span>
<span class="identifier">file</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">shared_ptr_owner</span><span class="special">&gt;(</span><span class="string">"owner2"</span><span class="special">)(*</span><span class="identifier">owner1</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">owner1</span><span class="special">-&gt;</span><span class="identifier">shared_ptr_</span><span class="special">.</span><span class="identifier">use_count</span><span class="special">()</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">owner2</span><span class="special">-&gt;</span><span class="identifier">shared_ptr_</span><span class="special">.</span><span class="identifier">use_count</span><span class="special">()</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">owner1</span><span class="special">-&gt;</span><span class="identifier">shared_ptr_</span><span class="special">.</span><span class="identifier">get</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">owner2</span><span class="special">-&gt;</span><span class="identifier">shared_ptr_</span><span class="special">.</span><span class="identifier">get</span><span class="special">());</span>
<span class="comment">//The mapped file is unmapped here. Objects have been flushed to disk</span>
<span class="special">}</span>
<span class="special">{</span>
<span class="comment">//Reopen the mapped file and find again all owners</span>
<span class="identifier">managed_mapped_file</span> <span class="identifier">file</span><span class="special">(</span><span class="identifier">open_only</span><span class="special">,</span> <span class="identifier">MappedFile</span><span class="special">);</span>
<span class="identifier">shared_ptr_owner</span> <span class="special">*</span><span class="identifier">owner1</span> <span class="special">=</span> <span class="identifier">file</span><span class="special">.</span><span class="identifier">find</span><span class="special">&lt;</span><span class="identifier">shared_ptr_owner</span><span class="special">&gt;(</span><span class="string">"owner1"</span><span class="special">).</span><span class="identifier">first</span><span class="special">;</span>
<span class="identifier">shared_ptr_owner</span> <span class="special">*</span><span class="identifier">owner2</span> <span class="special">=</span> <span class="identifier">file</span><span class="special">.</span><span class="identifier">find</span><span class="special">&lt;</span><span class="identifier">shared_ptr_owner</span><span class="special">&gt;(</span><span class="string">"owner2"</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">owner1</span> <span class="special">&amp;&amp;</span> <span class="identifier">owner2</span><span class="special">);</span>
<span class="comment">//Check everything is as expected</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">file</span><span class="special">.</span><span class="identifier">find</span><span class="special">&lt;</span><span class="identifier">type_to_share</span><span class="special">&gt;(</span><span class="string">"object to share"</span><span class="special">).</span><span class="identifier">first</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">owner1</span><span class="special">-&gt;</span><span class="identifier">shared_ptr_</span><span class="special">.</span><span class="identifier">use_count</span><span class="special">()</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">owner2</span><span class="special">-&gt;</span><span class="identifier">shared_ptr_</span><span class="special">.</span><span class="identifier">use_count</span><span class="special">()</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">owner1</span><span class="special">-&gt;</span><span class="identifier">shared_ptr_</span><span class="special">.</span><span class="identifier">get</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">owner2</span><span class="special">-&gt;</span><span class="identifier">shared_ptr_</span><span class="special">.</span><span class="identifier">get</span><span class="special">());</span>
<span class="comment">//Now destroy one of the owners, the reference count drops.</span>
<span class="identifier">file</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">owner1</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">owner2</span><span class="special">-&gt;</span><span class="identifier">shared_ptr_</span><span class="special">.</span><span class="identifier">use_count</span><span class="special">()</span> <span class="special">==</span> <span class="number">1</span><span class="special">);</span>
<span class="comment">//Create a weak pointer</span>
<span class="identifier">weak_ptr_type</span> <span class="identifier">local_observer1</span><span class="special">(</span><span class="identifier">owner2</span><span class="special">-&gt;</span><span class="identifier">shared_ptr_</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">local_observer1</span><span class="special">.</span><span class="identifier">use_count</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">owner2</span><span class="special">-&gt;</span><span class="identifier">shared_ptr_</span><span class="special">.</span><span class="identifier">use_count</span><span class="special">());</span>
<span class="special">{</span> <span class="comment">//Create a local shared pointer from the weak pointer</span>
<span class="identifier">shared_ptr_type</span> <span class="identifier">local_shared_ptr</span> <span class="special">=</span> <span class="identifier">local_observer1</span><span class="special">.</span><span class="identifier">lock</span><span class="special">();</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">local_observer1</span><span class="special">.</span><span class="identifier">use_count</span><span class="special">()</span> <span class="special">==</span> <span class="identifier">owner2</span><span class="special">-&gt;</span><span class="identifier">shared_ptr_</span><span class="special">.</span><span class="identifier">use_count</span><span class="special">());</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">local_observer1</span><span class="special">.</span><span class="identifier">use_count</span><span class="special">()</span> <span class="special">==</span> <span class="number">2</span><span class="special">);</span>
<span class="special">}</span>
<span class="comment">//Now destroy the remaining owner. "object to share" will be destroyed</span>
<span class="identifier">file</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">owner2</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">file</span><span class="special">.</span><span class="identifier">find</span><span class="special">&lt;</span><span class="identifier">type_to_share</span><span class="special">&gt;(</span><span class="string">"object to share"</span><span class="special">).</span><span class="identifier">first</span> <span class="special">==</span> <span class="number">0</span><span class="special">);</span>
<span class="comment">//Test observer</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">local_observer1</span><span class="special">.</span><span class="identifier">expired</span><span class="special">());</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">local_observer1</span><span class="special">.</span><span class="identifier">use_count</span><span class="special">()</span> <span class="special">==</span> <span class="number">0</span><span class="special">);</span>
<span class="comment">//The reference count will be deallocated when all weak pointers</span>
<span class="comment">//disappear. After that, the file is unmapped.</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>
In general, using <span class="bold"><strong>Boost.Interprocess</strong></span>' <code class="computeroutput"><a class="link" href="../boost/interprocess/shared_ptr.html" title="Class template shared_ptr">shared_ptr</a></code> and <code class="computeroutput"><a class="link" href="../boost/interprocess/weak_ptr.html" title="Class template weak_ptr">weak_ptr</a></code> is very similar
to their counterparts <a href="http://www.boost.org/libs/smart_ptr/shared_ptr.htm" target="_top">boost::shared_ptr</a>
and <a href="http://www.boost.org/libs/smart_ptr/weak_ptr.htm" target="_top">boost::weak_ptr</a>,
but they need more template parameters and more run-time parameters in their
constructors.
</p>
<p>
Just like <a href="http://www.boost.org/libs/smart_ptr/shared_ptr.htm" target="_top">boost::shared_ptr</a>
can be stored in a STL container, <code class="computeroutput"><a class="link" href="../boost/interprocess/shared_ptr.html" title="Class template shared_ptr">shared_ptr</a></code>
can also be stored in <span class="bold"><strong>Boost.Interprocess</strong></span>
containers.
</p>
<p>
If a programmer just uses <code class="computeroutput"><a class="link" href="../boost/interprocess/shared_ptr.html" title="Class template shared_ptr">shared_ptr</a></code>
to be able to insert dynamically constructed objects into a container constructed
in the managed segment, but he does not need to share the ownership of that
object with other objects <code class="computeroutput"><a class="link" href="../boost/interprocess/managed_unique_ptr.html" title="Struct template managed_unique_ptr">managed_unique_ptr</a></code>
is a much faster and easier to use alternative.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.interprocess_smart_ptr.unique_ptr"></a><a class="link" href="interprocess_smart_ptr.html#interprocess.interprocess_smart_ptr.unique_ptr" title="Unique pointer">Unique
pointer</a>
</h3></div></div></div>
<p>
Unique ownership smart pointers are really useful to free programmers from
manual resource liberation of non-shared objects. <span class="bold"><strong>Boost.Interprocess</strong></span>'
<code class="computeroutput"><span class="identifier">unique_ptr</span></code> is much like
<code class="computeroutput"><a class="link" href="../boost/interprocess/scoped_ptr.html" title="Class template scoped_ptr">scoped_ptr</a></code> but
it's <span class="bold"><strong>moveable</strong></span> and can be easily inserted
in <span class="bold"><strong>Boost.Interprocess</strong></span> containers. Interprocess
had its own <code class="computeroutput"><span class="identifier">unique_ptr</span></code> implementation
but from Boost 1.57, <span class="bold"><strong>Boost.Interprocess</strong></span>
uses the improved and generic <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">unique_ptr</span></code>
implementation. Here is the declaration of the unique pointer class:
</p>
<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">D</span><span class="special">&gt;</span>
<span class="keyword">class</span> <span class="identifier">unique_ptr</span><span class="special">;</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
T is the type of the object pointed by <code class="computeroutput"><span class="identifier">unique_ptr</span></code>.
</li>
<li class="listitem">
D is the deleter that will erase the object type of the object pointed
by the unique_ptr when the unique pointer is destroyed (and if still
has the ownership of the object). If the deleter defines an internal
<code class="computeroutput"><span class="identifier">pointer</span></code> typedef, <code class="computeroutput"><span class="identifier">unique_ptr</span></code>] will use an internal pointer
of the same type. So if <code class="computeroutput"><span class="identifier">D</span><span class="special">::</span><span class="identifier">pointer</span></code>
is <code class="computeroutput"><span class="identifier">offset_ptr</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span></code>
the unique pointer will store a relative pointer instead of a raw one.
This allows placing <code class="computeroutput"><span class="identifier">unique_ptr</span></code>
in shared memory and memory-mapped files.
</li>
</ul></div>
<p>
<code class="computeroutput"><span class="identifier">unique_ptr</span></code> can release the
ownership of the stored pointer so it's useful also to be used as a rollback
function. One of the main properties of the class is that <span class="bold"><strong>is
not copyable, but only moveable</strong></span>. When a unique pointer is moved
to another one, the ownership of the pointer is transferred from the source
unique pointer to the target unique pointer. If the target unique pointer
owned an object, that object is first deleted before taking ownership of
the new object.
</p>
<p>
<span class="bold"><strong>Boost.Interprocess</strong></span> also offers auxiliary
types to easily define and construct unique pointers that can be placed in
managed segments and will correctly delete owned object from the segment:
<code class="computeroutput"><a class="link" href="../boost/interprocess/managed_unique_ptr.html" title="Struct template managed_unique_ptr">managed_unique_ptr</a></code>
and <code class="computeroutput"><a class="link" href="../boost/interprocess/make_managed_unique_ptr.html" title="Function template make_managed_unique_ptr">make_managed_unique_ptr</a></code>
utilities.
</p>
<p>
Here we see an example of the use <code class="computeroutput"><span class="identifier">unique_ptr</span></code>
including creating containers of such objects:
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">smart_ptr</span><span class="special">/</span><span class="identifier">unique_ptr</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">vector</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cassert</span><span class="special">&gt;</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">//This is type of the object we'll allocate dynamically</span>
<span class="keyword">struct</span> <span class="identifier">MyType</span>
<span class="special">{</span>
<span class="identifier">MyType</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">number</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span>
<span class="special">:</span> <span class="identifier">number_</span><span class="special">(</span><span class="identifier">number</span><span class="special">)</span>
<span class="special">{}</span>
<span class="keyword">int</span> <span class="identifier">number_</span><span class="special">;</span>
<span class="special">};</span>
<span class="comment">//This is the type of a unique pointer to the previous type</span>
<span class="comment">//that will be built in the mapped file</span>
<span class="keyword">typedef</span> <span class="identifier">managed_unique_ptr</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">,</span> <span class="identifier">managed_mapped_file</span><span class="special">&gt;::</span><span class="identifier">type</span> <span class="identifier">unique_ptr_type</span><span class="special">;</span>
<span class="comment">//Define containers of unique pointer. Unique pointer simplifies object management</span>
<span class="keyword">typedef</span> <span class="identifier">vector</span>
<span class="special">&lt;</span> <span class="identifier">unique_ptr_type</span>
<span class="special">,</span> <span class="identifier">allocator</span><span class="special">&lt;</span><span class="identifier">unique_ptr_type</span><span class="special">,</span> <span class="identifier">managed_mapped_file</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">&gt;</span>
<span class="special">&gt;</span> <span class="identifier">unique_ptr_vector_t</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">list</span>
<span class="special">&lt;</span> <span class="identifier">unique_ptr_type</span>
<span class="special">,</span> <span class="identifier">allocator</span><span class="special">&lt;</span><span class="identifier">unique_ptr_type</span><span class="special">,</span> <span class="identifier">managed_mapped_file</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">&gt;</span>
<span class="special">&gt;</span> <span class="identifier">unique_ptr_list_t</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">//Define file names</span>
<span class="keyword">const</span> <span class="keyword">char</span> <span class="special">*</span><span class="identifier">MappedFile</span> <span class="special">=</span> <span class="string">"MyMappedFile"</span><span class="special">;</span>
<span class="comment">//Destroy any previous file with the name to be used.</span>
<span class="keyword">struct</span> <span class="identifier">file_remove</span>
<span class="special">{</span>
<span class="identifier">file_remove</span><span class="special">(</span><span class="keyword">const</span> <span class="keyword">char</span> <span class="special">*</span><span class="identifier">MappedFile</span><span class="special">)</span>
<span class="special">:</span> <span class="identifier">MappedFile_</span><span class="special">(</span><span class="identifier">MappedFile</span><span class="special">)</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">MappedFile_</span><span class="special">);</span> <span class="special">}</span>
<span class="special">~</span><span class="identifier">file_remove</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">MappedFile_</span><span class="special">);</span> <span class="special">}</span>
<span class="keyword">const</span> <span class="keyword">char</span> <span class="special">*</span><span class="identifier">MappedFile_</span><span class="special">;</span>
<span class="special">}</span> <span class="identifier">remover</span><span class="special">(</span><span class="identifier">MappedFile</span><span class="special">);</span>
<span class="special">{</span>
<span class="identifier">managed_mapped_file</span> <span class="identifier">file</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> <span class="identifier">MappedFile</span><span class="special">,</span> <span class="number">65536</span><span class="special">);</span>
<span class="comment">//Construct an object in the file and</span>
<span class="comment">//pass ownership to this local unique pointer</span>
<span class="identifier">unique_ptr_type</span> <span class="identifier">local_unique_ptr</span> <span class="special">(</span><span class="identifier">make_managed_unique_ptr</span>
<span class="special">(</span><span class="identifier">file</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">&gt;(</span><span class="string">"unique object"</span><span class="special">)(),</span> <span class="identifier">file</span><span class="special">));</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">local_unique_ptr</span><span class="special">.</span><span class="identifier">get</span><span class="special">()</span> <span class="special">!=</span> <span class="number">0</span><span class="special">);</span>
<span class="comment">//Reset the unique pointer. The object is automatically destroyed</span>
<span class="identifier">local_unique_ptr</span><span class="special">.</span><span class="identifier">reset</span><span class="special">();</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">file</span><span class="special">.</span><span class="identifier">find</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">&gt;(</span><span class="string">"unique object"</span><span class="special">).</span><span class="identifier">first</span> <span class="special">==</span> <span class="number">0</span><span class="special">);</span>
<span class="comment">//Now create a vector of unique pointers</span>
<span class="identifier">unique_ptr_vector_t</span> <span class="special">*</span><span class="identifier">unique_vector</span> <span class="special">=</span>
<span class="identifier">file</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">unique_ptr_vector_t</span><span class="special">&gt;(</span><span class="string">"unique vector"</span><span class="special">)(</span><span class="identifier">file</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span>
<span class="comment">//Speed optimization</span>
<span class="identifier">unique_vector</span><span class="special">-&gt;</span><span class="identifier">reserve</span><span class="special">(</span><span class="number">100</span><span class="special">);</span>
<span class="comment">//Now insert all values</span>
<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="number">100</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
<span class="identifier">unique_ptr_type</span> <span class="identifier">p</span><span class="special">(</span><span class="identifier">make_managed_unique_ptr</span><span class="special">(</span><span class="identifier">file</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">&gt;(</span><span class="identifier">anonymous_instance</span><span class="special">)(</span><span class="identifier">i</span><span class="special">),</span> <span class="identifier">file</span><span class="special">));</span>
<span class="identifier">unique_vector</span><span class="special">-&gt;</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">p</span><span class="special">));</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">unique_vector</span><span class="special">-&gt;</span><span class="identifier">back</span><span class="special">()-&gt;</span><span class="identifier">number_</span> <span class="special">==</span> <span class="identifier">i</span><span class="special">);</span>
<span class="special">}</span>
<span class="comment">//Now create a list of unique pointers</span>
<span class="identifier">unique_ptr_list_t</span> <span class="special">*</span><span class="identifier">unique_list</span> <span class="special">=</span>
<span class="identifier">file</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">unique_ptr_list_t</span><span class="special">&gt;(</span><span class="string">"unique list"</span><span class="special">)(</span><span class="identifier">file</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span>
<span class="comment">//Pass ownership of all values to the list</span>
<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">99</span><span class="special">;</span> <span class="special">!</span><span class="identifier">unique_vector</span><span class="special">-&gt;</span><span class="identifier">empty</span><span class="special">();</span> <span class="special">--</span><span class="identifier">i</span><span class="special">){</span>
<span class="identifier">unique_list</span><span class="special">-&gt;</span><span class="identifier">push_front</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">unique_vector</span><span class="special">-&gt;</span><span class="identifier">back</span><span class="special">()));</span>
<span class="comment">//The unique ptr of the vector is now empty...</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">unique_vector</span><span class="special">-&gt;</span><span class="identifier">back</span><span class="special">()</span> <span class="special">==</span> <span class="number">0</span><span class="special">);</span>
<span class="identifier">unique_vector</span><span class="special">-&gt;</span><span class="identifier">pop_back</span><span class="special">();</span>
<span class="comment">//...and the list has taken ownership of the value</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">unique_list</span><span class="special">-&gt;</span><span class="identifier">front</span><span class="special">()</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">unique_list</span><span class="special">-&gt;</span><span class="identifier">front</span><span class="special">()-&gt;</span><span class="identifier">number_</span> <span class="special">==</span> <span class="identifier">i</span><span class="special">);</span>
<span class="special">}</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">unique_list</span><span class="special">-&gt;</span><span class="identifier">size</span><span class="special">()</span> <span class="special">==</span> <span class="number">100</span><span class="special">);</span>
<span class="comment">//Now destroy the empty vector.</span>
<span class="identifier">file</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">unique_vector</span><span class="special">);</span>
<span class="comment">//The mapped file is unmapped here. Objects have been flushed to disk</span>
<span class="special">}</span>
<span class="special">{</span>
<span class="comment">//Reopen the mapped file and find again the list</span>
<span class="identifier">managed_mapped_file</span> <span class="identifier">file</span><span class="special">(</span><span class="identifier">open_only</span><span class="special">,</span> <span class="identifier">MappedFile</span><span class="special">);</span>
<span class="identifier">unique_ptr_list_t</span> <span class="special">*</span><span class="identifier">unique_list</span> <span class="special">=</span>
<span class="identifier">file</span><span class="special">.</span><span class="identifier">find</span><span class="special">&lt;</span><span class="identifier">unique_ptr_list_t</span><span class="special">&gt;(</span><span class="string">"unique list"</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">unique_list</span><span class="special">);</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">unique_list</span><span class="special">-&gt;</span><span class="identifier">size</span><span class="special">()</span> <span class="special">==</span> <span class="number">100</span><span class="special">);</span>
<span class="identifier">unique_ptr_list_t</span><span class="special">::</span><span class="identifier">const_iterator</span> <span class="identifier">list_it</span> <span class="special">=</span> <span class="identifier">unique_list</span><span class="special">-&gt;</span><span class="identifier">begin</span><span class="special">();</span>
<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="number">100</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">,</span> <span class="special">++</span><span class="identifier">list_it</span><span class="special">){</span>
<span class="identifier">assert</span><span class="special">((*</span><span class="identifier">list_it</span><span class="special">)-&gt;</span><span class="identifier">number_</span> <span class="special">==</span> <span class="identifier">i</span><span class="special">);</span>
<span class="special">}</span>
<span class="comment">//Now destroy the list. All elements will be automatically deallocated.</span>
<span class="identifier">file</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">unique_list</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>
<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="streams.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="architecture.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,175 @@
<!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>Memory allocation algorithms</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="allocators_containers.html" title="Allocators, containers and memory allocation algorithms">
<link rel="next" href="streams.html" title="Direct iostream formatting: vectorstream and bufferstream">
</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="allocators_containers.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="streams.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.memory_algorithms"></a><a class="link" href="memory_algorithms.html" title="Memory allocation algorithms">Memory allocation algorithms</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="memory_algorithms.html#interprocess.memory_algorithms.simple_seq_fit">simple_seq_fit:
A simple shared memory management algorithm</a></span></dt>
<dt><span class="section"><a href="memory_algorithms.html#interprocess.memory_algorithms.rbtree_best_fit">rbtree_best_fit:
Best-fit logarithmic-time complexity allocation</a></span></dt>
</dl></div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.memory_algorithms.simple_seq_fit"></a><a class="link" href="memory_algorithms.html#interprocess.memory_algorithms.simple_seq_fit" title="simple_seq_fit: A simple shared memory management algorithm">simple_seq_fit:
A simple shared memory management algorithm</a>
</h3></div></div></div>
<p>
The algorithm is a variation of sequential fit using singly linked list of
free memory buffers. The algorithm is based on the article about shared memory
titled <a href="http://home.earthlink.net/~joshwalker1/writing/SharedMemory.html" target="_top"><span class="emphasis"><em>"Taming
Shared Memory"</em></span> </a>. The algorithm is as follows:
</p>
<p>
The shared memory is divided in blocks of free shared memory, each one with
some control data and several bytes of memory ready to be used. The control
data contains a pointer (in our case offset_ptr) to the next free block and
the size of the block. The allocator consists of a singly linked list of
free blocks, ordered by address. The last block, points always to the first
block:
</p>
<pre class="programlisting"><span class="identifier">simple_seq_fit</span> <span class="identifier">memory</span> <span class="identifier">layout</span><span class="special">:</span>
<span class="identifier">main</span> <span class="identifier">extra</span> <span class="identifier">allocated</span> <span class="identifier">free_block_1</span> <span class="identifier">allocated</span> <span class="identifier">free_block_2</span> <span class="identifier">allocated</span> <span class="identifier">free_block_3</span>
<span class="identifier">header</span> <span class="identifier">header</span> <span class="identifier">block</span> <span class="identifier">ctrl</span> <span class="identifier">usr</span> <span class="identifier">block</span> <span class="identifier">ctrl</span> <span class="identifier">usr</span> <span class="identifier">block</span> <span class="identifier">ctrl</span> <span class="identifier">usr</span>
<span class="identifier">_________</span> <span class="identifier">_____</span> <span class="identifier">_________</span> <span class="identifier">_______________</span> <span class="identifier">_________</span> <span class="identifier">_______________</span> <span class="identifier">_________</span> <span class="identifier">_______________</span>
<span class="special">|</span> <span class="special">||</span> <span class="special">||</span> <span class="special">||</span> <span class="special">|</span> <span class="special">||</span> <span class="special">||</span> <span class="special">|</span> <span class="special">||</span> <span class="special">||</span> <span class="special">|</span> <span class="special">|</span>
<span class="special">|</span><span class="identifier">free</span><span class="special">|</span><span class="identifier">ctrl</span><span class="special">||</span><span class="identifier">extra</span><span class="special">||</span> <span class="special">||</span><span class="identifier">next</span><span class="special">|</span><span class="identifier">size</span><span class="special">|</span> <span class="identifier">mem</span> <span class="special">||</span> <span class="special">||</span><span class="identifier">next</span><span class="special">|</span><span class="identifier">size</span><span class="special">|</span> <span class="identifier">mem</span> <span class="special">||</span> <span class="special">||</span><span class="identifier">next</span><span class="special">|</span><span class="identifier">size</span><span class="special">|</span> <span class="identifier">mem</span> <span class="special">|</span>
<span class="special">|</span><span class="identifier">_________</span><span class="special">||</span><span class="identifier">_____</span><span class="special">||</span><span class="identifier">_________</span><span class="special">||</span><span class="identifier">_________</span><span class="special">|</span><span class="identifier">_____</span><span class="special">||</span><span class="identifier">_________</span><span class="special">||</span><span class="identifier">_________</span><span class="special">|</span><span class="identifier">_____</span><span class="special">||</span><span class="identifier">_________</span><span class="special">||</span><span class="identifier">_________</span><span class="special">|</span><span class="identifier">_____</span><span class="special">|</span>
<span class="special">|</span> <span class="special">|</span> <span class="special">|</span> <span class="special">|</span> <span class="special">|</span> <span class="special">|</span> <span class="special">|</span>
<span class="special">|</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">|</span> <span class="special">|</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">|</span> <span class="special">|</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">&gt;</span><span class="identifier">_</span><span class="special">|</span> <span class="special">|</span>
<span class="special">|</span> <span class="special">|</span>
<span class="special">|</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">_</span><span class="special">&lt;</span><span class="identifier">__</span><span class="special">|</span>
</pre>
<p>
When a user requests N bytes of memory, the allocator traverses the free
block list looking for a block large enough. If the "mem" part
of the block has the same size as the requested memory, we erase the block
from the list and return a pointer to the "mem" part of the block.
If the "mem" part size is bigger than needed, we split the block
in two blocks, one of the requested size and the other with remaining size.
Now, we take the block with the exact size, erase it from list and give it
to the user.
</p>
<p>
When the user deallocates a block, we traverse the list (remember that the
list is ordered), and search its place depending on the block address. Once
found, we try to merge the block with adjacent blocks if possible.
</p>
<p>
To ease implementation, the size of the free memory block is measured in
multiples of "basic_size" bytes. The basic size will be the size
of the control block aligned to machine most restrictive alignment.
</p>
<p>
This algorithm is a low size overhead algorithm suitable for simple allocation
schemes. This algorithm should only be used when size is a major concern,
because the performance of this algorithm suffers when the memory is fragmented.
This algorithm has linear allocation and deallocation time, so when the number
of allocations is high, the user should use a more performance-friendly algorithm.
</p>
<p>
In most 32 bit systems, with 8 byte alignment, "basic_size" is
8 bytes. This means that an allocation request of 1 byte leads to the creation
of a 16 byte block, where 8 bytes are available to the user. The allocation
of 8 bytes leads also to the same 16 byte block.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.memory_algorithms.rbtree_best_fit"></a><a class="link" href="memory_algorithms.html#interprocess.memory_algorithms.rbtree_best_fit" title="rbtree_best_fit: Best-fit logarithmic-time complexity allocation">rbtree_best_fit:
Best-fit logarithmic-time complexity allocation</a>
</h3></div></div></div>
<p>
This algorithm is an advanced algorithm using red-black trees to sort the
free portions of the memory segment by size. This allows logarithmic complexity
allocation. Apart from this, a doubly-linked list of all portions of memory
(free and allocated) is maintained to allow constant-time access to previous
and next blocks when doing merging operations.
</p>
<p>
The data used to create the red-black tree of free nodes is overwritten by
the user since it's no longer used once the memory is allocated. This maintains
the memory size overhead down to the doubly linked list overhead, which is
pretty small (two pointers). Basically this is the scheme:
</p>
<pre class="programlisting"><span class="identifier">rbtree_best_fit</span> <span class="identifier">memory</span> <span class="identifier">layout</span><span class="special">:</span>
<span class="identifier">main</span> <span class="identifier">allocated</span> <span class="identifier">block</span> <span class="identifier">free</span> <span class="identifier">block</span> <span class="identifier">allocated</span> <span class="identifier">block</span> <span class="identifier">free</span> <span class="identifier">block</span>
<span class="identifier">header</span>
<span class="identifier">_______________</span> <span class="identifier">_______________</span> <span class="identifier">_________________________________</span> <span class="identifier">_______________</span> <span class="identifier">_________________________________</span>
<span class="special">|</span> <span class="special">||</span> <span class="special">|</span> <span class="special">||</span> <span class="special">|</span> <span class="special">|</span> <span class="special">||</span> <span class="special">|</span> <span class="special">||</span> <span class="special">|</span> <span class="special">|</span> <span class="special">|</span>
<span class="special">|</span> <span class="identifier">main</span> <span class="identifier">header</span> <span class="special">||</span><span class="identifier">next</span><span class="special">|</span><span class="identifier">prev</span><span class="special">|</span> <span class="identifier">mem</span> <span class="special">||</span><span class="identifier">next</span><span class="special">|</span><span class="identifier">prev</span><span class="special">|</span><span class="identifier">left</span><span class="special">|</span><span class="identifier">right</span><span class="special">|</span><span class="identifier">parent</span><span class="special">|</span> <span class="identifier">mem</span> <span class="special">||</span><span class="identifier">next</span><span class="special">|</span><span class="identifier">prev</span><span class="special">|</span> <span class="identifier">mem</span> <span class="special">||</span><span class="identifier">next</span><span class="special">|</span><span class="identifier">prev</span><span class="special">|</span><span class="identifier">left</span><span class="special">|</span><span class="identifier">right</span><span class="special">|</span><span class="identifier">parent</span><span class="special">|</span> <span class="identifier">mem</span> <span class="special">|</span>
<span class="special">|</span><span class="identifier">_______________</span><span class="special">||</span><span class="identifier">_________</span><span class="special">|</span><span class="identifier">_____</span><span class="special">||</span><span class="identifier">_________</span><span class="special">|</span><span class="identifier">_________________</span><span class="special">|</span><span class="identifier">_____</span><span class="special">||</span><span class="identifier">_________</span><span class="special">|</span><span class="identifier">_____</span><span class="special">||</span><span class="identifier">_________</span><span class="special">|</span><span class="identifier">_________________</span><span class="special">|</span><span class="identifier">_____</span><span class="special">|</span>
</pre>
<p>
This allocation algorithm is pretty fast and scales well with big shared
memory segments and big number of allocations. To form a block a minimum
memory size is needed: the sum of the doubly linked list and the red-black
tree control data. The size of a block is measured in multiples of the most
restrictive alignment value.
</p>
<p>
In most 32 bit systems with 8 byte alignment the minimum size of a block
is 24 byte. When a block is allocated the control data related to the red
black tree is overwritten by the user (because it's only needed for free
blocks).
</p>
<p>
In those systems a 1 byte allocation request means that:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
24 bytes of memory from the segment are used to form a block.
</li>
<li class="listitem">
16 bytes of them are usable for the user.
</li>
</ul></div>
<p>
For really small allocations (&lt;= 8 bytes), this algorithm wastes more
memory than the simple sequential fit algorithm (8 bytes more). For allocations
bigger than 8 bytes the memory overhead is exactly the same. This is the
default allocation algorithm in <span class="bold"><strong>Boost.Interprocess</strong></span>
managed memory segments.
</p>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2005-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="allocators_containers.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="streams.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,163 @@
<!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>Mapping Address Independent Pointer: offset_ptr</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="sharedmemorybetweenprocesses.html" title="Sharing memory between processes">
<link rel="next" href="synchronization_mechanisms.html" title="Synchronization mechanisms">
</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="sharedmemorybetweenprocesses.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="synchronization_mechanisms.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.offset_ptr"></a><a class="link" href="offset_ptr.html" title="Mapping Address Independent Pointer: offset_ptr">Mapping Address Independent Pointer:
offset_ptr</a>
</h2></div></div></div>
<p>
When creating shared memory and memory mapped files to communicate two processes
the memory segment can be mapped in a different address in each process:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span><span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">shared_memory_object</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="comment">// ...</span>
<span class="keyword">using</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span>
<span class="comment">//Open a shared memory segment</span>
<span class="identifier">shared_memory_object</span> <span class="identifier">shm_obj</span>
<span class="special">(</span><span class="identifier">open_only</span> <span class="comment">//open or create</span>
<span class="special">,</span><span class="string">"shared_memory"</span> <span class="comment">//name</span>
<span class="special">,</span><span class="identifier">read_only</span> <span class="comment">//read-only mode</span>
<span class="special">);</span>
<span class="comment">//Map the whole shared memory</span>
<span class="identifier">mapped_region</span> <span class="identifier">region</span>
<span class="special">(</span> <span class="identifier">shm</span> <span class="comment">//Memory-mappable object</span>
<span class="special">,</span> <span class="identifier">read_write</span> <span class="comment">//Access mode</span>
<span class="special">);</span>
<span class="comment">//This address can be different in each process</span>
<span class="keyword">void</span> <span class="special">*</span><span class="identifier">addr</span> <span class="special">=</span> <span class="identifier">region</span><span class="special">.</span><span class="identifier">get_address</span><span class="special">();</span>
</pre>
<p>
This makes the creation of complex objects in mapped regions difficult: a C++
class instance placed in a mapped region might have a pointer pointing to another
object also placed in the mapped region. Since the pointer stores an absolute
address, that address is only valid for the process that placed the object
there unless all processes map the mapped region in the same address.
</p>
<p>
To be able to simulate pointers in mapped regions, users must use <span class="bold"><strong>offsets</strong></span> (distance between objects) instead of absolute
addresses. The offset between two objects in a mapped region is the same for
any process that maps the mapped region, even if that region is placed in different
base addresses. To facilitate the use of offsets, <span class="bold"><strong>Boost.Interprocess</strong></span>
offers <code class="computeroutput"><a class="link" href="../boost/interprocess/offset_ptr.html" title="Class template offset_ptr">offset_ptr</a></code>.
</p>
<p>
<code class="computeroutput"><a class="link" href="../boost/interprocess/offset_ptr.html" title="Class template offset_ptr">offset_ptr</a></code> wraps
all the background operations needed to offer a pointer-like interface. The
class interface is inspired in Boost Smart Pointers and this smart pointer
stores the offset (distance in bytes) between the pointee's address and it's
own <code class="computeroutput"><span class="keyword">this</span></code> pointer. Imagine a structure
in a common 32 bit processor:
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">structure</span>
<span class="special">{</span>
<span class="keyword">int</span> <span class="identifier">integer1</span><span class="special">;</span> <span class="comment">//The compiler places this at offset 0 in the structure</span>
<span class="identifier">offset_ptr</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">ptr</span><span class="special">;</span> <span class="comment">//The compiler places this at offset 4 in the structure</span>
<span class="keyword">int</span> <span class="identifier">integer2</span><span class="special">;</span> <span class="comment">//The compiler places this at offset 8 in the structure</span>
<span class="special">};</span>
<span class="comment">//...</span>
<span class="identifier">structure</span> <span class="identifier">s</span><span class="special">;</span>
<span class="comment">//Assign the address of "integer1" to "ptr".</span>
<span class="comment">//"ptr" will store internally "-4":</span>
<span class="comment">// (char*)&amp;s.integer1 - (char*)&amp;s.ptr;</span>
<span class="identifier">s</span><span class="special">.</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">s</span><span class="special">.</span><span class="identifier">integer1</span><span class="special">;</span>
<span class="comment">//Assign the address of "integer2" to "ptr".</span>
<span class="comment">//"ptr" will store internally "4":</span>
<span class="comment">// (char*)&amp;s.integer2 - (char*)&amp;s.ptr;</span>
<span class="identifier">s</span><span class="special">.</span><span class="identifier">ptr</span> <span class="special">=</span> <span class="special">&amp;</span><span class="identifier">s</span><span class="special">.</span><span class="identifier">integer2</span><span class="special">;</span>
</pre>
<p>
One of the big problems of <code class="computeroutput"><span class="identifier">offset_ptr</span></code>
is the representation of the null pointer. The null pointer can't be safely
represented like an offset, since the absolute address 0 is always outside
of the mapped region. Due to the fact that the segment can be mapped in a different
base address in each process the distance between the address 0 and <code class="computeroutput"><span class="identifier">offset_ptr</span></code> is different for every process.
</p>
<p>
Some implementations choose the offset 0 (that is, an <code class="computeroutput"><span class="identifier">offset_ptr</span></code>
pointing to itself) as the null pointer pointer representation but this is
not valid for many use cases since many times structures like linked lists
or nodes from STL containers point to themselves (the end node in an empty
container, for example) and 0 offset value is needed. An alternative is to
store, in addition to the offset, a boolean to indicate if the pointer is null.
However, this increments the size of the pointer and hurts performance.
</p>
<p>
In consequence, <code class="computeroutput"><a class="link" href="../boost/interprocess/offset_ptr.html" title="Class template offset_ptr">offset_ptr</a></code>
defines offset 1 as the null pointer, meaning that this class <span class="bold"><strong>can't</strong></span>
point to the byte after its own <span class="emphasis"><em>this</em></span> pointer:
</p>
<pre class="programlisting"><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="identifier">offset_ptr</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">&gt;</span> <span class="identifier">ptr</span><span class="special">;</span>
<span class="comment">//Pointing to the next byte of it's own address</span>
<span class="comment">//marks the smart pointer as null.</span>
<span class="identifier">ptr</span> <span class="special">=</span> <span class="special">(</span><span class="keyword">char</span><span class="special">*)&amp;</span><span class="identifier">ptr</span> <span class="special">+</span> <span class="number">1</span><span class="special">;</span>
<span class="comment">//ptr is equal to null</span>
<span class="identifier">assert</span><span class="special">(!</span><span class="identifier">ptr</span><span class="special">);</span>
<span class="comment">//This is the same as assigning the null value...</span>
<span class="identifier">ptr</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
<span class="comment">//ptr is also equal to null</span>
<span class="identifier">assert</span><span class="special">(!</span><span class="identifier">ptr</span><span class="special">);</span>
</pre>
<p>
In practice, this limitation is not important, since a user almost never wants
to point to this address.
</p>
<p>
<code class="computeroutput"><a class="link" href="../boost/interprocess/offset_ptr.html" title="Class template offset_ptr">offset_ptr</a></code> offers
all pointer-like operations and random_access_iterator typedefs, so it can
be used in STL algorithms requiring random access iterators and detected via
traits. For more information about the members and operations of the class,
see <code class="computeroutput"><a class="link" href="../boost/interprocess/offset_ptr.html" title="Class template offset_ptr">offset_ptr reference</a></code>.
</p>
</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="sharedmemorybetweenprocesses.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="synchronization_mechanisms.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,487 @@
<!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>Quick Guide for the Impatient</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="../interprocess.html" title="Chapter 18. Boost.Interprocess">
<link rel="next" href="some_basic_explanations.html" title="Some basic explanations">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td>
<td align="center"><a href="../../../index.html">Home</a></td>
<td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../interprocess.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="some_basic_explanations.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.quick_guide"></a><a class="link" href="quick_guide.html" title="Quick Guide for the Impatient">Quick Guide for the Impatient</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="quick_guide.html#interprocess.quick_guide.qg_memory_pool">Using shared
memory as a pool of unnamed memory blocks</a></span></dt>
<dt><span class="section"><a href="quick_guide.html#interprocess.quick_guide.qg_named_interprocess">Creating
named shared memory objects</a></span></dt>
<dt><span class="section"><a href="quick_guide.html#interprocess.quick_guide.qg_offset_ptr">Using an offset
smart pointer for shared memory</a></span></dt>
<dt><span class="section"><a href="quick_guide.html#interprocess.quick_guide.qg_interprocess_container">Creating
vectors in shared memory</a></span></dt>
<dt><span class="section"><a href="quick_guide.html#interprocess.quick_guide.qg_interprocess_map">Creating
maps in shared memory</a></span></dt>
</dl></div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.quick_guide.qg_memory_pool"></a><a class="link" href="quick_guide.html#interprocess.quick_guide.qg_memory_pool" title="Using shared memory as a pool of unnamed memory blocks">Using shared
memory as a pool of unnamed memory blocks</a>
</h3></div></div></div>
<p>
You can just allocate a portion of a shared memory segment, copy the message
to that buffer, send the offset of that portion of shared memory to another
process, and you are done. Let's see the example:
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cstdlib</span><span class="special">&gt;</span> <span class="comment">//std::system</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">sstream</span><span class="special">&gt;</span>
<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">(</span><span class="keyword">int</span> <span class="identifier">argc</span><span class="special">,</span> <span class="keyword">char</span> <span class="special">*</span><span class="identifier">argv</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">if</span><span class="special">(</span><span class="identifier">argc</span> <span class="special">==</span> <span class="number">1</span><span class="special">){</span> <span class="comment">//Parent process</span>
<span class="comment">//Remove shared memory on construction and destruction</span>
<span class="keyword">struct</span> <span class="identifier">shm_remove</span>
<span class="special">{</span>
<span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span>
<span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span>
<span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span>
<span class="comment">//Create a managed shared memory segment</span>
<span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> <span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="number">65536</span><span class="special">);</span>
<span class="comment">//Allocate a portion of the segment (raw memory)</span>
<span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">size_type</span> <span class="identifier">free_memory</span> <span class="special">=</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_free_memory</span><span class="special">();</span>
<span class="keyword">void</span> <span class="special">*</span> <span class="identifier">shptr</span> <span class="special">=</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">allocate</span><span class="special">(</span><span class="number">1024</span><span class="comment">/*bytes to allocate*/</span><span class="special">);</span>
<span class="comment">//Check invariant</span>
<span class="keyword">if</span><span class="special">(</span><span class="identifier">free_memory</span> <span class="special">&lt;=</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_free_memory</span><span class="special">())</span>
<span class="keyword">return</span> <span class="number">1</span><span class="special">;</span>
<span class="comment">//An handle from the base address can identify any byte of the shared</span>
<span class="comment">//memory segment even if it is mapped in different base addresses</span>
<span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">handle_t</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">shptr</span><span class="special">);</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">stringstream</span> <span class="identifier">s</span><span class="special">;</span>
<span class="identifier">s</span> <span class="special">&lt;&lt;</span> <span class="identifier">argv</span><span class="special">[</span><span class="number">0</span><span class="special">]</span> <span class="special">&lt;&lt;</span> <span class="string">" "</span> <span class="special">&lt;&lt;</span> <span class="identifier">handle</span><span class="special">;</span>
<span class="identifier">s</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ends</span><span class="special">;</span>
<span class="comment">//Launch child process</span>
<span class="keyword">if</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">system</span><span class="special">(</span><span class="identifier">s</span><span class="special">.</span><span class="identifier">str</span><span class="special">().</span><span class="identifier">c_str</span><span class="special">()))</span>
<span class="keyword">return</span> <span class="number">1</span><span class="special">;</span>
<span class="comment">//Check memory has been freed</span>
<span class="keyword">if</span><span class="special">(</span><span class="identifier">free_memory</span> <span class="special">!=</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_free_memory</span><span class="special">())</span>
<span class="keyword">return</span> <span class="number">1</span><span class="special">;</span>
<span class="special">}</span>
<span class="keyword">else</span><span class="special">{</span>
<span class="comment">//Open managed segment</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="comment">//An handle from the base address can identify any byte of the shared</span>
<span class="comment">//memory segment even if it is mapped in different base addresses</span>
<span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">handle_t</span> <span class="identifier">handle</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
<span class="comment">//Obtain handle value</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">stringstream</span> <span class="identifier">s</span><span class="special">;</span> <span class="identifier">s</span> <span class="special">&lt;&lt;</span> <span class="identifier">argv</span><span class="special">[</span><span class="number">1</span><span class="special">];</span> <span class="identifier">s</span> <span class="special">&gt;&gt;</span> <span class="identifier">handle</span><span class="special">;</span>
<span class="comment">//Get buffer local address from handle</span>
<span class="keyword">void</span> <span class="special">*</span><span class="identifier">msg</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>
<span class="comment">//Deallocate previously allocated memory</span>
<span class="identifier">segment</span><span class="special">.</span><span class="identifier">deallocate</span><span class="special">(</span><span class="identifier">msg</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.quick_guide.qg_named_interprocess"></a><a class="link" href="quick_guide.html#interprocess.quick_guide.qg_named_interprocess" title="Creating named shared memory objects">Creating
named shared memory objects</a>
</h3></div></div></div>
<p>
You want to create objects in a shared memory segment, giving a string name
to them so that any other process can find, use and delete them from the
segment when the objects are not needed anymore. Example:
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cstdlib</span><span class="special">&gt;</span> <span class="comment">//std::system</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cstddef</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cassert</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">utility</span><span class="special">&gt;</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">argc</span><span class="special">,</span> <span class="keyword">char</span> <span class="special">*</span><span class="identifier">argv</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">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">,</span> <span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">MyType</span><span class="special">;</span>
<span class="keyword">if</span><span class="special">(</span><span class="identifier">argc</span> <span class="special">==</span> <span class="number">1</span><span class="special">){</span> <span class="comment">//Parent process</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">//Construct managed shared memory</span>
<span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> <span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="number">65536</span><span class="special">);</span>
<span class="comment">//Create an object of MyType initialized to {0.0, 0}</span>
<span class="identifier">MyType</span> <span class="special">*</span><span class="identifier">instance</span> <span class="special">=</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">&gt;</span>
<span class="special">(</span><span class="string">"MyType instance"</span><span class="special">)</span> <span class="comment">//name of the object</span>
<span class="special">(</span><span class="number">0.0</span><span class="special">,</span> <span class="number">0</span><span class="special">);</span> <span class="comment">//ctor first argument</span>
<span class="comment">//Create an array of 10 elements of MyType initialized to {0.0, 0}</span>
<span class="identifier">MyType</span> <span class="special">*</span><span class="identifier">array</span> <span class="special">=</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">&gt;</span>
<span class="special">(</span><span class="string">"MyType array"</span><span class="special">)</span> <span class="comment">//name of the object</span>
<span class="special">[</span><span class="number">10</span><span class="special">]</span> <span class="comment">//number of elements</span>
<span class="special">(</span><span class="number">0.0</span><span class="special">,</span> <span class="number">0</span><span class="special">);</span> <span class="comment">//Same two ctor arguments for all objects</span>
<span class="comment">//Create an array of 3 elements of MyType initializing each one</span>
<span class="comment">//to a different value {0.0, 0}, {1.0, 1}, {2.0, 2}...</span>
<span class="keyword">float</span> <span class="identifier">float_initializer</span><span class="special">[</span><span class="number">3</span><span class="special">]</span> <span class="special">=</span> <span class="special">{</span> <span class="number">0.0</span><span class="special">,</span> <span class="number">1.0</span><span class="special">,</span> <span class="number">2.0</span> <span class="special">};</span>
<span class="keyword">int</span> <span class="identifier">int_initializer</span><span class="special">[</span><span class="number">3</span><span class="special">]</span> <span class="special">=</span> <span class="special">{</span> <span class="number">0</span><span class="special">,</span> <span class="number">1</span><span class="special">,</span> <span class="number">2</span> <span class="special">};</span>
<span class="identifier">MyType</span> <span class="special">*</span><span class="identifier">array_it</span> <span class="special">=</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">construct_it</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">&gt;</span>
<span class="special">(</span><span class="string">"MyType array from it"</span><span class="special">)</span> <span class="comment">//name of the object</span>
<span class="special">[</span><span class="number">3</span><span class="special">]</span> <span class="comment">//number of elements</span>
<span class="special">(</span> <span class="special">&amp;</span><span class="identifier">float_initializer</span><span class="special">[</span><span class="number">0</span><span class="special">]</span> <span class="comment">//Iterator for the 1st ctor argument</span>
<span class="special">,</span> <span class="special">&amp;</span><span class="identifier">int_initializer</span><span class="special">[</span><span class="number">0</span><span class="special">]);</span> <span class="comment">//Iterator for the 2nd ctor argument</span>
<span class="comment">//Launch child process</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">s</span><span class="special">(</span><span class="identifier">argv</span><span class="special">[</span><span class="number">0</span><span class="special">]);</span> <span class="identifier">s</span> <span class="special">+=</span> <span class="string">" child "</span><span class="special">;</span>
<span class="keyword">if</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">system</span><span class="special">(</span><span class="identifier">s</span><span class="special">.</span><span class="identifier">c_str</span><span class="special">()))</span>
<span class="keyword">return</span> <span class="number">1</span><span class="special">;</span>
<span class="comment">//Check child has destroyed all objects</span>
<span class="keyword">if</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">find</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">&gt;(</span><span class="string">"MyType array"</span><span class="special">).</span><span class="identifier">first</span> <span class="special">||</span>
<span class="identifier">segment</span><span class="special">.</span><span class="identifier">find</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">&gt;(</span><span class="string">"MyType instance"</span><span class="special">).</span><span class="identifier">first</span> <span class="special">||</span>
<span class="identifier">segment</span><span class="special">.</span><span class="identifier">find</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">&gt;(</span><span class="string">"MyType array from it"</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="special">}</span>
<span class="keyword">else</span><span class="special">{</span>
<span class="comment">//Open managed shared memory</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">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">*,</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">size_type</span><span class="special">&gt;</span> <span class="identifier">res</span><span class="special">;</span>
<span class="comment">//Find the array</span>
<span class="identifier">res</span> <span class="special">=</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">find</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">&gt;</span> <span class="special">(</span><span class="string">"MyType array"</span><span class="special">);</span>
<span class="comment">//Length should be 10</span>
<span class="keyword">if</span><span class="special">(</span><span class="identifier">res</span><span class="special">.</span><span class="identifier">second</span> <span class="special">!=</span> <span class="number">10</span><span class="special">)</span> <span class="keyword">return</span> <span class="number">1</span><span class="special">;</span>
<span class="comment">//Find the object</span>
<span class="identifier">res</span> <span class="special">=</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">find</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">&gt;</span> <span class="special">(</span><span class="string">"MyType instance"</span><span class="special">);</span>
<span class="comment">//Length should be 1</span>
<span class="keyword">if</span><span class="special">(</span><span class="identifier">res</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="number">1</span><span class="special">;</span>
<span class="comment">//Find the array constructed from iterators</span>
<span class="identifier">res</span> <span class="special">=</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">find</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">&gt;</span> <span class="special">(</span><span class="string">"MyType array from it"</span><span class="special">);</span>
<span class="comment">//Length should be 3</span>
<span class="keyword">if</span><span class="special">(</span><span class="identifier">res</span><span class="special">.</span><span class="identifier">second</span> <span class="special">!=</span> <span class="number">3</span><span class="special">)</span> <span class="keyword">return</span> <span class="number">1</span><span class="special">;</span>
<span class="comment">//We're done, delete all the objects</span>
<span class="identifier">segment</span><span class="special">.</span><span class="identifier">destroy</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">&gt;(</span><span class="string">"MyType array"</span><span class="special">);</span>
<span class="identifier">segment</span><span class="special">.</span><span class="identifier">destroy</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">&gt;(</span><span class="string">"MyType instance"</span><span class="special">);</span>
<span class="identifier">segment</span><span class="special">.</span><span class="identifier">destroy</span><span class="special">&lt;</span><span class="identifier">MyType</span><span class="special">&gt;(</span><span class="string">"MyType array from it"</span><span class="special">);</span>
<span class="special">}</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.quick_guide.qg_offset_ptr"></a><a class="link" href="quick_guide.html#interprocess.quick_guide.qg_offset_ptr" title="Using an offset smart pointer for shared memory">Using an offset
smart pointer for shared memory</a>
</h3></div></div></div>
<p>
<span class="bold"><strong>Boost.Interprocess</strong></span> offers offset_ptr smart
pointer family as an offset pointer that stores the distance between the
address of the offset pointer itself and the address of the pointed object.
When offset_ptr is placed in a shared memory segment, it can point safely
objects stored in the same shared memory segment, even if the segment is
mapped in different base addresses in different processes.
</p>
<p>
This allows placing objects with pointer members in shared memory. For example,
if we want to create a linked list in shared memory:
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">offset_ptr</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</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">//Shared memory linked list node</span>
<span class="keyword">struct</span> <span class="identifier">list_node</span>
<span class="special">{</span>
<span class="identifier">offset_ptr</span><span class="special">&lt;</span><span class="identifier">list_node</span><span class="special">&gt;</span> <span class="identifier">next</span><span class="special">;</span>
<span class="keyword">int</span> <span class="identifier">value</span><span class="special">;</span>
<span class="special">};</span>
<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span>
<span class="special">{</span>
<span class="comment">//Remove shared memory on construction and destruction</span>
<span class="keyword">struct</span> <span class="identifier">shm_remove</span>
<span class="special">{</span>
<span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span>
<span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span>
<span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span>
<span class="comment">//Create shared memory</span>
<span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span>
<span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="comment">//segment name</span>
<span class="number">65536</span><span class="special">);</span>
<span class="comment">//Create linked list with 10 nodes in shared memory</span>
<span class="identifier">offset_ptr</span><span class="special">&lt;</span><span class="identifier">list_node</span><span class="special">&gt;</span> <span class="identifier">prev</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="identifier">current</span><span class="special">,</span> <span class="identifier">first</span><span class="special">;</span>
<span class="keyword">int</span> <span class="identifier">i</span><span class="special">;</span>
<span class="keyword">for</span><span class="special">(</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">&lt;</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">prev</span> <span class="special">=</span> <span class="identifier">current</span><span class="special">){</span>
<span class="identifier">current</span> <span class="special">=</span> <span class="keyword">static_cast</span><span class="special">&lt;</span><span class="identifier">list_node</span><span class="special">*&gt;(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">allocate</span><span class="special">(</span><span class="keyword">sizeof</span><span class="special">(</span><span class="identifier">list_node</span><span class="special">)));</span>
<span class="identifier">current</span><span class="special">-&gt;</span><span class="identifier">value</span> <span class="special">=</span> <span class="identifier">i</span><span class="special">;</span>
<span class="identifier">current</span><span class="special">-&gt;</span><span class="identifier">next</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
<span class="keyword">if</span><span class="special">(!</span><span class="identifier">prev</span><span class="special">)</span>
<span class="identifier">first</span> <span class="special">=</span> <span class="identifier">current</span><span class="special">;</span>
<span class="keyword">else</span>
<span class="identifier">prev</span><span class="special">-&gt;</span><span class="identifier">next</span> <span class="special">=</span> <span class="identifier">current</span><span class="special">;</span>
<span class="special">}</span>
<span class="comment">//Communicate list to other processes</span>
<span class="comment">//. . .</span>
<span class="comment">//When done, destroy list</span>
<span class="keyword">for</span><span class="special">(</span><span class="identifier">current</span> <span class="special">=</span> <span class="identifier">first</span><span class="special">;</span> <span class="identifier">current</span><span class="special">;</span> <span class="comment">/**/</span><span class="special">){</span>
<span class="identifier">prev</span> <span class="special">=</span> <span class="identifier">current</span><span class="special">;</span>
<span class="identifier">current</span> <span class="special">=</span> <span class="identifier">current</span><span class="special">-&gt;</span><span class="identifier">next</span><span class="special">;</span>
<span class="identifier">segment</span><span class="special">.</span><span class="identifier">deallocate</span><span class="special">(</span><span class="identifier">prev</span><span class="special">.</span><span class="identifier">get</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>
<p>
To help with basic data structures, <span class="bold"><strong>Boost.Interprocess</strong></span>
offers containers like vector, list, map, so you can avoid these manual data
structures just like with standard containers.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.quick_guide.qg_interprocess_container"></a><a class="link" href="quick_guide.html#interprocess.quick_guide.qg_interprocess_container" title="Creating vectors in shared memory">Creating
vectors in shared memory</a>
</h3></div></div></div>
<p>
<span class="bold"><strong>Boost.Interprocess</strong></span> allows creating complex
objects in shared memory and memory mapped files. For example, we can construct
STL-like containers in shared memory. To do this, we just need to create
a special (managed) shared memory segment, declare a <span class="bold"><strong>Boost.Interprocess</strong></span>
allocator and construct the vector in shared memory just if it was any other
object.
</p>
<p>
The class that allows this complex structures in shared memory is called
<code class="computeroutput"><a class="link" href="../boost/interprocess/managed_shared_memory.html" title="Type definition managed_shared_memory">boost::interprocess::managed_shared_memory</a></code>
and it's easy to use. Just execute this example without arguments:
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">vector</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">string</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cstdlib</span><span class="special">&gt;</span> <span class="comment">//std::system</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 an STL compatible allocator of ints that allocates from the managed_shared_memory.</span>
<span class="comment">//This allocator will allow placing containers in the segment</span>
<span class="keyword">typedef</span> <span class="identifier">allocator</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">&gt;</span> <span class="identifier">ShmemAllocator</span><span class="special">;</span>
<span class="comment">//Alias a vector that uses the previous STL-like allocator so that allocates</span>
<span class="comment">//its values from the segment</span>
<span class="keyword">typedef</span> <span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">ShmemAllocator</span><span class="special">&gt;</span> <span class="identifier">MyVector</span><span class="special">;</span>
<span class="comment">//Main function. For parent process argc == 1, for child process argc == 2</span>
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">argc</span><span class="special">,</span> <span class="keyword">char</span> <span class="special">*</span><span class="identifier">argv</span><span class="special">[])</span>
<span class="special">{</span>
<span class="keyword">if</span><span class="special">(</span><span class="identifier">argc</span> <span class="special">==</span> <span class="number">1</span><span class="special">){</span> <span class="comment">//Parent process</span>
<span class="comment">//Remove shared memory on construction and destruction</span>
<span class="keyword">struct</span> <span class="identifier">shm_remove</span>
<span class="special">{</span>
<span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span>
<span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span>
<span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span>
<span class="comment">//Create a new segment with given name and size</span>
<span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> <span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="number">65536</span><span class="special">);</span>
<span class="comment">//Initialize shared memory STL-compatible allocator</span>
<span class="keyword">const</span> <span class="identifier">ShmemAllocator</span> <span class="identifier">alloc_inst</span> <span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span>
<span class="comment">//Construct a vector named "MyVector" in shared memory with argument alloc_inst</span>
<span class="identifier">MyVector</span> <span class="special">*</span><span class="identifier">myvector</span> <span class="special">=</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">MyVector</span><span class="special">&gt;(</span><span class="string">"MyVector"</span><span class="special">)(</span><span class="identifier">alloc_inst</span><span class="special">);</span>
<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="number">100</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span> <span class="comment">//Insert data in the vector</span>
<span class="identifier">myvector</span><span class="special">-&gt;</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">i</span><span class="special">);</span>
<span class="comment">//Launch child process</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">s</span><span class="special">(</span><span class="identifier">argv</span><span class="special">[</span><span class="number">0</span><span class="special">]);</span> <span class="identifier">s</span> <span class="special">+=</span> <span class="string">" child "</span><span class="special">;</span>
<span class="keyword">if</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">system</span><span class="special">(</span><span class="identifier">s</span><span class="special">.</span><span class="identifier">c_str</span><span class="special">()))</span>
<span class="keyword">return</span> <span class="number">1</span><span class="special">;</span>
<span class="comment">//Check child has destroyed the vector</span>
<span class="keyword">if</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">find</span><span class="special">&lt;</span><span class="identifier">MyVector</span><span class="special">&gt;(</span><span class="string">"MyVector"</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="special">}</span>
<span class="keyword">else</span><span class="special">{</span> <span class="comment">//Child process</span>
<span class="comment">//Open the managed segment</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="comment">//Find the vector using the c-string name</span>
<span class="identifier">MyVector</span> <span class="special">*</span><span class="identifier">myvector</span> <span class="special">=</span> <span class="identifier">segment</span><span class="special">.</span><span class="identifier">find</span><span class="special">&lt;</span><span class="identifier">MyVector</span><span class="special">&gt;(</span><span class="string">"MyVector"</span><span class="special">).</span><span class="identifier">first</span><span class="special">;</span>
<span class="comment">//Use vector in reverse order</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">sort</span><span class="special">(</span><span class="identifier">myvector</span><span class="special">-&gt;</span><span class="identifier">rbegin</span><span class="special">(),</span> <span class="identifier">myvector</span><span class="special">-&gt;</span><span class="identifier">rend</span><span class="special">());</span>
<span class="comment">//When done, destroy the vector from the segment</span>
<span class="identifier">segment</span><span class="special">.</span><span class="identifier">destroy</span><span class="special">&lt;</span><span class="identifier">MyVector</span><span class="special">&gt;(</span><span class="string">"MyVector"</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>
<p>
The parent process will create an special shared memory class that allows
easy construction of many complex data structures associated with a name.
The parent process executes the same program with an additional argument
so the child process opens the shared memory and uses the vector and erases
it.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.quick_guide.qg_interprocess_map"></a><a class="link" href="quick_guide.html#interprocess.quick_guide.qg_interprocess_map" title="Creating maps in shared memory">Creating
maps in shared memory</a>
</h3></div></div></div>
<p>
Just like a vector, <span class="bold"><strong>Boost.Interprocess</strong></span> allows
creating maps in shared memory and memory mapped files. The only difference
is that like standard associative containers, <span class="bold"><strong>Boost.Interprocess</strong></span>'s
map needs also the comparison functor when an allocator is passed in the
constructor:
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">map</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">functional</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">utility</span><span class="special">&gt;</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">//Shared memory front-end that is able to construct objects</span>
<span class="comment">//associated with a c-string. Erase previous shared memory with the name</span>
<span class="comment">//to be used and create the memory segment at the specified address and initialize resources</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">//segment name</span>
<span class="special">,</span><span class="number">65536</span><span class="special">);</span> <span class="comment">//segment size in bytes</span>
<span class="comment">//Note that map&lt;Key, MappedType&gt;'s value_type is std::pair&lt;const Key, MappedType&gt;,</span>
<span class="comment">//so the allocator must allocate that pair.</span>
<span class="keyword">typedef</span> <span class="keyword">int</span> <span class="identifier">KeyType</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">float</span> <span class="identifier">MappedType</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="keyword">const</span> <span class="keyword">int</span><span class="special">,</span> <span class="keyword">float</span><span class="special">&gt;</span> <span class="identifier">ValueType</span><span class="special">;</span>
<span class="comment">//Alias an STL compatible allocator of for the map.</span>
<span class="comment">//This allocator will allow to place containers</span>
<span class="comment">//in managed shared memory segments</span>
<span class="keyword">typedef</span> <span class="identifier">allocator</span><span class="special">&lt;</span><span class="identifier">ValueType</span><span class="special">,</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">&gt;</span>
<span class="identifier">ShmemAllocator</span><span class="special">;</span>
<span class="comment">//Alias a map of ints that uses the previous STL-like allocator.</span>
<span class="comment">//Note that the third parameter argument is the ordering function</span>
<span class="comment">//of the map, just like with std::map, used to compare the keys.</span>
<span class="keyword">typedef</span> <span class="identifier">map</span><span class="special">&lt;</span><span class="identifier">KeyType</span><span class="special">,</span> <span class="identifier">MappedType</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">less</span><span class="special">&lt;</span><span class="identifier">KeyType</span><span class="special">&gt;,</span> <span class="identifier">ShmemAllocator</span><span class="special">&gt;</span> <span class="identifier">MyMap</span><span class="special">;</span>
<span class="comment">//Initialize the shared memory STL-compatible allocator</span>
<span class="identifier">ShmemAllocator</span> <span class="identifier">alloc_inst</span> <span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">());</span>
<span class="comment">//Construct a shared memory map.</span>
<span class="comment">//Note that the first parameter is the comparison function,</span>
<span class="comment">//and the second one the allocator.</span>
<span class="comment">//This the same signature as std::map's constructor taking an allocator</span>
<span class="identifier">MyMap</span> <span class="special">*</span><span class="identifier">mymap</span> <span class="special">=</span>
<span class="identifier">segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">MyMap</span><span class="special">&gt;(</span><span class="string">"MyMap"</span><span class="special">)</span> <span class="comment">//object name</span>
<span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">less</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;()</span> <span class="comment">//first ctor parameter</span>
<span class="special">,</span><span class="identifier">alloc_inst</span><span class="special">);</span> <span class="comment">//second ctor parameter</span>
<span class="comment">//Insert data in the map</span>
<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="number">100</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
<span class="identifier">mymap</span><span class="special">-&gt;</span><span class="identifier">insert</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="keyword">const</span> <span class="keyword">int</span><span class="special">,</span> <span class="keyword">float</span><span class="special">&gt;(</span><span class="identifier">i</span><span class="special">,</span> <span class="special">(</span><span class="keyword">float</span><span class="special">)</span><span class="identifier">i</span><span class="special">));</span>
<span class="special">}</span>
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
</p>
<p>
For a more advanced example including containers of containers, see the section
<a class="link" href="allocators_containers.html#interprocess.allocators_containers.containers_explained.containers_of_containers" title="Containers of containers">Containers
of containers</a>.
</p>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2005-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="../interprocess.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="some_basic_explanations.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,577 @@
<!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>Some basic explanations</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="quick_guide.html" title="Quick Guide for the Impatient">
<link rel="next" href="sharedmemorybetweenprocesses.html" title="Sharing memory between processes">
</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="quick_guide.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="sharedmemorybetweenprocesses.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.some_basic_explanations"></a><a class="link" href="some_basic_explanations.html" title="Some basic explanations">Some basic explanations</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="some_basic_explanations.html#interprocess.some_basic_explanations.processes_and_threads">Processes
And Threads</a></span></dt>
<dt><span class="section"><a href="some_basic_explanations.html#interprocess.some_basic_explanations.sharing_information">Sharing
information between processes</a></span></dt>
<dt><span class="section"><a href="some_basic_explanations.html#interprocess.some_basic_explanations.persistence">Persistence
Of Interprocess Mechanisms</a></span></dt>
<dt><span class="section"><a href="some_basic_explanations.html#interprocess.some_basic_explanations.names">Names Of
Interprocess Mechanisms</a></span></dt>
<dt><span class="section"><a href="some_basic_explanations.html#interprocess.some_basic_explanations.constructors_destructors_and_resource_lifetime">Constructors,
destructors and lifetime of Interprocess named resources</a></span></dt>
<dt><span class="section"><a href="some_basic_explanations.html#interprocess.some_basic_explanations.permissions">Permissions</a></span></dt>
</dl></div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.some_basic_explanations.processes_and_threads"></a><a class="link" href="some_basic_explanations.html#interprocess.some_basic_explanations.processes_and_threads" title="Processes And Threads">Processes
And Threads</a>
</h3></div></div></div>
<p>
<span class="bold"><strong>Boost.Interprocess</strong></span> does not work only with
processes but also with threads. <span class="bold"><strong>Boost.Interprocess</strong></span>
synchronization mechanisms can synchronize threads from different processes,
but also threads from the same process.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.some_basic_explanations.sharing_information"></a><a class="link" href="some_basic_explanations.html#interprocess.some_basic_explanations.sharing_information" title="Sharing information between processes">Sharing
information between processes</a>
</h3></div></div></div>
<p>
In the traditional programming model an operating system has multiple processes
running and each process has its own address space. To share information
between processes we have several alternatives:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
Two processes share information using a <span class="bold"><strong>file</strong></span>.
To access to the data, each process uses the usual file read/write mechanisms.
When updating/reading a file shared between processes, we need some sort
of synchronization, to protect readers from writers.
</li>
<li class="listitem">
Two processes share information that resides in the <span class="bold"><strong>kernel</strong></span>
of the operating system. This is the case, for example, of traditional
message queues. The synchronization is guaranteed by the operating system
kernel.
</li>
<li class="listitem">
Two processes can share a <span class="bold"><strong>memory</strong></span> region.
This is the case of classical shared memory or memory mapped files. Once
the processes set up the memory region, the processes can read/write
the data like any other memory segment without calling the operating
system's kernel. This also requires some kind of manual synchronization
between processes.
</li>
</ul></div>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.some_basic_explanations.persistence"></a><a class="link" href="some_basic_explanations.html#interprocess.some_basic_explanations.persistence" title="Persistence Of Interprocess Mechanisms">Persistence
Of Interprocess Mechanisms</a>
</h3></div></div></div>
<p>
One of the biggest issues with interprocess communication mechanisms is the
lifetime of the interprocess communication mechanism. It's important to know
when an interprocess communication mechanism disappears from the system.
In <span class="bold"><strong>Boost.Interprocess</strong></span>, we can have 3 types
of persistence:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
<span class="bold"><strong>Process-persistence</strong></span>: The mechanism lasts
until all the processes that have opened the mechanism close it, exit
or crash.
</li>
<li class="listitem">
<span class="bold"><strong>Kernel-persistence</strong></span>: The mechanism exists
until the kernel of the operating system reboots or the mechanism is
explicitly deleted.
</li>
<li class="listitem">
<span class="bold"><strong>Filesystem-persistence</strong></span>: The mechanism
exists until the mechanism is explicitly deleted.
</li>
</ul></div>
<p>
Some native POSIX and Windows IPC mechanisms have different persistence so
it's difficult to achieve portability between Windows and POSIX native mechanisms.
<span class="bold"><strong>Boost.Interprocess</strong></span> classes have the following
persistence:
</p>
<div class="table">
<a name="interprocess.some_basic_explanations.persistence.boost_interprocess_persistence_table"></a><p class="title"><b>Table 18.1. Boost.Interprocess Persistence Table</b></p>
<div class="table-contents"><table class="table" summary="Boost.Interprocess Persistence Table">
<colgroup>
<col>
<col>
</colgroup>
<thead><tr>
<th>
<p>
Mechanism
</p>
</th>
<th>
<p>
Persistence
</p>
</th>
</tr></thead>
<tbody>
<tr>
<td>
<p>
Shared memory
</p>
</td>
<td>
<p>
Kernel or Filesystem
</p>
</td>
</tr>
<tr>
<td>
<p>
Memory mapped file
</p>
</td>
<td>
<p>
Filesystem
</p>
</td>
</tr>
<tr>
<td>
<p>
Process-shared mutex types
</p>
</td>
<td>
<p>
Process
</p>
</td>
</tr>
<tr>
<td>
<p>
Process-shared semaphore
</p>
</td>
<td>
<p>
Process
</p>
</td>
</tr>
<tr>
<td>
<p>
Process-shared condition
</p>
</td>
<td>
<p>
Process
</p>
</td>
</tr>
<tr>
<td>
<p>
File lock
</p>
</td>
<td>
<p>
Process
</p>
</td>
</tr>
<tr>
<td>
<p>
Message queue
</p>
</td>
<td>
<p>
Kernel or Filesystem
</p>
</td>
</tr>
<tr>
<td>
<p>
Named mutex
</p>
</td>
<td>
<p>
Kernel or Filesystem
</p>
</td>
</tr>
<tr>
<td>
<p>
Named semaphore
</p>
</td>
<td>
<p>
Kernel or Filesystem
</p>
</td>
</tr>
<tr>
<td>
<p>
Named condition
</p>
</td>
<td>
<p>
Kernel or Filesystem
</p>
</td>
</tr>
</tbody>
</table></div>
</div>
<br class="table-break"><p>
As you can see, <span class="bold"><strong>Boost.Interprocess</strong></span> defines
some mechanisms with "Kernel or Filesystem" persistence. This is
because POSIX allows this possibility to native interprocess communication
implementations. One could, for example, implement shared memory using memory
mapped files and obtain filesystem persistence (for example, there is no
proper known way to emulate kernel persistence with a user library for Windows
shared memory using native shared memory, or process persistence for POSIX
shared memory, so the only portable way is to define "Kernel or Filesystem"
persistence).
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.some_basic_explanations.names"></a><a class="link" href="some_basic_explanations.html#interprocess.some_basic_explanations.names" title="Names Of Interprocess Mechanisms">Names Of
Interprocess Mechanisms</a>
</h3></div></div></div>
<p>
Some interprocess mechanisms are anonymous objects created in shared memory
or memory-mapped files but other interprocess mechanisms need a name or identifier
so that two unrelated processes can use the same interprocess mechanism object.
Examples of this are shared memory, named mutexes and named semaphores (for
example, native windows CreateMutex/CreateSemaphore API family).
</p>
<p>
The name used to identify an interprocess mechanism is not portable, even
between UNIX systems. For this reason, <span class="bold"><strong>Boost.Interprocess</strong></span>
limits this name to a C++ variable identifier or keyword:
</p>
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
<li class="listitem">
Starts with a letter, lowercase or uppercase, such as a letter from a
to z or from A to Z. Examples: <span class="emphasis"><em>Sharedmemory, sharedmemory,
sHaReDmEmOrY...</em></span>
</li>
<li class="listitem">
Can include letters, underscore, or digits. Examples: <span class="emphasis"><em>shm1,
shm2and3, ShM3plus4...</em></span>
</li>
</ul></div>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.some_basic_explanations.constructors_destructors_and_resource_lifetime"></a><a class="link" href="some_basic_explanations.html#interprocess.some_basic_explanations.constructors_destructors_and_resource_lifetime" title="Constructors, destructors and lifetime of Interprocess named resources">Constructors,
destructors and lifetime of Interprocess named resources</a>
</h3></div></div></div>
<p>
Named <span class="bold"><strong>Boost.Interprocess</strong></span> resources (shared
memory, memory mapped files, named mutexes/conditions/semaphores) have kernel
or filesystem persistency. This means that even if all processes that have
opened those resources end, the resource will still be accessible to be opened
again and the resource can only be destructed via an explicit call to their
static member <code class="computeroutput"><span class="identifier">remove</span></code> function.
This behavior can be easily understood, since it's the same mechanism used
by functions controlling file opening/creation/erasure:
</p>
<div class="table">
<a name="interprocess.some_basic_explanations.constructors_destructors_and_resource_lifetime.boost_interprocess_filesystem_analogy"></a><p class="title"><b>Table 18.2. Boost.Interprocess-Filesystem Analogy</b></p>
<div class="table-contents"><table class="table" summary="Boost.Interprocess-Filesystem Analogy">
<colgroup>
<col>
<col>
<col>
</colgroup>
<thead><tr>
<th>
<p>
Named Interprocess resource
</p>
</th>
<th>
<p>
Corresponding std file
</p>
</th>
<th>
<p>
Corresponding POSIX operation
</p>
</th>
</tr></thead>
<tbody>
<tr>
<td>
<p>
Constructor
</p>
</td>
<td>
<p>
std::fstream constructor
</p>
</td>
<td>
<p>
open
</p>
</td>
</tr>
<tr>
<td>
<p>
Destructor
</p>
</td>
<td>
<p>
std::fstream destructor
</p>
</td>
<td>
<p>
close
</p>
</td>
</tr>
<tr>
<td>
<p>
Member <code class="computeroutput"><span class="identifier">remove</span></code>
</p>
</td>
<td>
<p>
None. <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">remove</span></code>
</p>
</td>
<td>
<p>
unlink
</p>
</td>
</tr>
</tbody>
</table></div>
</div>
<br class="table-break"><p>
Now the correspondence between POSIX and Boost.Interprocess regarding shared
memory and named semaphores:
</p>
<div class="table">
<a name="interprocess.some_basic_explanations.constructors_destructors_and_resource_lifetime.boost_interprocess_posix_shared_memory"></a><p class="title"><b>Table 18.3. Boost.Interprocess-POSIX shared memory</b></p>
<div class="table-contents"><table class="table" summary="Boost.Interprocess-POSIX shared memory">
<colgroup>
<col>
<col>
</colgroup>
<thead><tr>
<th>
<p>
<code class="computeroutput"><span class="identifier">shared_memory_object</span></code>
operation
</p>
</th>
<th>
<p>
POSIX operation
</p>
</th>
</tr></thead>
<tbody>
<tr>
<td>
<p>
Constructor
</p>
</td>
<td>
<p>
shm_open
</p>
</td>
</tr>
<tr>
<td>
<p>
Destructor
</p>
</td>
<td>
<p>
close
</p>
</td>
</tr>
<tr>
<td>
<p>
Member <code class="computeroutput"><span class="identifier">remove</span></code>
</p>
</td>
<td>
<p>
shm_unlink
</p>
</td>
</tr>
</tbody>
</table></div>
</div>
<br class="table-break"><div class="table">
<a name="interprocess.some_basic_explanations.constructors_destructors_and_resource_lifetime.boost_interprocess_posix_named_semaphore"></a><p class="title"><b>Table 18.4. Boost.Interprocess-POSIX named semaphore</b></p>
<div class="table-contents"><table class="table" summary="Boost.Interprocess-POSIX named semaphore">
<colgroup>
<col>
<col>
</colgroup>
<thead><tr>
<th>
<p>
<code class="computeroutput"><span class="identifier">named_semaphore</span></code>
operation
</p>
</th>
<th>
<p>
POSIX operation
</p>
</th>
</tr></thead>
<tbody>
<tr>
<td>
<p>
Constructor
</p>
</td>
<td>
<p>
sem_open
</p>
</td>
</tr>
<tr>
<td>
<p>
Destructor
</p>
</td>
<td>
<p>
close
</p>
</td>
</tr>
<tr>
<td>
<p>
Member <code class="computeroutput"><span class="identifier">remove</span></code>
</p>
</td>
<td>
<p>
sem_unlink
</p>
</td>
</tr>
</tbody>
</table></div>
</div>
<br class="table-break"><p>
The most important property is that <span class="bold"><strong>destructors of
named resources don't remove the resource from the system</strong></span>, they
only liberate resources allocated by the system for use by the process for
the named resource. <span class="bold"><strong>To remove the resource from the
system the programmer must use <code class="computeroutput"><span class="identifier">remove</span></code></strong></span>.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.some_basic_explanations.permissions"></a><a class="link" href="some_basic_explanations.html#interprocess.some_basic_explanations.permissions" title="Permissions">Permissions</a>
</h3></div></div></div>
<p>
Named resources offered by <span class="bold"><strong>Boost.Interprocess</strong></span>
must cope with platform-dependant permission issues also present when creating
files. If a programmer wants to shared shared memory, memory mapped files
or named synchronization mechanisms (mutexes, semaphores, etc...) between
users, it's necessary to specify those permissions. Sadly, traditional UNIX
and Windows permissions are very different and <span class="bold"><strong>Boost.Interprocess</strong></span>
does not try to standardize permissions, but does not ignore them.
</p>
<p>
All named resource creation functions take an optional <code class="computeroutput"><a class="link" href="../boost/interprocess/permissions.html" title="Class permissions">permissions
object</a></code> that can be configured with platform-dependant permissions.
</p>
<p>
Since each mechanism can be emulated through different mechanisms (a semaphore
might be implement using mapped files or native semaphores) permissions types
could vary when the implementation of a named resource changes (eg.: in Windows
mutexes require <code class="computeroutput"><span class="identifier">synchronize</span> <span class="identifier">permissions</span></code>, but that's not the case of
files). To avoid this, <span class="bold"><strong>Boost.Interprocess</strong></span>
relies on file-like permissions, requiring file read-write-delete permissions
to open named synchronization mechanisms (mutex, semaphores, etc.) and appropriate
read or read-write-delete permissions for shared memory. This approach has
two advantages: it's similar to the UNIX philosophy and the programmer does
not need to know how the named resource is implemented.
</p>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2005-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="quick_guide.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="sharedmemorybetweenprocesses.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

View File

@@ -0,0 +1,443 @@
<!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>Direct iostream formatting: vectorstream and bufferstream</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="memory_algorithms.html" title="Memory allocation algorithms">
<link rel="next" href="interprocess_smart_ptr.html" title="Ownership smart pointers">
</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="memory_algorithms.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="interprocess_smart_ptr.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.streams"></a><a class="link" href="streams.html" title="Direct iostream formatting: vectorstream and bufferstream">Direct iostream formatting: vectorstream
and bufferstream</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="streams.html#interprocess.streams.vectorstream">Formatting directly
in your character vector: vectorstream</a></span></dt>
<dt><span class="section"><a href="streams.html#interprocess.streams.bufferstream">Formatting directly
in your character buffer: bufferstream</a></span></dt>
</dl></div>
<p>
Shared memory, memory-mapped files and all <span class="bold"><strong>Boost.Interprocess</strong></span>
mechanisms are focused on efficiency. The reason why shared memory is used
is that it's the fastest IPC mechanism available. When passing text-oriented
messages through shared memory, there is need to format the message. Obviously
C++ offers the iostream framework for that work.
</p>
<p>
Some programmers appreciate the iostream safety and design for memory formatting
but feel that the stringstream family is far from efficient not when formatting,
but when obtaining formatted data to a string, or when setting the string from
which the stream will extract data. An example:
</p>
<pre class="programlisting"><span class="comment">//Some formatting elements</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">my_text</span> <span class="special">=</span> <span class="string">"..."</span><span class="special">;</span>
<span class="keyword">int</span> <span class="identifier">number</span><span class="special">;</span>
<span class="comment">//Data reader</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">istringstream</span> <span class="identifier">input_processor</span><span class="special">;</span>
<span class="comment">//This makes a copy of the string. If not using a</span>
<span class="comment">//reference counted string, this is a serious overhead.</span>
<span class="identifier">input_processor</span><span class="special">.</span><span class="identifier">str</span><span class="special">(</span><span class="identifier">my_text</span><span class="special">);</span>
<span class="comment">//Extract data</span>
<span class="keyword">while</span><span class="special">(/*...*/){</span>
<span class="identifier">input_processor</span> <span class="special">&gt;&gt;</span> <span class="identifier">number</span><span class="special">;</span>
<span class="special">}</span>
<span class="comment">//Data writer</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">ostringstream</span> <span class="identifier">output_processor</span><span class="special">;</span>
<span class="comment">//Write data</span>
<span class="keyword">while</span><span class="special">(/*...*/){</span>
<span class="identifier">output_processor</span> <span class="special">&lt;&lt;</span> <span class="identifier">number</span><span class="special">;</span>
<span class="special">}</span>
<span class="comment">//This returns a temporary string. Even with return-value</span>
<span class="comment">//optimization this is expensive.</span>
<span class="identifier">my_text</span> <span class="special">=</span> <span class="identifier">input_processor</span><span class="special">.</span><span class="identifier">str</span><span class="special">();</span>
</pre>
<p>
The problem is even worse if the string is a shared-memory string, because
to extract data, we must copy the data first from shared-memory to a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>
and then to a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">stringstream</span></code>. To encode data in a shared
memory string we should copy data from a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">stringstream</span></code>
to a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code> and then to the shared-memory string.
</p>
<p>
Because of this overhead, <span class="bold"><strong>Boost.Interprocess</strong></span>
offers a way to format memory-strings (in shared memory, memory mapped files
or any other memory segment) that can avoid all unneeded string copy and memory
allocation/deallocations, while using all iostream facilities. <span class="bold"><strong>Boost.Interprocess</strong></span>
<span class="bold"><strong>vectorstream</strong></span> and <span class="bold"><strong>bufferstream</strong></span>
implement vector-based and fixed-size buffer based storage support for iostreams
and all the formatting/locale hard work is done by standard <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_streambuf</span><span class="special">&lt;&gt;</span></code> and <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_iostream</span><span class="special">&lt;&gt;</span></code> classes.
</p>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="interprocess.streams.vectorstream"></a><a class="link" href="streams.html#interprocess.streams.vectorstream" title="Formatting directly in your character vector: vectorstream">Formatting directly
in your character vector: vectorstream</a>
</h3></div></div></div>
<p>
The <span class="bold"><strong>vectorstream</strong></span> class family (<span class="bold"><strong>basic_vectorbuf</strong></span>, <span class="bold"><strong>basic_ivectorstream</strong></span>
,<span class="bold"><strong>basic_ovectorstream</strong></span> and <span class="bold"><strong>basic_vectorstream</strong></span>)
is an efficient way to obtain formatted reading/writing directly in a character
vector. This way, if a shared-memory vector is used, data is extracted/written
from/to the shared-memory vector, without additional copy/allocation. We
can see the declaration of basic_vectorstream here:
</p>
<pre class="programlisting"><span class="comment">//!A basic_iostream class that holds a character vector specified by CharVector</span>
<span class="comment">//!template parameter as its formatting buffer. The vector must have</span>
<span class="comment">//!contiguous storage, like std::vector, boost::interprocess::vector or</span>
<span class="comment">//!boost::interprocess::basic_string</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">CharVector</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">CharTraits</span> <span class="special">=</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">char_traits</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">CharVector</span><span class="special">::</span><span class="identifier">value_type</span><span class="special">&gt;</span> <span class="special">&gt;</span>
<span class="keyword">class</span> <span class="identifier">basic_vectorstream</span>
<span class="special">:</span> <span class="keyword">public</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_iostream</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">CharVector</span><span class="special">::</span><span class="identifier">value_type</span><span class="special">,</span> <span class="identifier">CharTraits</span><span class="special">&gt;</span>
<span class="special">{</span>
<span class="keyword">public</span><span class="special">:</span>
<span class="keyword">typedef</span> <span class="identifier">CharVector</span> <span class="identifier">vector_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ios</span>
<span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">CharVector</span><span class="special">::</span><span class="identifier">value_type</span><span class="special">,</span> <span class="identifier">CharTraits</span><span class="special">&gt;::</span><span class="identifier">char_type</span> <span class="identifier">char_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ios</span><span class="special">&lt;</span><span class="identifier">char_type</span><span class="special">,</span> <span class="identifier">CharTraits</span><span class="special">&gt;::</span><span class="identifier">int_type</span> <span class="identifier">int_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ios</span><span class="special">&lt;</span><span class="identifier">char_type</span><span class="special">,</span> <span class="identifier">CharTraits</span><span class="special">&gt;::</span><span class="identifier">pos_type</span> <span class="identifier">pos_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ios</span><span class="special">&lt;</span><span class="identifier">char_type</span><span class="special">,</span> <span class="identifier">CharTraits</span><span class="special">&gt;::</span><span class="identifier">off_type</span> <span class="identifier">off_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ios</span><span class="special">&lt;</span><span class="identifier">char_type</span><span class="special">,</span> <span class="identifier">CharTraits</span><span class="special">&gt;::</span><span class="identifier">traits_type</span> <span class="identifier">traits_type</span><span class="special">;</span>
<span class="comment">//!Constructor. Throws if vector_type default constructor throws.</span>
<span class="identifier">basic_vectorstream</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">openmode</span> <span class="identifier">mode</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">in</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="comment">//!Constructor. Throws if vector_type(const Parameter &amp;param) throws.</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Parameter</span><span class="special">&gt;</span>
<span class="identifier">basic_vectorstream</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">Parameter</span> <span class="special">&amp;</span><span class="identifier">param</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">openmode</span> <span class="identifier">mode</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">in</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="special">~</span><span class="identifier">basic_vectorstream</span><span class="special">(){}</span>
<span class="comment">//!Returns the address of the stored stream buffer.</span>
<span class="identifier">basic_vectorbuf</span><span class="special">&lt;</span><span class="identifier">CharVector</span><span class="special">,</span> <span class="identifier">CharTraits</span><span class="special">&gt;*</span> <span class="identifier">rdbuf</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
<span class="comment">//!Swaps the underlying vector with the passed vector.</span>
<span class="comment">//!This function resets the position in the stream.</span>
<span class="comment">//!Does not throw.</span>
<span class="keyword">void</span> <span class="identifier">swap_vector</span><span class="special">(</span><span class="identifier">vector_type</span> <span class="special">&amp;</span><span class="identifier">vect</span><span class="special">);</span>
<span class="comment">//!Returns a const reference to the internal vector.</span>
<span class="comment">//!Does not throw.</span>
<span class="keyword">const</span> <span class="identifier">vector_type</span> <span class="special">&amp;</span><span class="identifier">vector</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
<span class="comment">//!Preallocates memory from the internal vector.</span>
<span class="comment">//!Resets the stream to the first position.</span>
<span class="comment">//!Throws if the internals vector's memory allocation throws.</span>
<span class="keyword">void</span> <span class="identifier">reserve</span><span class="special">(</span><span class="keyword">typename</span> <span class="identifier">vector_type</span><span class="special">::</span><span class="identifier">size_type</span> <span class="identifier">size</span><span class="special">);</span>
<span class="special">};</span>
</pre>
<p>
The vector type is templatized, so that we can use any type of vector: <span class="bold"><strong>std::vector</strong></span>, <code class="computeroutput">boost::interprocess::vector</code>...
But the storage must be <span class="bold"><strong>contiguous</strong></span>, we can't
use a deque. We can even use <span class="bold"><strong>boost::interprocess::basic_string</strong></span>,
since it has a vector interface and it has contiguous storage. <span class="bold"><strong>We can't use std::string</strong></span>, because although some std::string
implementation are vector-based, others can have optimizations and reference-counted
implementations.
</p>
<p>
The user can obtain a const reference to the internal vector using <code class="computeroutput"><span class="identifier">vector_type</span> <span class="identifier">vector</span><span class="special">()</span> <span class="keyword">const</span></code> function
and he also can swap the internal vector with an external one calling <code class="computeroutput"><span class="keyword">void</span> <span class="identifier">swap_vector</span><span class="special">(</span><span class="identifier">vector_type</span>
<span class="special">&amp;</span><span class="identifier">vect</span><span class="special">)</span></code>. The swap function resets the stream position.
This functions allow efficient methods to obtain the formatted data avoiding
all allocations and data copies.
</p>
<p>
Let's see an example to see how to use vectorstream:
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">vector</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">containers</span><span class="special">/</span><span class="identifier">string</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">streams</span><span class="special">/</span><span class="identifier">vectorstream</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iterator</span><span class="special">&gt;</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">allocator</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">&gt;</span>
<span class="identifier">IntAllocator</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">allocator</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">,</span> <span class="identifier">managed_shared_memory</span><span class="special">::</span><span class="identifier">segment_manager</span><span class="special">&gt;</span>
<span class="identifier">CharAllocator</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">,</span> <span class="identifier">IntAllocator</span><span class="special">&gt;</span> <span class="identifier">MyVector</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">basic_string</span>
<span class="special">&lt;</span><span class="keyword">char</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">char_traits</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">&gt;,</span> <span class="identifier">CharAllocator</span><span class="special">&gt;</span> <span class="identifier">MyString</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">basic_vectorstream</span><span class="special">&lt;</span><span class="identifier">MyString</span><span class="special">&gt;</span> <span class="identifier">MyVectorStream</span><span class="special">;</span>
<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span>
<span class="special">{</span>
<span class="comment">//Remove shared memory on construction and destruction</span>
<span class="keyword">struct</span> <span class="identifier">shm_remove</span>
<span class="special">{</span>
<span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span>
<span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span>
<span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span>
<span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span><span class="special">(</span>
<span class="identifier">create_only</span><span class="special">,</span>
<span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="comment">//segment name</span>
<span class="number">65536</span><span class="special">);</span> <span class="comment">//segment size in bytes</span>
<span class="comment">//Construct shared memory vector</span>
<span class="identifier">MyVector</span> <span class="special">*</span><span class="identifier">myvector</span> <span class="special">=</span>
<span class="identifier">segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">MyVector</span><span class="special">&gt;(</span><span class="string">"MyVector"</span><span class="special">)</span>
<span class="special">(</span><span class="identifier">IntAllocator</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">()));</span>
<span class="comment">//Fill vector</span>
<span class="identifier">myvector</span><span class="special">-&gt;</span><span class="identifier">reserve</span><span class="special">(</span><span class="number">100</span><span class="special">);</span>
<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="number">100</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
<span class="identifier">myvector</span><span class="special">-&gt;</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">i</span><span class="special">);</span>
<span class="special">}</span>
<span class="comment">//Create the vectorstream. To create the internal shared memory</span>
<span class="comment">//basic_string we need to pass the shared memory allocator as</span>
<span class="comment">//a constructor argument</span>
<span class="identifier">MyVectorStream</span> <span class="identifier">myvectorstream</span><span class="special">(</span><span class="identifier">CharAllocator</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">()));</span>
<span class="comment">//Reserve the internal string</span>
<span class="identifier">myvectorstream</span><span class="special">.</span><span class="identifier">reserve</span><span class="special">(</span><span class="number">100</span><span class="special">*</span><span class="number">5</span><span class="special">);</span>
<span class="comment">//Write all vector elements as text in the internal string</span>
<span class="comment">//Data will be directly written in shared memory, because</span>
<span class="comment">//internal string's allocator is a shared memory allocator</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">max</span> <span class="special">=</span> <span class="identifier">myvector</span><span class="special">-&gt;</span><span class="identifier">size</span><span class="special">();</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">max</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
<span class="identifier">myvectorstream</span> <span class="special">&lt;&lt;</span> <span class="special">(*</span><span class="identifier">myvector</span><span class="special">)[</span><span class="identifier">i</span><span class="special">]</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="special">}</span>
<span class="comment">//Auxiliary vector to compare original data</span>
<span class="identifier">MyVector</span> <span class="special">*</span><span class="identifier">myvector2</span> <span class="special">=</span>
<span class="identifier">segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">MyVector</span><span class="special">&gt;(</span><span class="string">"MyVector2"</span><span class="special">)</span>
<span class="special">(</span><span class="identifier">IntAllocator</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">()));</span>
<span class="comment">//Avoid reallocations</span>
<span class="identifier">myvector2</span><span class="special">-&gt;</span><span class="identifier">reserve</span><span class="special">(</span><span class="number">100</span><span class="special">);</span>
<span class="comment">//Extract all values from the internal</span>
<span class="comment">//string directly to a shared memory vector.</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">istream_iterator</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">it</span><span class="special">(</span><span class="identifier">myvectorstream</span><span class="special">),</span> <span class="identifier">itend</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">copy</span><span class="special">(</span><span class="identifier">it</span><span class="special">,</span> <span class="identifier">itend</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">back_inserter</span><span class="special">(*</span><span class="identifier">myvector2</span><span class="special">));</span>
<span class="comment">//Compare vectors</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">equal</span><span class="special">(</span><span class="identifier">myvector</span><span class="special">-&gt;</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">myvector</span><span class="special">-&gt;</span><span class="identifier">end</span><span class="special">(),</span> <span class="identifier">myvector2</span><span class="special">-&gt;</span><span class="identifier">begin</span><span class="special">()));</span>
<span class="comment">//Create a copy of the internal string</span>
<span class="identifier">MyString</span> <span class="identifier">stringcopy</span> <span class="special">(</span><span class="identifier">myvectorstream</span><span class="special">.</span><span class="identifier">vector</span><span class="special">());</span>
<span class="comment">//Now we create a new empty shared memory string...</span>
<span class="identifier">MyString</span> <span class="special">*</span><span class="identifier">mystring</span> <span class="special">=</span>
<span class="identifier">segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="identifier">MyString</span><span class="special">&gt;(</span><span class="string">"MyString"</span><span class="special">)</span>
<span class="special">(</span><span class="identifier">CharAllocator</span><span class="special">(</span><span class="identifier">segment</span><span class="special">.</span><span class="identifier">get_segment_manager</span><span class="special">()));</span>
<span class="comment">//...and we swap vectorstream's internal string</span>
<span class="comment">//with the new one: after this statement mystring</span>
<span class="comment">//will be the owner of the formatted data.</span>
<span class="comment">//No reallocations, no data copies</span>
<span class="identifier">myvectorstream</span><span class="special">.</span><span class="identifier">swap_vector</span><span class="special">(*</span><span class="identifier">mystring</span><span class="special">);</span>
<span class="comment">//Let's compare both strings</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">stringcopy</span> <span class="special">==</span> <span class="special">*</span><span class="identifier">mystring</span><span class="special">);</span>
<span class="comment">//Done, destroy and delete vectors and string from the segment</span>
<span class="identifier">segment</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">myvector2</span><span class="special">);</span>
<span class="identifier">segment</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">myvector</span><span class="special">);</span>
<span class="identifier">segment</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">mystring</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><h3 class="title">
<a name="interprocess.streams.bufferstream"></a><a class="link" href="streams.html#interprocess.streams.bufferstream" title="Formatting directly in your character buffer: bufferstream">Formatting directly
in your character buffer: bufferstream</a>
</h3></div></div></div>
<p>
As seen, vectorstream offers an easy and secure way for efficient iostream
formatting, but many times, we have to read or write formatted data from/to
a fixed size character buffer (a static buffer, a c-string, or any other).
Because of the overhead of stringstream, many developers (specially in embedded
systems) choose sprintf family. The <span class="bold"><strong>bufferstream</strong></span>
classes offer iostream interface with direct formatting in a fixed size memory
buffer with protection against buffer overflows. This is the interface:
</p>
<pre class="programlisting"><span class="comment">//!A basic_iostream class that uses a fixed size character buffer</span>
<span class="comment">//!as its formatting buffer.</span>
<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">CharT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">CharTraits</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">char_traits</span><span class="special">&lt;</span><span class="identifier">CharT</span><span class="special">&gt;</span> <span class="special">&gt;</span>
<span class="keyword">class</span> <span class="identifier">basic_bufferstream</span>
<span class="special">:</span> <span class="keyword">public</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_iostream</span><span class="special">&lt;</span><span class="identifier">CharT</span><span class="special">,</span> <span class="identifier">CharTraits</span><span class="special">&gt;</span>
<span class="special">{</span>
<span class="keyword">public</span><span class="special">:</span> <span class="comment">// Typedefs</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ios</span>
<span class="special">&lt;</span><span class="identifier">CharT</span><span class="special">,</span> <span class="identifier">CharTraits</span><span class="special">&gt;::</span><span class="identifier">char_type</span> <span class="identifier">char_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ios</span><span class="special">&lt;</span><span class="identifier">char_type</span><span class="special">,</span> <span class="identifier">CharTraits</span><span class="special">&gt;::</span><span class="identifier">int_type</span> <span class="identifier">int_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ios</span><span class="special">&lt;</span><span class="identifier">char_type</span><span class="special">,</span> <span class="identifier">CharTraits</span><span class="special">&gt;::</span><span class="identifier">pos_type</span> <span class="identifier">pos_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ios</span><span class="special">&lt;</span><span class="identifier">char_type</span><span class="special">,</span> <span class="identifier">CharTraits</span><span class="special">&gt;::</span><span class="identifier">off_type</span> <span class="identifier">off_type</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">basic_ios</span><span class="special">&lt;</span><span class="identifier">char_type</span><span class="special">,</span> <span class="identifier">CharTraits</span><span class="special">&gt;::</span><span class="identifier">traits_type</span> <span class="identifier">traits_type</span><span class="special">;</span>
<span class="comment">//!Constructor. Does not throw.</span>
<span class="identifier">basic_bufferstream</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">openmode</span> <span class="identifier">mode</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">in</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="comment">//!Constructor. Assigns formatting buffer. Does not throw.</span>
<span class="identifier">basic_bufferstream</span><span class="special">(</span><span class="identifier">CharT</span> <span class="special">*</span><span class="identifier">buffer</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">length</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">openmode</span> <span class="identifier">mode</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">in</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="comment">//!Returns the address of the stored stream buffer.</span>
<span class="identifier">basic_bufferbuf</span><span class="special">&lt;</span><span class="identifier">CharT</span><span class="special">,</span> <span class="identifier">CharTraits</span><span class="special">&gt;*</span> <span class="identifier">rdbuf</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
<span class="comment">//!Returns the pointer and size of the internal buffer.</span>
<span class="comment">//!Does not throw.</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">pair</span><span class="special">&lt;</span><span class="identifier">CharT</span> <span class="special">*,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">&gt;</span> <span class="identifier">buffer</span><span class="special">()</span> <span class="keyword">const</span><span class="special">;</span>
<span class="comment">//!Sets the underlying buffer to a new value. Resets</span>
<span class="comment">//!stream position. Does not throw.</span>
<span class="keyword">void</span> <span class="identifier">buffer</span><span class="special">(</span><span class="identifier">CharT</span> <span class="special">*</span><span class="identifier">buffer</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">length</span><span class="special">);</span>
<span class="special">};</span>
<span class="comment">//Some typedefs to simplify usage</span>
<span class="keyword">typedef</span> <span class="identifier">basic_bufferstream</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">&gt;</span> <span class="identifier">bufferstream</span><span class="special">;</span>
<span class="keyword">typedef</span> <span class="identifier">basic_bufferstream</span><span class="special">&lt;</span><span class="keyword">wchar_t</span><span class="special">&gt;</span> <span class="identifier">wbufferstream</span><span class="special">;</span>
<span class="comment">// ...</span>
</pre>
<p>
While reading from a fixed size buffer, <span class="bold"><strong>bufferstream</strong></span>
activates endbit flag if we try to read an address beyond the end of the
buffer. While writing to a fixed size buffer, <span class="bold"><strong>bufferstream</strong></span>
will active the badbit flag if a buffer overflow is going to happen and disallows
writing. This way, the fixed size buffer formatting through <span class="bold"><strong>bufferstream</strong></span>
is secure and efficient, and offers a good alternative to sprintf/sscanf
functions. Let's see an example:
</p>
<p>
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">streams</span><span class="special">/</span><span class="identifier">bufferstream</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">vector</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iterator</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cstddef</span><span class="special">&gt;</span>
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span>
<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span>
<span class="special">{</span>
<span class="comment">//Remove shared memory on construction and destruction</span>
<span class="keyword">struct</span> <span class="identifier">shm_remove</span>
<span class="special">{</span>
<span class="identifier">shm_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span>
<span class="special">~</span><span class="identifier">shm_remove</span><span class="special">(){</span> <span class="identifier">shared_memory_object</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"MySharedMemory"</span><span class="special">);</span> <span class="special">}</span>
<span class="special">}</span> <span class="identifier">remover</span><span class="special">;</span>
<span class="comment">//Create shared memory</span>
<span class="identifier">managed_shared_memory</span> <span class="identifier">segment</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span>
<span class="string">"MySharedMemory"</span><span class="special">,</span> <span class="comment">//segment name</span>
<span class="number">65536</span><span class="special">);</span>
<span class="comment">//Fill data</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">data</span><span class="special">;</span>
<span class="identifier">data</span><span class="special">.</span><span class="identifier">reserve</span><span class="special">(</span><span class="number">100</span><span class="special">);</span>
<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="number">100</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
<span class="identifier">data</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">i</span><span class="special">);</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">BufferSize</span> <span class="special">=</span> <span class="number">100</span><span class="special">*</span><span class="number">5</span><span class="special">;</span>
<span class="comment">//Allocate a buffer in shared memory to write data</span>
<span class="keyword">char</span> <span class="special">*</span><span class="identifier">my_cstring</span> <span class="special">=</span>
<span class="identifier">segment</span><span class="special">.</span><span class="identifier">construct</span><span class="special">&lt;</span><span class="keyword">char</span><span class="special">&gt;(</span><span class="string">"MyCString"</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">bufferstream</span> <span class="identifier">mybufstream</span><span class="special">(</span><span class="identifier">my_cstring</span><span class="special">,</span> <span class="identifier">BufferSize</span><span class="special">);</span>
<span class="comment">//Now write data to the buffer</span>
<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="number">100</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
<span class="identifier">mybufstream</span> <span class="special">&lt;&lt;</span> <span class="identifier">data</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="special">}</span>
<span class="comment">//Check there was no overflow attempt</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">mybufstream</span><span class="special">.</span><span class="identifier">good</span><span class="special">());</span>
<span class="comment">//Extract all values from the shared memory string</span>
<span class="comment">//directly to a vector.</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">data2</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">istream_iterator</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">it</span><span class="special">(</span><span class="identifier">mybufstream</span><span class="special">),</span> <span class="identifier">itend</span><span class="special">;</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">copy</span><span class="special">(</span><span class="identifier">it</span><span class="special">,</span> <span class="identifier">itend</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">back_inserter</span><span class="special">(</span><span class="identifier">data2</span><span class="special">));</span>
<span class="comment">//This extraction should have ended will fail error since</span>
<span class="comment">//the numbers formatted in the buffer end before the end</span>
<span class="comment">//of the buffer. (Otherwise it would trigger eofbit)</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">mybufstream</span><span class="special">.</span><span class="identifier">fail</span><span class="special">());</span>
<span class="comment">//Compare data</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">equal</span><span class="special">(</span><span class="identifier">data</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">data</span><span class="special">.</span><span class="identifier">end</span><span class="special">(),</span> <span class="identifier">data2</span><span class="special">.</span><span class="identifier">begin</span><span class="special">()));</span>
<span class="comment">//Clear errors and rewind</span>
<span class="identifier">mybufstream</span><span class="special">.</span><span class="identifier">clear</span><span class="special">();</span>
<span class="identifier">mybufstream</span><span class="special">.</span><span class="identifier">seekp</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">ios</span><span class="special">::</span><span class="identifier">beg</span><span class="special">);</span>
<span class="comment">//Now write again the data trying to do a buffer overflow</span>
<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="identifier">m</span> <span class="special">=</span> <span class="identifier">data</span><span class="special">.</span><span class="identifier">size</span><span class="special">()*</span><span class="number">5</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">m</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
<span class="identifier">mybufstream</span> <span class="special">&lt;&lt;</span> <span class="identifier">data</span><span class="special">[</span><span class="identifier">i</span><span class="special">%</span><span class="number">5</span><span class="special">]</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="special">}</span>
<span class="comment">//Now make sure badbit is active</span>
<span class="comment">//which means overflow attempt.</span>
<span class="identifier">assert</span><span class="special">(!</span><span class="identifier">mybufstream</span><span class="special">.</span><span class="identifier">good</span><span class="special">());</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">mybufstream</span><span class="special">.</span><span class="identifier">bad</span><span class="special">());</span>
<span class="identifier">segment</span><span class="special">.</span><span class="identifier">destroy_ptr</span><span class="special">(</span><span class="identifier">my_cstring</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>
As seen, <span class="bold"><strong>bufferstream</strong></span> offers an efficient
way to format data without any allocation and extra copies. This is very
helpful in embedded systems, or formatting inside time-critical loops, where
stringstream extra copies would be too expensive. Unlike sprintf/sscanf,
it has protection against buffer overflows. As we know, according to the
<span class="bold"><strong>Technical Report on C++ Performance</strong></span>, it's
possible to design efficient iostreams for embedded platforms, so this bufferstream
class comes handy to format data to stack, static or shared memory buffers.
</p>
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright © 2005-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="memory_algorithms.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="interprocess_smart_ptr.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff