719 lines
53 KiB
HTML
719 lines
53 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||
<html>
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
<title>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"><</span><span class="keyword">void</span><span class="special">></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">|<-</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"><</span><span class="keyword">class</span> <span class="identifier">CharType</span>
|
||
<span class="special">,</span><span class="keyword">class</span> <span class="identifier">MemoryAlgorithm</span>
|
||
<span class="special">,</span><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">IndexConfig</span><span class="special">></span> <span class="keyword">class</span> <span class="identifier">IndexType</span><span class="special">></span>
|
||
<span class="keyword">class</span> <span class="identifier">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"><</span><span class="keyword">void</span><span class="special">></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"><</span><span class="identifier">T</span><span class="special">></span></code>
|
||
will store an <code class="computeroutput"><span class="identifier">offset_ptr</span><span class="special"><</span><span class="identifier">segment_manager</span><span class="special">></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"><</span><span class="identifier">T</span><span class="special">>::</span><span class="identifier">pointer</span></code> type will be <code class="computeroutput"><span class="identifier">offset_ptr</span><span class="special"><</span><span class="identifier">T</span><span class="special">></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"><...></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"><</span><span class="identifier">T</span><span class="special">>(</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">&)</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 &). 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>
|