3219 lines
242 KiB
HTML
3219 lines
242 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>Synchronization mechanisms</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="offset_ptr.html" title="Mapping Address Independent Pointer: offset_ptr">
|
||
<link rel="next" href="managed_memory_segments.html" title="Managed Memory Segments">
|
||
</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="offset_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="managed_memory_segments.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.synchronization_mechanisms"></a><a class="link" href="synchronization_mechanisms.html" title="Synchronization mechanisms">Synchronization
|
||
mechanisms</a>
|
||
</h2></div></div></div>
|
||
<div class="toc"><dl class="toc">
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.synchronization_mechanisms_overview">Synchronization
|
||
mechanisms overview</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes">Mutexes</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.conditions">Conditions</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.semaphores">Semaphores</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes">Sharable
|
||
and Upgradable Mutexes</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.lock_conversions">Lock
|
||
Transfers Through Move Semantics</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.file_lock">File
|
||
Locks</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.message_queue">Message
|
||
Queue</a></span></dt>
|
||
</dl></div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h3 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.synchronization_mechanisms_overview"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.synchronization_mechanisms_overview" title="Synchronization mechanisms overview">Synchronization
|
||
mechanisms overview</a>
|
||
</h3></div></div></div>
|
||
<div class="toc"><dl class="toc">
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.synchronization_mechanisms_overview.synchronization_mechanisms_named_vs_anonymous">Named
|
||
And Anonymous Synchronization Mechanisms</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.synchronization_mechanisms_overview.synchronization_mechanisms_types">Types
|
||
Of Synchronization Mechanisms</a></span></dt>
|
||
</dl></div>
|
||
<p>
|
||
As mentioned before, the ability to shared memory between processes through
|
||
memory mapped files or shared memory objects is not very useful if the access
|
||
to that memory can't be effectively synchronized. This is the same problem
|
||
that happens with thread-synchronization mechanisms, where heap memory and
|
||
global variables are shared between threads, but the access to these resources
|
||
needs to be synchronized typically through mutex and condition variables.
|
||
<span class="bold"><strong>Boost.Threads</strong></span> implements these synchronization
|
||
utilities between threads inside the same process. <span class="bold"><strong>Boost.Interprocess</strong></span>
|
||
implements similar mechanisms to synchronize threads from different processes.
|
||
</p>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.synchronization_mechanisms_overview.synchronization_mechanisms_named_vs_anonymous"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.synchronization_mechanisms_overview.synchronization_mechanisms_named_vs_anonymous" title="Named And Anonymous Synchronization Mechanisms">Named
|
||
And Anonymous Synchronization Mechanisms</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
<span class="bold"><strong>Boost.Interprocess</strong></span> presents two types
|
||
of synchronization objects:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
<span class="bold"><strong>Named utilities</strong></span>: When two processes
|
||
want to create an object of such type, both processes must <span class="emphasis"><em>create</em></span>
|
||
or <span class="emphasis"><em>open</em></span> an object using the same name. This is
|
||
similar to creating or opening files: a process creates a file with
|
||
using a <code class="computeroutput"><span class="identifier">fstream</span></code> with
|
||
the name <span class="emphasis"><em>filename</em></span> and another process opens that
|
||
file using another <code class="computeroutput"><span class="identifier">fstream</span></code>
|
||
with the same <span class="emphasis"><em>filename</em></span> argument. <span class="bold"><strong>Each
|
||
process uses a different object to access to the resource, but both
|
||
processes are using the same underlying resource</strong></span>.
|
||
</li>
|
||
<li class="listitem">
|
||
<span class="bold"><strong>Anonymous utilities</strong></span>: Since these utilities
|
||
have no name, two processes must share <span class="bold"><strong>the same
|
||
object</strong></span> through shared memory or memory mapped files. This
|
||
is similar to traditional thread synchronization objects: <span class="bold"><strong>Both processes share the same object</strong></span>. Unlike
|
||
thread synchronization, where global variables and heap memory is shared
|
||
between threads of the same process, sharing objects between two threads
|
||
from different process can be only possible through mapped regions
|
||
that map the same mappable resource (for example, shared memory or
|
||
memory mapped files).
|
||
</li>
|
||
</ul></div>
|
||
<p>
|
||
Each type has it's own advantages and disadvantages:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
Named utilities are easier to handle for simple synchronization tasks,
|
||
since both process don't have to create a shared memory region and
|
||
construct the synchronization mechanism there.
|
||
</li>
|
||
<li class="listitem">
|
||
Anonymous utilities can be serialized to disk when using memory mapped
|
||
objects obtaining automatic persistence of synchronization utilities.
|
||
One could construct a synchronization utility in a memory mapped file,
|
||
reboot the system, map the file again, and use the synchronization
|
||
utility again without any problem. This can't be achieved with named
|
||
synchronization utilities.
|
||
</li>
|
||
</ul></div>
|
||
<p>
|
||
The main interface difference between named and anonymous utilities are
|
||
the constructors. Usually anonymous utilities have only one constructor,
|
||
whereas the named utilities have several constructors whose first argument
|
||
is a special type that requests creation, opening or opening or creation
|
||
of the underlying resource:
|
||
</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="comment">//Create the synchronization utility. If it previously</span>
|
||
<span class="comment">//exists, throws an error</span>
|
||
<span class="identifier">NamedUtility</span><span class="special">(</span><span class="identifier">create_only</span><span class="special">,</span> <span class="special">...)</span>
|
||
|
||
<span class="comment">//Open the synchronization utility. If it does not previously</span>
|
||
<span class="comment">//exist, it's created.</span>
|
||
<span class="identifier">NamedUtility</span><span class="special">(</span><span class="identifier">open_or_create</span><span class="special">,</span> <span class="special">...)</span>
|
||
|
||
<span class="comment">//Open the synchronization utility. If it does not previously</span>
|
||
<span class="comment">//exist, throws an error.</span>
|
||
<span class="identifier">NamedUtility</span><span class="special">(</span><span class="identifier">open_only</span><span class="special">,</span> <span class="special">...)</span>
|
||
</pre>
|
||
<p>
|
||
On the other hand the anonymous synchronization utility can only be created
|
||
and the processes must synchronize using other mechanisms who creates the
|
||
utility:
|
||
</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="comment">//Create the synchronization utility.</span>
|
||
<span class="identifier">AnonymousUtility</span><span class="special">(...)</span>
|
||
</pre>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.synchronization_mechanisms_overview.synchronization_mechanisms_types"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.synchronization_mechanisms_overview.synchronization_mechanisms_types" title="Types Of Synchronization Mechanisms">Types
|
||
Of Synchronization Mechanisms</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
Apart from its named/anonymous nature, <span class="bold"><strong>Boost.Interprocess</strong></span>
|
||
presents the following synchronization utilities:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
Mutexes (named and anonymous)
|
||
</li>
|
||
<li class="listitem">
|
||
Condition variables (named and anonymous)
|
||
</li>
|
||
<li class="listitem">
|
||
Semaphores (named and anonymous)
|
||
</li>
|
||
<li class="listitem">
|
||
Upgradable mutexes
|
||
</li>
|
||
<li class="listitem">
|
||
File locks
|
||
</li>
|
||
</ul></div>
|
||
</div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h3 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.mutexes"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes" title="Mutexes">Mutexes</a>
|
||
</h3></div></div></div>
|
||
<div class="toc"><dl class="toc">
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes.mutexes_whats_a_mutex">What's
|
||
A Mutex?</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes.mutexes_mutex_operations">Mutex
|
||
Operations</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes.mutexes_interprocess_mutexes">Boost.Interprocess
|
||
Mutex Types And Headers</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes.mutexes_scoped_lock">Scoped
|
||
lock</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes.mutexes_anonymous_example">Anonymous
|
||
mutex example</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes.mutexes_named_example">Named
|
||
mutex example</a></span></dt>
|
||
</dl></div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.mutexes.mutexes_whats_a_mutex"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes.mutexes_whats_a_mutex" title="What's A Mutex?">What's
|
||
A Mutex?</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em>Mutex</em></span> stands for <span class="bold"><strong>mut</strong></span>ual
|
||
<span class="bold"><strong>ex</strong></span>clusion and it's the most basic form
|
||
of synchronization between processes. Mutexes guarantee that only one thread
|
||
can lock a given mutex. If a code section is surrounded by a mutex locking
|
||
and unlocking, it's guaranteed that only a thread at a time executes that
|
||
section of code. When that thread <span class="bold"><strong>unlocks</strong></span>
|
||
the mutex, other threads can enter to that code region:
|
||
</p>
|
||
<pre class="programlisting"><span class="comment">//The mutex has been previously constructed</span>
|
||
|
||
<span class="identifier">lock_the_mutex</span><span class="special">();</span>
|
||
|
||
<span class="comment">//This code will be executed only by one thread</span>
|
||
<span class="comment">//at a time.</span>
|
||
|
||
<span class="identifier">unlock_the_mutex</span><span class="special">();</span>
|
||
</pre>
|
||
<p>
|
||
A mutex can also be <span class="bold"><strong>recursive</strong></span> or <span class="bold"><strong>non-recursive</strong></span>:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
Recursive mutexes can be locked several times by the same thread. To
|
||
fully unlock the mutex, the thread has to unlock the mutex the same
|
||
times it has locked it.
|
||
</li>
|
||
<li class="listitem">
|
||
Non-recursive mutexes can't be locked several times by the same thread.
|
||
If a mutex is locked twice by a thread, the result is undefined, it
|
||
might throw an error or the thread could be blocked forever.
|
||
</li>
|
||
</ul></div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.mutexes.mutexes_mutex_operations"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes.mutexes_mutex_operations" title="Mutex Operations">Mutex
|
||
Operations</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
All the mutex types from <span class="bold"><strong>Boost.Interprocess</strong></span>
|
||
implement the following operations:
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>void lock()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread tries to obtain
|
||
ownership of the mutex, and if another thread has ownership of the mutex,
|
||
it waits until it can obtain the ownership. If a thread takes ownership
|
||
of the mutex the mutex must be unlocked by the same thread. If the mutex
|
||
supports recursive locking, the mutex must be unlocked the same number
|
||
of times it is locked.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> <span class="bold"><strong>interprocess_exception</strong></span>
|
||
on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>bool try_lock()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread tries to obtain
|
||
ownership of the mutex, and if another thread has ownership of the mutex
|
||
returns immediately. If the mutex supports recursive locking, the mutex
|
||
must be unlocked the same number of times it is locked.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Returns:</strong></span> If the thread acquires ownership
|
||
of the mutex, returns true, if the another thread has ownership of the
|
||
mutex, returns false.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> <span class="bold"><strong>interprocess_exception</strong></span>
|
||
on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>bool timed_lock(const boost::posix_time::ptime
|
||
&abs_time)</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread will try to
|
||
obtain exclusive ownership of the mutex if it can do so in until the specified
|
||
time is reached. If the mutex supports recursive locking, the mutex must
|
||
be unlocked the same number of times it is locked.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Returns:</strong></span> If the thread acquires ownership
|
||
of the mutex, returns true, if the timeout expires returns false.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> <span class="bold"><strong>interprocess_exception</strong></span>
|
||
on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>void unlock()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Precondition:</strong></span> The thread must have exclusive
|
||
ownership of the mutex.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread releases the
|
||
exclusive ownership of the mutex. If the mutex supports recursive locking,
|
||
the mutex must be unlocked the same number of times it is locked.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> An exception derived from <span class="bold"><strong>interprocess_exception</strong></span> on error.
|
||
</p>
|
||
<div class="important"><table border="0" summary="Important">
|
||
<tr>
|
||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../../doc/src/images/important.png"></td>
|
||
<th align="left">Important</th>
|
||
</tr>
|
||
<tr><td align="left" valign="top"><p>
|
||
<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">posix_time</span><span class="special">::</span><span class="identifier">ptime</span></code> absolute time points used by
|
||
Boost.Interprocess synchronization mechanisms are UTC time points, not
|
||
local time points
|
||
</p></td></tr>
|
||
</table></div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.mutexes.mutexes_interprocess_mutexes"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes.mutexes_interprocess_mutexes" title="Boost.Interprocess Mutex Types And Headers">Boost.Interprocess
|
||
Mutex Types And Headers</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
Boost.Interprocess offers the following mutex types:
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">interprocess_mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
||
<code class="computeroutput"><a class="link" href="../boost/interprocess/interprocess_mutex.html" title="Class interprocess_mutex">interprocess_mutex</a></code>:
|
||
A non-recursive, anonymous mutex that can be placed in shared memory
|
||
or memory mapped files.
|
||
</li></ul></div>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">interprocess_recursive_mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
||
<code class="computeroutput"><a class="link" href="../boost/interprocess/interpro_idm45189371318128.html" title="Class interprocess_recursive_mutex">interprocess_recursive_mutex</a></code>:
|
||
A recursive, anonymous mutex that can be placed in shared memory or
|
||
memory mapped files.
|
||
</li></ul></div>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">named_mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
||
<code class="computeroutput"><a class="link" href="../boost/interprocess/named_mutex.html" title="Class named_mutex">named_mutex</a></code>:
|
||
A non-recursive, named mutex.
|
||
</li></ul></div>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">named_recursive_mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
||
<code class="computeroutput"><a class="link" href="../boost/interprocess/named_recursive_mutex.html" title="Class named_recursive_mutex">named_recursive_mutex</a></code>:
|
||
A recursive, named mutex.
|
||
</li></ul></div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.mutexes.mutexes_scoped_lock"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes.mutexes_scoped_lock" title="Scoped lock">Scoped
|
||
lock</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
It's very important to unlock a mutex after the process has read or written
|
||
the data. This can be difficult when dealing with exceptions, so usually
|
||
mutexes are used with a scoped lock, a class that can guarantee that a
|
||
mutex will always be unlocked even when an exception occurs. To use a scoped
|
||
lock just include:
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">scoped_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
<p>
|
||
Basically, a scoped lock calls <span class="bold"><strong>unlock()</strong></span>
|
||
in its destructor, and a mutex is always unlocked when an exception occurs.
|
||
Scoped lock has many constructors to lock, try_lock, timed_lock a mutex
|
||
or not to lock it at all.
|
||
</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="comment">//Let's create any mutex type:</span>
|
||
<span class="identifier">MutexType</span> <span class="identifier">mutex</span><span class="special">;</span>
|
||
|
||
<span class="special">{</span>
|
||
<span class="comment">//This will lock the mutex</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">MutexType</span><span class="special">></span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">mutex</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Some code</span>
|
||
|
||
<span class="comment">//The mutex will be unlocked here</span>
|
||
<span class="special">}</span>
|
||
|
||
<span class="special">{</span>
|
||
<span class="comment">//This will try_lock the mutex</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">MutexType</span><span class="special">></span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">mutex</span><span class="special">,</span> <span class="identifier">try_to_lock</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Check if the mutex has been successfully locked</span>
|
||
<span class="keyword">if</span><span class="special">(</span><span class="identifier">lock</span><span class="special">){</span>
|
||
<span class="comment">//Some code</span>
|
||
<span class="special">}</span>
|
||
|
||
<span class="comment">//If the mutex was locked it will be unlocked</span>
|
||
<span class="special">}</span>
|
||
|
||
<span class="special">{</span>
|
||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">posix_time</span><span class="special">::</span><span class="identifier">ptime</span> <span class="identifier">abs_time</span> <span class="special">=</span> <span class="special">...</span>
|
||
|
||
<span class="comment">//This will timed_lock the mutex</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">MutexType</span><span class="special">></span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">mutex</span><span class="special">,</span> <span class="identifier">abs_time</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Check if the mutex has been successfully locked</span>
|
||
<span class="keyword">if</span><span class="special">(</span><span class="identifier">lock</span><span class="special">){</span>
|
||
<span class="comment">//Some code</span>
|
||
<span class="special">}</span>
|
||
|
||
<span class="comment">//If the mutex was locked it will be unlocked</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
<p>
|
||
For more information, check the <code class="computeroutput"><a class="link" href="../boost/interprocess/scoped_lock.html" title="Class template scoped_lock">scoped_lock's
|
||
reference</a></code>.
|
||
</p>
|
||
<div class="important"><table border="0" summary="Important">
|
||
<tr>
|
||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../../doc/src/images/important.png"></td>
|
||
<th align="left">Important</th>
|
||
</tr>
|
||
<tr><td align="left" valign="top"><p>
|
||
<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">posix_time</span><span class="special">::</span><span class="identifier">ptime</span></code> absolute time points used by
|
||
Boost.Interprocess synchronization mechanisms are UTC time points, not
|
||
local time points
|
||
</p></td></tr>
|
||
</table></div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.mutexes.mutexes_anonymous_example"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes.mutexes_anonymous_example" title="Anonymous mutex example">Anonymous
|
||
mutex example</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
Imagine that two processes need to write traces to a cyclic buffer built
|
||
in shared memory. Each process needs to obtain exclusive access to the
|
||
cyclic buffer, write the trace and continue.
|
||
</p>
|
||
<p>
|
||
To protect the cyclic buffer, we can store a process shared mutex in the
|
||
cyclic buffer. Each process will lock the mutex before writing the data
|
||
and will write a flag when ends writing the traces (<code class="computeroutput"><span class="identifier">doc_anonymous_mutex_shared_data</span><span class="special">.</span><span class="identifier">hpp</span></code>
|
||
header):
|
||
</p>
|
||
<p>
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">interprocess_mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
|
||
<span class="keyword">struct</span> <span class="identifier">shared_memory_log</span>
|
||
<span class="special">{</span>
|
||
<span class="keyword">enum</span> <span class="special">{</span> <span class="identifier">NumItems</span> <span class="special">=</span> <span class="number">100</span> <span class="special">};</span>
|
||
<span class="keyword">enum</span> <span class="special">{</span> <span class="identifier">LineSize</span> <span class="special">=</span> <span class="number">100</span> <span class="special">};</span>
|
||
|
||
<span class="identifier">shared_memory_log</span><span class="special">()</span>
|
||
<span class="special">:</span> <span class="identifier">current_line</span><span class="special">(</span><span class="number">0</span><span class="special">)</span>
|
||
<span class="special">,</span> <span class="identifier">end_a</span><span class="special">(</span><span class="keyword">false</span><span class="special">)</span>
|
||
<span class="special">,</span> <span class="identifier">end_b</span><span class="special">(</span><span class="keyword">false</span><span class="special">)</span>
|
||
<span class="special">{}</span>
|
||
|
||
<span class="comment">//Mutex to protect access to the queue</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</span><span class="special">;</span>
|
||
|
||
<span class="comment">//Items to fill</span>
|
||
<span class="keyword">char</span> <span class="identifier">items</span><span class="special">[</span><span class="identifier">NumItems</span><span class="special">][</span><span class="identifier">LineSize</span><span class="special">];</span>
|
||
<span class="keyword">int</span> <span class="identifier">current_line</span><span class="special">;</span>
|
||
<span class="keyword">bool</span> <span class="identifier">end_a</span><span class="special">;</span>
|
||
<span class="keyword">bool</span> <span class="identifier">end_b</span><span class="special">;</span>
|
||
<span class="special">};</span>
|
||
</pre>
|
||
<p>
|
||
</p>
|
||
<p>
|
||
This is the process main process. Creates the shared memory, constructs
|
||
the cyclic buffer and start writing traces:
|
||
</p>
|
||
<p>
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">shared_memory_object</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">mapped_region</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">scoped_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="string">"doc_anonymous_mutex_shared_data.hpp"</span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cstdio</span><span class="special">></span>
|
||
|
||
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span>
|
||
|
||
<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span>
|
||
<span class="special">{</span>
|
||
<span class="keyword">try</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 a shared memory object.</span>
|
||
<span class="identifier">shared_memory_object</span> <span class="identifier">shm</span>
|
||
<span class="special">(</span><span class="identifier">create_only</span> <span class="comment">//only create</span>
|
||
<span class="special">,</span><span class="string">"MySharedMemory"</span> <span class="comment">//name</span>
|
||
<span class="special">,</span><span class="identifier">read_write</span> <span class="comment">//read-write mode</span>
|
||
<span class="special">);</span>
|
||
|
||
<span class="comment">//Set size</span>
|
||
<span class="identifier">shm</span><span class="special">.</span><span class="identifier">truncate</span><span class="special">(</span><span class="keyword">sizeof</span><span class="special">(</span><span class="identifier">shared_memory_log</span><span class="special">));</span>
|
||
|
||
<span class="comment">//Map the whole shared memory in this process</span>
|
||
<span class="identifier">mapped_region</span> <span class="identifier">region</span>
|
||
<span class="special">(</span><span class="identifier">shm</span> <span class="comment">//What to map</span>
|
||
<span class="special">,</span><span class="identifier">read_write</span> <span class="comment">//Map it as read-write</span>
|
||
<span class="special">);</span>
|
||
|
||
<span class="comment">//Get the address of the mapped region</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>
|
||
|
||
<span class="comment">//Construct the shared structure in memory</span>
|
||
<span class="identifier">shared_memory_log</span> <span class="special">*</span> <span class="identifier">data</span> <span class="special">=</span> <span class="keyword">new</span> <span class="special">(</span><span class="identifier">addr</span><span class="special">)</span> <span class="identifier">shared_memory_log</span><span class="special">;</span>
|
||
|
||
<span class="comment">//Write some logs</span>
|
||
<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special"><</span> <span class="identifier">shared_memory_log</span><span class="special">::</span><span class="identifier">NumItems</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
|
||
<span class="comment">//Lock the mutex</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">interprocess_mutex</span><span class="special">></span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">data</span><span class="special">-></span><span class="identifier">mutex</span><span class="special">);</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">sprintf</span><span class="special">(</span><span class="identifier">data</span><span class="special">-></span><span class="identifier">items</span><span class="special">[(</span><span class="identifier">data</span><span class="special">-></span><span class="identifier">current_line</span><span class="special">++)</span> <span class="special">%</span> <span class="identifier">shared_memory_log</span><span class="special">::</span><span class="identifier">NumItems</span><span class="special">]</span>
|
||
<span class="special">,</span><span class="string">"%s_%d"</span><span class="special">,</span> <span class="string">"process_a"</span><span class="special">,</span> <span class="identifier">i</span><span class="special">);</span>
|
||
<span class="keyword">if</span><span class="special">(</span><span class="identifier">i</span> <span class="special">==</span> <span class="special">(</span><span class="identifier">shared_memory_log</span><span class="special">::</span><span class="identifier">NumItems</span><span class="special">-</span><span class="number">1</span><span class="special">))</span>
|
||
<span class="identifier">data</span><span class="special">-></span><span class="identifier">end_a</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span>
|
||
<span class="comment">//Mutex is released here</span>
|
||
<span class="special">}</span>
|
||
|
||
<span class="comment">//Wait until the other process ends</span>
|
||
<span class="keyword">while</span><span class="special">(</span><span class="number">1</span><span class="special">){</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">interprocess_mutex</span><span class="special">></span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">data</span><span class="special">-></span><span class="identifier">mutex</span><span class="special">);</span>
|
||
<span class="keyword">if</span><span class="special">(</span><span class="identifier">data</span><span class="special">-></span><span class="identifier">end_b</span><span class="special">)</span>
|
||
<span class="keyword">break</span><span class="special">;</span>
|
||
<span class="special">}</span>
|
||
<span class="special">}</span>
|
||
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">interprocess_exception</span> <span class="special">&</span><span class="identifier">ex</span><span class="special">){</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">ex</span><span class="special">.</span><span class="identifier">what</span><span class="special">()</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</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">return</span> <span class="number">0</span><span class="special">;</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
<p>
|
||
</p>
|
||
<p>
|
||
The second process opens the shared memory, obtains access to the cyclic
|
||
buffer and starts writing traces:
|
||
</p>
|
||
<p>
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">shared_memory_object</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">mapped_region</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">scoped_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="string">"doc_anonymous_mutex_shared_data.hpp"</span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cstdio</span><span class="special">></span>
|
||
|
||
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span>
|
||
|
||
<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span>
|
||
<span class="special">{</span>
|
||
<span class="comment">//Remove shared memory on destruction</span>
|
||
<span class="keyword">struct</span> <span class="identifier">shm_remove</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">//Open the shared memory object.</span>
|
||
<span class="identifier">shared_memory_object</span> <span class="identifier">shm</span>
|
||
<span class="special">(</span><span class="identifier">open_only</span> <span class="comment">//only create</span>
|
||
<span class="special">,</span><span class="string">"MySharedMemory"</span> <span class="comment">//name</span>
|
||
<span class="special">,</span><span class="identifier">read_write</span> <span class="comment">//read-write mode</span>
|
||
<span class="special">);</span>
|
||
|
||
<span class="comment">//Map the whole shared memory in this process</span>
|
||
<span class="identifier">mapped_region</span> <span class="identifier">region</span>
|
||
<span class="special">(</span><span class="identifier">shm</span> <span class="comment">//What to map</span>
|
||
<span class="special">,</span><span class="identifier">read_write</span> <span class="comment">//Map it as read-write</span>
|
||
<span class="special">);</span>
|
||
|
||
<span class="comment">//Get the address of the mapped region</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>
|
||
|
||
<span class="comment">//Construct the shared structure in memory</span>
|
||
<span class="identifier">shared_memory_log</span> <span class="special">*</span> <span class="identifier">data</span> <span class="special">=</span> <span class="keyword">static_cast</span><span class="special"><</span><span class="identifier">shared_memory_log</span><span class="special">*>(</span><span class="identifier">addr</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Write some logs</span>
|
||
<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special"><</span> <span class="number">100</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
|
||
<span class="comment">//Lock the mutex</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">interprocess_mutex</span><span class="special">></span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">data</span><span class="special">-></span><span class="identifier">mutex</span><span class="special">);</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">sprintf</span><span class="special">(</span><span class="identifier">data</span><span class="special">-></span><span class="identifier">items</span><span class="special">[(</span><span class="identifier">data</span><span class="special">-></span><span class="identifier">current_line</span><span class="special">++)</span> <span class="special">%</span> <span class="identifier">shared_memory_log</span><span class="special">::</span><span class="identifier">NumItems</span><span class="special">]</span>
|
||
<span class="special">,</span><span class="string">"%s_%d"</span><span class="special">,</span> <span class="string">"process_a"</span><span class="special">,</span> <span class="identifier">i</span><span class="special">);</span>
|
||
<span class="keyword">if</span><span class="special">(</span><span class="identifier">i</span> <span class="special">==</span> <span class="special">(</span><span class="identifier">shared_memory_log</span><span class="special">::</span><span class="identifier">NumItems</span><span class="special">-</span><span class="number">1</span><span class="special">))</span>
|
||
<span class="identifier">data</span><span class="special">-></span><span class="identifier">end_b</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span>
|
||
<span class="comment">//Mutex is released here</span>
|
||
<span class="special">}</span>
|
||
|
||
<span class="comment">//Wait until the other process ends</span>
|
||
<span class="keyword">while</span><span class="special">(</span><span class="number">1</span><span class="special">){</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">interprocess_mutex</span><span class="special">></span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">data</span><span class="special">-></span><span class="identifier">mutex</span><span class="special">);</span>
|
||
<span class="keyword">if</span><span class="special">(</span><span class="identifier">data</span><span class="special">-></span><span class="identifier">end_a</span><span class="special">)</span>
|
||
<span class="keyword">break</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>
|
||
As we can see, a mutex is useful to protect data but not to notify an event
|
||
to another process. For this, we need a condition variable, as we will
|
||
see in the next section.
|
||
</p>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.mutexes.mutexes_named_example"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.mutexes.mutexes_named_example" title="Named mutex example">Named
|
||
mutex example</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
Now imagine that two processes want to write a trace to a file. First they
|
||
write their name, and after that they write the message. Since the operating
|
||
system can interrupt a process in any moment we can mix parts of the messages
|
||
of both processes, so we need a way to write the whole message to the file
|
||
atomically. To achieve this, we can use a named mutex so that each process
|
||
locks the mutex before writing:
|
||
</p>
|
||
<p>
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">scoped_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">named_mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">fstream</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cstdio</span><span class="special">></span>
|
||
|
||
|
||
<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span>
|
||
<span class="special">{</span>
|
||
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span>
|
||
<span class="keyword">try</span><span class="special">{</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="special">{</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"file_name"</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">std</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"file_name"</span><span class="special">);</span> <span class="special">}</span>
|
||
<span class="special">}</span> <span class="identifier">file_remover</span><span class="special">;</span>
|
||
<span class="keyword">struct</span> <span class="identifier">mutex_remove</span>
|
||
<span class="special">{</span>
|
||
<span class="identifier">mutex_remove</span><span class="special">()</span> <span class="special">{</span> <span class="identifier">named_mutex</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"fstream_named_mutex"</span><span class="special">);</span> <span class="special">}</span>
|
||
<span class="special">~</span><span class="identifier">mutex_remove</span><span class="special">(){</span> <span class="identifier">named_mutex</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"fstream_named_mutex"</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">//Open or create the named mutex</span>
|
||
<span class="identifier">named_mutex</span> <span class="identifier">mutex</span><span class="special">(</span><span class="identifier">open_or_create</span><span class="special">,</span> <span class="string">"fstream_named_mutex"</span><span class="special">);</span>
|
||
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">ofstream</span> <span class="identifier">file</span><span class="special">(</span><span class="string">"file_name"</span><span class="special">);</span>
|
||
|
||
<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special"><</span> <span class="number">10</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
|
||
|
||
<span class="comment">//Do some operations...</span>
|
||
|
||
<span class="comment">//Write to file atomically</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">named_mutex</span><span class="special">></span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">mutex</span><span class="special">);</span>
|
||
<span class="identifier">file</span> <span class="special"><<</span> <span class="string">"Process name, "</span><span class="special">;</span>
|
||
<span class="identifier">file</span> <span class="special"><<</span> <span class="string">"This is iteration #"</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">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
|
||
<span class="special">}</span>
|
||
<span class="special">}</span>
|
||
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">interprocess_exception</span> <span class="special">&</span><span class="identifier">ex</span><span class="special">){</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">ex</span><span class="special">.</span><span class="identifier">what</span><span class="special">()</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</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">return</span> <span class="number">0</span><span class="special">;</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
<p>
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h3 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.conditions"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.conditions" title="Conditions">Conditions</a>
|
||
</h3></div></div></div>
|
||
<div class="toc"><dl class="toc">
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.conditions.conditions_whats_a_condition">What's
|
||
A Condition Variable?</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.conditions.conditions_interprocess_conditions">Boost.Interprocess
|
||
Condition Types And Headers</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.conditions.conditions_anonymous_example">Anonymous
|
||
condition example</a></span></dt>
|
||
</dl></div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.conditions.conditions_whats_a_condition"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.conditions.conditions_whats_a_condition" title="What's A Condition Variable?">What's
|
||
A Condition Variable?</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
In the previous example, a mutex is used to <span class="emphasis"><em>lock</em></span> but
|
||
we can't use it to <span class="emphasis"><em>wait</em></span> efficiently until the condition
|
||
to continue is met. A condition variable can do two things:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
<span class="bold"><strong>wait</strong></span>: The thread is blocked until
|
||
some other thread notifies that it can continue because the condition
|
||
that lead to waiting has disappeared.
|
||
</li>
|
||
<li class="listitem">
|
||
<span class="bold"><strong>notify</strong></span>: The thread sends a signal
|
||
to one blocked thread or to all blocked threads to tell them that they
|
||
the condition that provoked their wait has disappeared.
|
||
</li>
|
||
</ul></div>
|
||
<p>
|
||
Waiting in a condition variable is always associated with a mutex. The
|
||
mutex must be locked prior to waiting on the condition. When waiting on
|
||
the condition variable, the thread unlocks the mutex and waits <span class="bold"><strong>atomically</strong></span>.
|
||
</p>
|
||
<p>
|
||
When the thread returns from a wait function (because of a signal or a
|
||
timeout, for example) the mutex object is again locked.
|
||
</p>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.conditions.conditions_interprocess_conditions"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.conditions.conditions_interprocess_conditions" title="Boost.Interprocess Condition Types And Headers">Boost.Interprocess
|
||
Condition Types And Headers</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
Boost.Interprocess offers the following condition types:
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">interprocess_condition</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
||
<code class="computeroutput"><a class="link" href="../boost/interprocess/interprocess_condition.html" title="Class interprocess_condition">interprocess_condition</a></code>:
|
||
An anonymous condition variable that can be placed in shared memory
|
||
or memory mapped files to be used with <code class="computeroutput"><a class="link" href="../boost/interprocess/interprocess_mutex.html" title="Class interprocess_mutex">boost::interprocess::interprocess_mutex</a></code>.
|
||
</li></ul></div>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">interprocess_condition_any</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
||
<code class="computeroutput"><a class="link" href="../boost/interprocess/interprocess_condition_any.html" title="Class interprocess_condition_any">interprocess_condition_any</a></code>:
|
||
An anonymous condition variable that can be placed in shared memory
|
||
or memory mapped files to be used with any lock type.
|
||
</li></ul></div>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">named_condition</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
||
<code class="computeroutput"><a class="link" href="../boost/interprocess/named_condition.html" title="Class named_condition">named_condition</a></code>:
|
||
A named condition variable to be used with <code class="computeroutput"><a class="link" href="../boost/interprocess/named_mutex.html" title="Class named_mutex">named_mutex</a></code>.
|
||
</li></ul></div>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">named_condition_any</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
||
<code class="computeroutput"><a class="link" href="../boost/interprocess/named_condition_any.html" title="Class named_condition_any">named_condition_any</a></code>:
|
||
A named condition variable to be used with any lock type.
|
||
</li></ul></div>
|
||
<p>
|
||
Named conditions are similar to anonymous conditions, but they are used
|
||
in combination with named mutexes. Several times, we don't want to store
|
||
synchronization objects with the synchronized data:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
We want to change the synchronization method (from interprocess to
|
||
intra-process, or without any synchronization) using the same data.
|
||
Storing the process-shared anonymous synchronization with the synchronized
|
||
data would forbid this.
|
||
</li>
|
||
<li class="listitem">
|
||
We want to send the synchronized data through the network or any other
|
||
communication method. Sending the process-shared synchronization objects
|
||
wouldn't have any sense.
|
||
</li>
|
||
</ul></div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.conditions.conditions_anonymous_example"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.conditions.conditions_anonymous_example" title="Anonymous condition example">Anonymous
|
||
condition example</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
Imagine that a process that writes a trace to a simple shared memory buffer
|
||
that another process prints one by one. The first process writes the trace
|
||
and waits until the other process prints the data. To achieve this, we
|
||
can use two condition variables: the first one is used to block the sender
|
||
until the second process prints the message and the second one to block
|
||
the receiver until the buffer has a trace to print.
|
||
</p>
|
||
<p>
|
||
The shared memory trace buffer (doc_anonymous_condition_shared_data.hpp):
|
||
</p>
|
||
<p>
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">interprocess_mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">interprocess_condition</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
|
||
<span class="keyword">struct</span> <span class="identifier">trace_queue</span>
|
||
<span class="special">{</span>
|
||
<span class="keyword">enum</span> <span class="special">{</span> <span class="identifier">LineSize</span> <span class="special">=</span> <span class="number">100</span> <span class="special">};</span>
|
||
|
||
<span class="identifier">trace_queue</span><span class="special">()</span>
|
||
<span class="special">:</span> <span class="identifier">message_in</span><span class="special">(</span><span class="keyword">false</span><span class="special">)</span>
|
||
<span class="special">{}</span>
|
||
|
||
<span class="comment">//Mutex to protect access to the queue</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</span><span class="special">;</span>
|
||
|
||
<span class="comment">//Condition to wait when the queue is empty</span>
|
||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">interprocess_condition</span> <span class="identifier">cond_empty</span><span class="special">;</span>
|
||
|
||
<span class="comment">//Condition to wait when the queue is full</span>
|
||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">interprocess_condition</span> <span class="identifier">cond_full</span><span class="special">;</span>
|
||
|
||
<span class="comment">//Items to fill</span>
|
||
<span class="keyword">char</span> <span class="identifier">items</span><span class="special">[</span><span class="identifier">LineSize</span><span class="special">];</span>
|
||
|
||
<span class="comment">//Is there any message</span>
|
||
<span class="keyword">bool</span> <span class="identifier">message_in</span><span class="special">;</span>
|
||
<span class="special">};</span>
|
||
</pre>
|
||
<p>
|
||
</p>
|
||
<p>
|
||
This is the process main process. Creates the shared memory, places there
|
||
the buffer and starts writing messages one by one until it writes "last
|
||
message" to indicate that there are no more messages to print:
|
||
</p>
|
||
<p>
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">shared_memory_object</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">mapped_region</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">scoped_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cstdio</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="string">"doc_anonymous_condition_shared_data.hpp"</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">//Erase previous shared memory and schedule erasure on exit</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 shared memory object.</span>
|
||
<span class="identifier">shared_memory_object</span> <span class="identifier">shm</span>
|
||
<span class="special">(</span><span class="identifier">create_only</span> <span class="comment">//only create</span>
|
||
<span class="special">,</span><span class="string">"MySharedMemory"</span> <span class="comment">//name</span>
|
||
<span class="special">,</span><span class="identifier">read_write</span> <span class="comment">//read-write mode</span>
|
||
<span class="special">);</span>
|
||
<span class="keyword">try</span><span class="special">{</span>
|
||
<span class="comment">//Set size</span>
|
||
<span class="identifier">shm</span><span class="special">.</span><span class="identifier">truncate</span><span class="special">(</span><span class="keyword">sizeof</span><span class="special">(</span><span class="identifier">trace_queue</span><span class="special">));</span>
|
||
|
||
<span class="comment">//Map the whole shared memory in this process</span>
|
||
<span class="identifier">mapped_region</span> <span class="identifier">region</span>
|
||
<span class="special">(</span><span class="identifier">shm</span> <span class="comment">//What to map</span>
|
||
<span class="special">,</span><span class="identifier">read_write</span> <span class="comment">//Map it as read-write</span>
|
||
<span class="special">);</span>
|
||
|
||
<span class="comment">//Get the address of the mapped region</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>
|
||
|
||
<span class="comment">//Construct the shared structure in memory</span>
|
||
<span class="identifier">trace_queue</span> <span class="special">*</span> <span class="identifier">data</span> <span class="special">=</span> <span class="keyword">new</span> <span class="special">(</span><span class="identifier">addr</span><span class="special">)</span> <span class="identifier">trace_queue</span><span class="special">;</span>
|
||
|
||
<span class="keyword">const</span> <span class="keyword">int</span> <span class="identifier">NumMsg</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"><</span> <span class="identifier">NumMsg</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">interprocess_mutex</span><span class="special">></span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">data</span><span class="special">-></span><span class="identifier">mutex</span><span class="special">);</span>
|
||
<span class="keyword">if</span><span class="special">(</span><span class="identifier">data</span><span class="special">-></span><span class="identifier">message_in</span><span class="special">){</span>
|
||
<span class="identifier">data</span><span class="special">-></span><span class="identifier">cond_full</span><span class="special">.</span><span class="identifier">wait</span><span class="special">(</span><span class="identifier">lock</span><span class="special">);</span>
|
||
<span class="special">}</span>
|
||
<span class="keyword">if</span><span class="special">(</span><span class="identifier">i</span> <span class="special">==</span> <span class="special">(</span><span class="identifier">NumMsg</span><span class="special">-</span><span class="number">1</span><span class="special">))</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">sprintf</span><span class="special">(</span><span class="identifier">data</span><span class="special">-></span><span class="identifier">items</span><span class="special">,</span> <span class="string">"%s"</span><span class="special">,</span> <span class="string">"last message"</span><span class="special">);</span>
|
||
<span class="keyword">else</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">sprintf</span><span class="special">(</span><span class="identifier">data</span><span class="special">-></span><span class="identifier">items</span><span class="special">,</span> <span class="string">"%s_%d"</span><span class="special">,</span> <span class="string">"my_trace"</span><span class="special">,</span> <span class="identifier">i</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Notify to the other process that there is a message</span>
|
||
<span class="identifier">data</span><span class="special">-></span><span class="identifier">cond_empty</span><span class="special">.</span><span class="identifier">notify_one</span><span class="special">();</span>
|
||
|
||
<span class="comment">//Mark message buffer as full</span>
|
||
<span class="identifier">data</span><span class="special">-></span><span class="identifier">message_in</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span>
|
||
<span class="special">}</span>
|
||
<span class="special">}</span>
|
||
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">interprocess_exception</span> <span class="special">&</span><span class="identifier">ex</span><span class="special">){</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">ex</span><span class="special">.</span><span class="identifier">what</span><span class="special">()</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</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">return</span> <span class="number">0</span><span class="special">;</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
<p>
|
||
</p>
|
||
<p>
|
||
The second process opens the shared memory and prints each message until
|
||
the "last message" message is received:
|
||
</p>
|
||
<p>
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">shared_memory_object</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">mapped_region</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">scoped_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">cstring</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="string">"doc_anonymous_condition_shared_data.hpp"</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">//Create a shared memory object.</span>
|
||
<span class="identifier">shared_memory_object</span> <span class="identifier">shm</span>
|
||
<span class="special">(</span><span class="identifier">open_only</span> <span class="comment">//only create</span>
|
||
<span class="special">,</span><span class="string">"MySharedMemory"</span> <span class="comment">//name</span>
|
||
<span class="special">,</span><span class="identifier">read_write</span> <span class="comment">//read-write mode</span>
|
||
<span class="special">);</span>
|
||
|
||
<span class="keyword">try</span><span class="special">{</span>
|
||
<span class="comment">//Map the whole shared memory in this process</span>
|
||
<span class="identifier">mapped_region</span> <span class="identifier">region</span>
|
||
<span class="special">(</span><span class="identifier">shm</span> <span class="comment">//What to map</span>
|
||
<span class="special">,</span><span class="identifier">read_write</span> <span class="comment">//Map it as read-write</span>
|
||
<span class="special">);</span>
|
||
|
||
<span class="comment">//Get the address of the mapped region</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>
|
||
|
||
<span class="comment">//Obtain a pointer to the shared structure</span>
|
||
<span class="identifier">trace_queue</span> <span class="special">*</span> <span class="identifier">data</span> <span class="special">=</span> <span class="keyword">static_cast</span><span class="special"><</span><span class="identifier">trace_queue</span><span class="special">*>(</span><span class="identifier">addr</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Print messages until the other process marks the end</span>
|
||
<span class="keyword">bool</span> <span class="identifier">end_loop</span> <span class="special">=</span> <span class="keyword">false</span><span class="special">;</span>
|
||
<span class="keyword">do</span><span class="special">{</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">interprocess_mutex</span><span class="special">></span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">data</span><span class="special">-></span><span class="identifier">mutex</span><span class="special">);</span>
|
||
<span class="keyword">if</span><span class="special">(!</span><span class="identifier">data</span><span class="special">-></span><span class="identifier">message_in</span><span class="special">){</span>
|
||
<span class="identifier">data</span><span class="special">-></span><span class="identifier">cond_empty</span><span class="special">.</span><span class="identifier">wait</span><span class="special">(</span><span class="identifier">lock</span><span class="special">);</span>
|
||
<span class="special">}</span>
|
||
<span class="keyword">if</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">strcmp</span><span class="special">(</span><span class="identifier">data</span><span class="special">-></span><span class="identifier">items</span><span class="special">,</span> <span class="string">"last message"</span><span class="special">)</span> <span class="special">==</span> <span class="number">0</span><span class="special">){</span>
|
||
<span class="identifier">end_loop</span> <span class="special">=</span> <span class="keyword">true</span><span class="special">;</span>
|
||
<span class="special">}</span>
|
||
<span class="keyword">else</span><span class="special">{</span>
|
||
<span class="comment">//Print the message</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">data</span><span class="special">-></span><span class="identifier">items</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
|
||
<span class="comment">//Notify the other process that the buffer is empty</span>
|
||
<span class="identifier">data</span><span class="special">-></span><span class="identifier">message_in</span> <span class="special">=</span> <span class="keyword">false</span><span class="special">;</span>
|
||
<span class="identifier">data</span><span class="special">-></span><span class="identifier">cond_full</span><span class="special">.</span><span class="identifier">notify_one</span><span class="special">();</span>
|
||
<span class="special">}</span>
|
||
<span class="special">}</span>
|
||
<span class="keyword">while</span><span class="special">(!</span><span class="identifier">end_loop</span><span class="special">);</span>
|
||
<span class="special">}</span>
|
||
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">interprocess_exception</span> <span class="special">&</span><span class="identifier">ex</span><span class="special">){</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">ex</span><span class="special">.</span><span class="identifier">what</span><span class="special">()</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</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">return</span> <span class="number">0</span><span class="special">;</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
<p>
|
||
</p>
|
||
<p>
|
||
With condition variables, a process can block if it can't continue the
|
||
work, and when the conditions to continue are met another process can wake
|
||
it.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h3 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.semaphores"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.semaphores" title="Semaphores">Semaphores</a>
|
||
</h3></div></div></div>
|
||
<div class="toc"><dl class="toc">
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.semaphores.semaphores_whats_a_semaphores">What's
|
||
A Semaphore?</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.semaphores.semaphores_interprocess_semaphores">Boost.Interprocess
|
||
Semaphore Types And Headers</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.semaphores.semaphores_anonymous_example">Anonymous
|
||
semaphore example</a></span></dt>
|
||
</dl></div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.semaphores.semaphores_whats_a_semaphores"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.semaphores.semaphores_whats_a_semaphores" title="What's A Semaphore?">What's
|
||
A Semaphore?</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
A semaphore is a synchronization mechanism between processes based in an
|
||
internal count that offers two basic operations:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
<span class="bold"><strong>Wait</strong></span>: Tests the value of the semaphore
|
||
count, and waits if the value is less than or equal than 0. Otherwise,
|
||
decrements the semaphore count.
|
||
</li>
|
||
<li class="listitem">
|
||
<span class="bold"><strong>Post</strong></span>: Increments the semaphore count.
|
||
If any process is blocked, one of those processes is awoken.
|
||
</li>
|
||
</ul></div>
|
||
<p>
|
||
If the initial semaphore count is initialized to 1, a <span class="bold"><strong>Wait</strong></span>
|
||
operation is equivalent to a mutex locking and <span class="bold"><strong>Post</strong></span>
|
||
is equivalent to a mutex unlocking. This type of semaphore is known as
|
||
a <span class="bold"><strong>binary semaphore</strong></span>.
|
||
</p>
|
||
<p>
|
||
Although semaphores can be used like mutexes, they have a unique feature:
|
||
unlike mutexes, a <span class="bold"><strong>Post</strong></span> operation need
|
||
not be executed by the same thread/process that executed the <span class="bold"><strong>Wait</strong></span> operation.
|
||
</p>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.semaphores.semaphores_interprocess_semaphores"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.semaphores.semaphores_interprocess_semaphores" title="Boost.Interprocess Semaphore Types And Headers">Boost.Interprocess
|
||
Semaphore Types And Headers</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
Boost.Interprocess offers the following semaphore types:
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">interprocess_semaphore</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
||
<code class="computeroutput"><a class="link" href="../boost/interprocess/interprocess_semaphore.html" title="Class interprocess_semaphore">interprocess_semaphore</a></code>:
|
||
An anonymous semaphore that can be placed in shared memory or memory
|
||
mapped files.
|
||
</li></ul></div>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">named_semaphore</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
||
<code class="computeroutput"><a class="link" href="../boost/interprocess/named_semaphore.html" title="Class named_semaphore">named_semaphore</a></code>:
|
||
A named semaphore.
|
||
</li></ul></div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.semaphores.semaphores_anonymous_example"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.semaphores.semaphores_anonymous_example" title="Anonymous semaphore example">Anonymous
|
||
semaphore example</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
We will implement an integer array in shared memory that will be used to
|
||
transfer data from one process to another process. The first process will
|
||
write some integers to the array and the process will block if the array
|
||
is full.
|
||
</p>
|
||
<p>
|
||
The second process will copy the transmitted data to its own buffer, blocking
|
||
if there is no new data in the buffer.
|
||
</p>
|
||
<p>
|
||
This is the shared integer array (doc_anonymous_semaphore_shared_data.hpp):
|
||
</p>
|
||
<p>
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">interprocess_semaphore</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
|
||
<span class="keyword">struct</span> <span class="identifier">shared_memory_buffer</span>
|
||
<span class="special">{</span>
|
||
<span class="keyword">enum</span> <span class="special">{</span> <span class="identifier">NumItems</span> <span class="special">=</span> <span class="number">10</span> <span class="special">};</span>
|
||
|
||
<span class="identifier">shared_memory_buffer</span><span class="special">()</span>
|
||
<span class="special">:</span> <span class="identifier">mutex</span><span class="special">(</span><span class="number">1</span><span class="special">),</span> <span class="identifier">nempty</span><span class="special">(</span><span class="identifier">NumItems</span><span class="special">),</span> <span class="identifier">nstored</span><span class="special">(</span><span class="number">0</span><span class="special">)</span>
|
||
<span class="special">{}</span>
|
||
|
||
<span class="comment">//Semaphores to protect and synchronize access</span>
|
||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">interprocess_semaphore</span>
|
||
<span class="identifier">mutex</span><span class="special">,</span> <span class="identifier">nempty</span><span class="special">,</span> <span class="identifier">nstored</span><span class="special">;</span>
|
||
|
||
<span class="comment">//Items to fill</span>
|
||
<span class="keyword">int</span> <span class="identifier">items</span><span class="special">[</span><span class="identifier">NumItems</span><span class="special">];</span>
|
||
<span class="special">};</span>
|
||
</pre>
|
||
<p>
|
||
</p>
|
||
<p>
|
||
This is the process main process. Creates the shared memory, places there
|
||
the integer array and starts integers one by one, blocking if the array
|
||
is full:
|
||
</p>
|
||
<p>
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">shared_memory_object</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">mapped_region</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="string">"doc_anonymous_semaphore_shared_data.hpp"</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 a shared memory object.</span>
|
||
<span class="identifier">shared_memory_object</span> <span class="identifier">shm</span>
|
||
<span class="special">(</span><span class="identifier">create_only</span> <span class="comment">//only create</span>
|
||
<span class="special">,</span><span class="string">"MySharedMemory"</span> <span class="comment">//name</span>
|
||
<span class="special">,</span><span class="identifier">read_write</span> <span class="comment">//read-write mode</span>
|
||
<span class="special">);</span>
|
||
|
||
<span class="comment">//Set size</span>
|
||
<span class="identifier">shm</span><span class="special">.</span><span class="identifier">truncate</span><span class="special">(</span><span class="keyword">sizeof</span><span class="special">(</span><span class="identifier">shared_memory_buffer</span><span class="special">));</span>
|
||
|
||
<span class="comment">//Map the whole shared memory in this process</span>
|
||
<span class="identifier">mapped_region</span> <span class="identifier">region</span>
|
||
<span class="special">(</span><span class="identifier">shm</span> <span class="comment">//What to map</span>
|
||
<span class="special">,</span><span class="identifier">read_write</span> <span class="comment">//Map it as read-write</span>
|
||
<span class="special">);</span>
|
||
|
||
<span class="comment">//Get the address of the mapped region</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>
|
||
|
||
<span class="comment">//Construct the shared structure in memory</span>
|
||
<span class="identifier">shared_memory_buffer</span> <span class="special">*</span> <span class="identifier">data</span> <span class="special">=</span> <span class="keyword">new</span> <span class="special">(</span><span class="identifier">addr</span><span class="special">)</span> <span class="identifier">shared_memory_buffer</span><span class="special">;</span>
|
||
|
||
<span class="keyword">const</span> <span class="keyword">int</span> <span class="identifier">NumMsg</span> <span class="special">=</span> <span class="number">100</span><span class="special">;</span>
|
||
|
||
<span class="comment">//Insert data in the array</span>
|
||
<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special"><</span> <span class="identifier">NumMsg</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">nempty</span><span class="special">.</span><span class="identifier">wait</span><span class="special">();</span>
|
||
<span class="identifier">data</span><span class="special">-></span><span class="identifier">mutex</span><span class="special">.</span><span class="identifier">wait</span><span class="special">();</span>
|
||
<span class="identifier">data</span><span class="special">-></span><span class="identifier">items</span><span class="special">[</span><span class="identifier">i</span> <span class="special">%</span> <span class="identifier">shared_memory_buffer</span><span class="special">::</span><span class="identifier">NumItems</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">mutex</span><span class="special">.</span><span class="identifier">post</span><span class="special">();</span>
|
||
<span class="identifier">data</span><span class="special">-></span><span class="identifier">nstored</span><span class="special">.</span><span class="identifier">post</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 second process opens the shared memory and copies the received integers
|
||
to it's own buffer:
|
||
</p>
|
||
<p>
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">shared_memory_object</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">mapped_region</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="string">"doc_anonymous_semaphore_shared_data.hpp"</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 destruction</span>
|
||
<span class="keyword">struct</span> <span class="identifier">shm_remove</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 shared memory object.</span>
|
||
<span class="identifier">shared_memory_object</span> <span class="identifier">shm</span>
|
||
<span class="special">(</span><span class="identifier">open_only</span> <span class="comment">//only create</span>
|
||
<span class="special">,</span><span class="string">"MySharedMemory"</span> <span class="comment">//name</span>
|
||
<span class="special">,</span><span class="identifier">read_write</span> <span class="comment">//read-write mode</span>
|
||
<span class="special">);</span>
|
||
|
||
<span class="comment">//Map the whole shared memory in this process</span>
|
||
<span class="identifier">mapped_region</span> <span class="identifier">region</span>
|
||
<span class="special">(</span><span class="identifier">shm</span> <span class="comment">//What to map</span>
|
||
<span class="special">,</span><span class="identifier">read_write</span> <span class="comment">//Map it as read-write</span>
|
||
<span class="special">);</span>
|
||
|
||
<span class="comment">//Get the address of the mapped region</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>
|
||
|
||
<span class="comment">//Obtain the shared structure</span>
|
||
<span class="identifier">shared_memory_buffer</span> <span class="special">*</span> <span class="identifier">data</span> <span class="special">=</span> <span class="keyword">static_cast</span><span class="special"><</span><span class="identifier">shared_memory_buffer</span><span class="special">*>(</span><span class="identifier">addr</span><span class="special">);</span>
|
||
|
||
<span class="keyword">const</span> <span class="keyword">int</span> <span class="identifier">NumMsg</span> <span class="special">=</span> <span class="number">100</span><span class="special">;</span>
|
||
|
||
<span class="keyword">int</span> <span class="identifier">extracted_data</span> <span class="special">[</span><span class="identifier">NumMsg</span><span class="special">];</span>
|
||
|
||
<span class="comment">//Extract the data</span>
|
||
<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special"><</span> <span class="identifier">NumMsg</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">nstored</span><span class="special">.</span><span class="identifier">wait</span><span class="special">();</span>
|
||
<span class="identifier">data</span><span class="special">-></span><span class="identifier">mutex</span><span class="special">.</span><span class="identifier">wait</span><span class="special">();</span>
|
||
<span class="identifier">extracted_data</span><span class="special">[</span><span class="identifier">i</span><span class="special">]</span> <span class="special">=</span> <span class="identifier">data</span><span class="special">-></span><span class="identifier">items</span><span class="special">[</span><span class="identifier">i</span> <span class="special">%</span> <span class="identifier">shared_memory_buffer</span><span class="special">::</span><span class="identifier">NumItems</span><span class="special">];</span>
|
||
<span class="identifier">data</span><span class="special">-></span><span class="identifier">mutex</span><span class="special">.</span><span class="identifier">post</span><span class="special">();</span>
|
||
<span class="identifier">data</span><span class="special">-></span><span class="identifier">nempty</span><span class="special">.</span><span class="identifier">post</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 same interprocess communication can be achieved with a condition variables
|
||
and mutexes, but for several synchronization patterns, a semaphore is more
|
||
efficient than a mutex/condition combination.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h3 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.sharable_upgradable_mutexes"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes" title="Sharable and Upgradable Mutexes">Sharable
|
||
and Upgradable Mutexes</a>
|
||
</h3></div></div></div>
|
||
<div class="toc"><dl class="toc">
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.upgradable_whats_a_mutex">What's
|
||
a Sharable and an Upgradable Mutex?</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.upgradable_transitions">Lock
|
||
transitions for Upgradable Mutex</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_operations">Upgradable
|
||
Mutex Operations</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_mutex_interprocess_mutexes">Boost.Interprocess
|
||
Sharable & Upgradable Mutex Types And Headers</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_locks">Sharable
|
||
Lock And Upgradable Lock</a></span></dt>
|
||
</dl></div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.upgradable_whats_a_mutex"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.upgradable_whats_a_mutex" title="What's a Sharable and an Upgradable Mutex?">What's
|
||
a Sharable and an Upgradable Mutex?</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
Sharable and upgradable mutex are special mutex types that offers more
|
||
locking possibilities than a normal mutex. Sometimes, we can distinguish
|
||
between <span class="bold"><strong>reading</strong></span> the data and <span class="bold"><strong>modifying</strong></span> the data. If just some threads need to
|
||
modify the data, and a plain mutex is used to protect the data from concurrent
|
||
access, concurrency is pretty limited: two threads that only read the data
|
||
will be serialized instead of being executed concurrently.
|
||
</p>
|
||
<p>
|
||
If we allow concurrent access to threads that just read the data but we
|
||
avoid concurrent access between threads that read and modify or between
|
||
threads that modify, we can increase performance. This is specially true
|
||
in applications where data reading is more common than data modification
|
||
and the synchronized data reading code needs some time to execute. With
|
||
a sharable mutex we can acquire 2 lock types:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
<span class="bold"><strong>Exclusive lock</strong></span>: Similar to a plain
|
||
mutex. If a thread acquires an exclusive lock, no other thread can
|
||
acquire any lock (exclusive or other) until the exclusive lock is released.
|
||
If any thread other has any lock other than exclusive, a thread trying
|
||
to acquire an exclusive lock will block. This lock will be acquired
|
||
by threads that will modify the data.
|
||
</li>
|
||
<li class="listitem">
|
||
<span class="bold"><strong>Sharable lock</strong></span>: If a thread acquires
|
||
a sharable lock, other threads can't acquire the exclusive lock. If
|
||
any thread has acquired the exclusive lock a thread trying to acquire
|
||
a sharable lock will block. This locking is executed by threads that
|
||
just need to read the data.
|
||
</li>
|
||
</ul></div>
|
||
<p>
|
||
With an upgradable mutex we can acquire previous locks plus a new upgradable
|
||
lock:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
||
<span class="bold"><strong>Upgradable lock</strong></span>: Acquiring an upgradable
|
||
lock is similar to acquiring a <span class="bold"><strong>privileged sharable
|
||
lock</strong></span>. If a thread acquires an upgradable lock, other threads
|
||
can acquire a sharable lock. If any thread has acquired the exclusive
|
||
or upgradable lock a thread trying to acquire an upgradable lock will
|
||
block. A thread that has acquired an upgradable lock, is guaranteed
|
||
to be able to acquire atomically an exclusive lock when other threads
|
||
that have acquired a sharable lock release it. This is used for a thread
|
||
that <span class="bold"><strong>maybe</strong></span> needs to modify the data,
|
||
but usually just needs to read the data. This thread acquires the upgradable
|
||
lock and other threads can acquire the sharable lock. If the upgradable
|
||
thread reads the data and it has to modify it, the thread can be promoted
|
||
to acquire the exclusive lock: when all sharable threads have released
|
||
the sharable lock, the upgradable lock is atomically promoted to an
|
||
exclusive lock. The newly promoted thread can modify the data and it
|
||
can be sure that no other thread has modified it while doing the transition.
|
||
<span class="bold"><strong>Only 1 thread can acquire the upgradable (privileged
|
||
reader) lock</strong></span>.
|
||
</li></ul></div>
|
||
<p>
|
||
To sum up:
|
||
</p>
|
||
<div class="table">
|
||
<a name="interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.upgradable_whats_a_mutex.locking_possibilities_for_a_sharable_mutex"></a><p class="title"><b>Table 18.5. Locking Possibilities for a Sharable Mutex</b></p>
|
||
<div class="table-contents"><table class="table" summary="Locking Possibilities for a Sharable Mutex">
|
||
<colgroup>
|
||
<col>
|
||
<col>
|
||
</colgroup>
|
||
<thead><tr>
|
||
<th>
|
||
<p>
|
||
If a thread has acquired the...
|
||
</p>
|
||
</th>
|
||
<th>
|
||
<p>
|
||
Other threads can acquire...
|
||
</p>
|
||
</th>
|
||
</tr></thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
Sharable lock
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
many sharable locks
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
Exclusive lock
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
no locks
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table></div>
|
||
</div>
|
||
<br class="table-break"><div class="table">
|
||
<a name="interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.upgradable_whats_a_mutex.locking_possibilities_for_an_upgradable_mutex"></a><p class="title"><b>Table 18.6. Locking Possibilities for an Upgradable Mutex</b></p>
|
||
<div class="table-contents"><table class="table" summary="Locking Possibilities for an Upgradable Mutex">
|
||
<colgroup>
|
||
<col>
|
||
<col>
|
||
</colgroup>
|
||
<thead><tr>
|
||
<th>
|
||
<p>
|
||
If a thread has acquired the...
|
||
</p>
|
||
</th>
|
||
<th>
|
||
<p>
|
||
Other threads can acquire...
|
||
</p>
|
||
</th>
|
||
</tr></thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
Sharable lock
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
many sharable locks and 1 upgradable lock
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
Upgradable lock
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
many sharable locks
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
Exclusive lock
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
no locks
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table></div>
|
||
</div>
|
||
<br class="table-break">
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.upgradable_transitions"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.upgradable_transitions" title="Lock transitions for Upgradable Mutex">Lock
|
||
transitions for Upgradable Mutex</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
A sharable mutex has no option to change the acquired lock for another
|
||
lock atomically.
|
||
</p>
|
||
<p>
|
||
On the other hand, for an upgradable mutex, a thread that has acquired
|
||
a lock can try to acquire another lock type atomically. All lock transitions
|
||
are not guaranteed to succeed. Even if a transition is guaranteed to succeed,
|
||
some transitions will block the thread waiting until other threads release
|
||
the sharable locks. <span class="bold"><strong>Atomically</strong></span> means that
|
||
no other thread will acquire an Upgradable or Exclusive lock in the transition,
|
||
<span class="bold"><strong>so data is guaranteed to remain unchanged</strong></span>:
|
||
</p>
|
||
<div class="table">
|
||
<a name="interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.upgradable_transitions.transition_possibilities_for_an_upgradable_mutex"></a><p class="title"><b>Table 18.7. Transition Possibilities for an Upgradable Mutex</b></p>
|
||
<div class="table-contents"><table class="table" summary="Transition Possibilities for an Upgradable Mutex">
|
||
<colgroup>
|
||
<col>
|
||
<col>
|
||
</colgroup>
|
||
<thead><tr>
|
||
<th>
|
||
<p>
|
||
If a thread has acquired the...
|
||
</p>
|
||
</th>
|
||
<th>
|
||
<p>
|
||
It can atomically release the previous lock and...
|
||
</p>
|
||
</th>
|
||
</tr></thead>
|
||
<tbody>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
Sharable lock
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
try to obtain (not guaranteed) immediately the Exclusive lock
|
||
if no other thread has exclusive or upgrable lock
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
Sharable lock
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
try to obtain (not guaranteed) immediately the Upgradable lock
|
||
if no other thread has exclusive or upgrable lock
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
Upgradable lock
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
obtain the Exclusive lock when all sharable locks are released
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
Upgradable lock
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
obtain the Sharable lock immediately
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
Exclusive lock
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
obtain the Upgradable lock immediately
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td>
|
||
<p>
|
||
Exclusive lock
|
||
</p>
|
||
</td>
|
||
<td>
|
||
<p>
|
||
obtain the Sharable lock immediately
|
||
</p>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table></div>
|
||
</div>
|
||
<br class="table-break"><p>
|
||
As we can see, an upgradable mutex is a powerful synchronization utility
|
||
that can improve the concurrency. However, if most of the time we have
|
||
to modify the data, or the synchronized code section is very short, it's
|
||
more efficient to use a plain mutex, since it has less overhead. Upgradable
|
||
lock shines when the synchronized code section is bigger and there are
|
||
more readers than modifiers.
|
||
</p>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_operations"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_operations" title="Upgradable Mutex Operations">Upgradable
|
||
Mutex Operations</a>
|
||
</h4></div></div></div>
|
||
<div class="toc"><dl class="toc">
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_operations.sharable_upgradable_mutexes_operations_exclusive">Exclusive
|
||
Locking (Sharable & Upgradable Mutexes)</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_operations.sharable_upgradable_mutexes_operations_sharable">Sharable
|
||
Locking (Sharable & Upgradable Mutexes)</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_operations.upgradable_mutexes_operations_upgradable">Upgradable
|
||
Locking (Upgradable Mutex only)</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_operations.upgradable_mutexes_operations_demotions">Demotions
|
||
(Upgradable Mutex only)</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_operations.upgradable_mutexes_operations_promotions">Promotions
|
||
(Upgradable Mutex only)</a></span></dt>
|
||
</dl></div>
|
||
<p>
|
||
All the upgradable mutex types from <span class="bold"><strong>Boost.Interprocess</strong></span>
|
||
implement the following operations:
|
||
</p>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h5 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_operations.sharable_upgradable_mutexes_operations_exclusive"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_operations.sharable_upgradable_mutexes_operations_exclusive" title="Exclusive Locking (Sharable & Upgradable Mutexes)">Exclusive
|
||
Locking (Sharable & Upgradable Mutexes)</a>
|
||
</h5></div></div></div>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>void lock()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread tries to
|
||
obtain exclusive ownership of the mutex, and if another thread has any
|
||
ownership of the mutex (exclusive or other), it waits until it can obtain
|
||
the ownership.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> <span class="bold"><strong>interprocess_exception</strong></span>
|
||
on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>bool try_lock()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread tries to
|
||
acquire exclusive ownership of the mutex without waiting. If no other
|
||
thread has any ownership of the mutex (exclusive or other) this succeeds.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Returns:</strong></span> If it can acquire exclusive
|
||
ownership immediately returns true. If it has to wait, returns false.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> <span class="bold"><strong>interprocess_exception</strong></span>
|
||
on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>bool timed_lock(const boost::posix_time::ptime
|
||
&abs_time)</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread tries to
|
||
acquire exclusive ownership of the mutex waiting if necessary until no
|
||
other thread has any ownership of the mutex (exclusive or other) or abs_time
|
||
is reached.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Returns:</strong></span> If acquires exclusive ownership,
|
||
returns true. Otherwise returns false.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> <span class="bold"><strong>interprocess_exception</strong></span>
|
||
on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>void unlock()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Precondition:</strong></span> The thread must have exclusive
|
||
ownership of the mutex.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread releases
|
||
the exclusive ownership of the mutex.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> An exception derived from <span class="bold"><strong>interprocess_exception</strong></span> on error.
|
||
</p>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h5 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_operations.sharable_upgradable_mutexes_operations_sharable"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_operations.sharable_upgradable_mutexes_operations_sharable" title="Sharable Locking (Sharable & Upgradable Mutexes)">Sharable
|
||
Locking (Sharable & Upgradable Mutexes)</a>
|
||
</h5></div></div></div>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>void lock_sharable()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread tries to
|
||
obtain sharable ownership of the mutex, and if another thread has exclusive
|
||
ownership of the mutex, waits until it can obtain the ownership.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> <span class="bold"><strong>interprocess_exception</strong></span>
|
||
on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>bool try_lock_sharable()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread tries to
|
||
acquire sharable ownership of the mutex without waiting. If no other
|
||
thread has exclusive ownership of the mutex this succeeds.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Returns:</strong></span> If it can acquire sharable
|
||
ownership immediately returns true. If it has to wait, returns false.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> <span class="bold"><strong>interprocess_exception</strong></span>
|
||
on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>bool timed_lock_sharable(const boost::posix_time::ptime
|
||
&abs_time)</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread tries to
|
||
acquire sharable ownership of the mutex waiting if necessary until no
|
||
other thread has exclusive ownership of the mutex or abs_time is reached.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Returns:</strong></span> If acquires sharable ownership,
|
||
returns true. Otherwise returns false.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> <span class="bold"><strong>interprocess_exception</strong></span>
|
||
on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>void unlock_sharable()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Precondition:</strong></span> The thread must have sharable
|
||
ownership of the mutex.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread releases
|
||
the sharable ownership of the mutex.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> An exception derived from <span class="bold"><strong>interprocess_exception</strong></span> on error.
|
||
</p>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h5 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_operations.upgradable_mutexes_operations_upgradable"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_operations.upgradable_mutexes_operations_upgradable" title="Upgradable Locking (Upgradable Mutex only)">Upgradable
|
||
Locking (Upgradable Mutex only)</a>
|
||
</h5></div></div></div>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>void lock_upgradable()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread tries to
|
||
obtain upgradable ownership of the mutex, and if another thread has exclusive
|
||
or upgradable ownership of the mutex, waits until it can obtain the ownership.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> <span class="bold"><strong>interprocess_exception</strong></span>
|
||
on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>bool try_lock_upgradable()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread tries to
|
||
acquire upgradable ownership of the mutex without waiting. If no other
|
||
thread has exclusive or upgradable ownership of the mutex this succeeds.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Returns:</strong></span> If it can acquire upgradable
|
||
ownership immediately returns true. If it has to wait, returns false.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> <span class="bold"><strong>interprocess_exception</strong></span>
|
||
on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>bool timed_lock_upgradable(const boost::posix_time::ptime
|
||
&abs_time)</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread tries to
|
||
acquire upgradable ownership of the mutex waiting if necessary until
|
||
no other thread has exclusive ownership of the mutex or abs_time is reached.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Returns:</strong></span> If acquires upgradable ownership,
|
||
returns true. Otherwise returns false.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> <span class="bold"><strong>interprocess_exception</strong></span>
|
||
on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>void unlock_upgradable()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Precondition:</strong></span> The thread must have upgradable
|
||
ownership of the mutex.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread releases
|
||
the upgradable ownership of the mutex.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> An exception derived from <span class="bold"><strong>interprocess_exception</strong></span> on error.
|
||
</p>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h5 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_operations.upgradable_mutexes_operations_demotions"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_operations.upgradable_mutexes_operations_demotions" title="Demotions (Upgradable Mutex only)">Demotions
|
||
(Upgradable Mutex only)</a>
|
||
</h5></div></div></div>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>void unlock_and_lock_upgradable()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Precondition:</strong></span> The thread must have exclusive
|
||
ownership of the mutex.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The thread atomically releases
|
||
exclusive ownership and acquires upgradable ownership. This operation
|
||
is non-blocking.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> An exception derived from <span class="bold"><strong>interprocess_exception</strong></span> on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>void unlock_and_lock_sharable()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Precondition:</strong></span> The thread must have exclusive
|
||
ownership of the mutex.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The thread atomically releases
|
||
exclusive ownership and acquires sharable ownership. This operation is
|
||
non-blocking.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> An exception derived from <span class="bold"><strong>interprocess_exception</strong></span> on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>void unlock_upgradable_and_lock_sharable()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Precondition:</strong></span> The thread must have upgradable
|
||
ownership of the mutex.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The thread atomically releases
|
||
upgradable ownership and acquires sharable ownership. This operation
|
||
is non-blocking.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> An exception derived from <span class="bold"><strong>interprocess_exception</strong></span> on error.
|
||
</p>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h5 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_operations.upgradable_mutexes_operations_promotions"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_operations.upgradable_mutexes_operations_promotions" title="Promotions (Upgradable Mutex only)">Promotions
|
||
(Upgradable Mutex only)</a>
|
||
</h5></div></div></div>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>void unlock_upgradable_and_lock()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Precondition:</strong></span> The thread must have upgradable
|
||
ownership of the mutex.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The thread atomically releases
|
||
upgradable ownership and acquires exclusive ownership. This operation
|
||
will block until all threads with sharable ownership release it.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> An exception derived from <span class="bold"><strong>interprocess_exception</strong></span> on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>bool try_unlock_upgradable_and_lock()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Precondition:</strong></span> The thread must have upgradable
|
||
ownership of the mutex.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The thread atomically releases
|
||
upgradable ownership and tries to acquire exclusive ownership. This operation
|
||
will fail if there are threads with sharable ownership, but it will maintain
|
||
upgradable ownership.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Returns:</strong></span> If acquires exclusive ownership,
|
||
returns true. Otherwise returns false.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> An exception derived from <span class="bold"><strong>interprocess_exception</strong></span> on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>bool timed_unlock_upgradable_and_lock(const
|
||
boost::posix_time::ptime &abs_time)</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Precondition:</strong></span> The thread must have upgradable
|
||
ownership of the mutex.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The thread atomically releases
|
||
upgradable ownership and tries to acquire exclusive ownership, waiting
|
||
if necessary until abs_time. This operation will fail if there are threads
|
||
with sharable ownership or timeout reaches, but it will maintain upgradable
|
||
ownership.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Returns:</strong></span> If acquires exclusive ownership,
|
||
returns true. Otherwise returns false.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> An exception derived from <span class="bold"><strong>interprocess_exception</strong></span> on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>bool try_unlock_sharable_and_lock()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Precondition:</strong></span> The thread must have sharable
|
||
ownership of the mutex.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The thread atomically releases
|
||
sharable ownership and tries to acquire exclusive ownership. This operation
|
||
will fail if there are threads with sharable or upgradable ownership,
|
||
but it will maintain sharable ownership.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Returns:</strong></span> If acquires exclusive ownership,
|
||
returns true. Otherwise returns false.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> An exception derived from <span class="bold"><strong>interprocess_exception</strong></span> on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>bool try_unlock_sharable_and_lock_upgradable()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Precondition:</strong></span> The thread must have sharable
|
||
ownership of the mutex.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The thread atomically releases
|
||
sharable ownership and tries to acquire upgradable ownership. This operation
|
||
will fail if there are threads with sharable or upgradable ownership,
|
||
but it will maintain sharable ownership.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Returns:</strong></span> If acquires upgradable ownership,
|
||
returns true. Otherwise returns false.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> An exception derived from <span class="bold"><strong>interprocess_exception</strong></span> on error.
|
||
</p>
|
||
<div class="important"><table border="0" summary="Important">
|
||
<tr>
|
||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../../doc/src/images/important.png"></td>
|
||
<th align="left">Important</th>
|
||
</tr>
|
||
<tr><td align="left" valign="top"><p>
|
||
<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">posix_time</span><span class="special">::</span><span class="identifier">ptime</span></code> absolute time points used by
|
||
Boost.Interprocess synchronization mechanisms are UTC time points,
|
||
not local time points
|
||
</p></td></tr>
|
||
</table></div>
|
||
</div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_mutex_interprocess_mutexes"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_mutexes_mutex_interprocess_mutexes" title="Boost.Interprocess Sharable & Upgradable Mutex Types And Headers">Boost.Interprocess
|
||
Sharable & Upgradable Mutex Types And Headers</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
Boost.Interprocess offers the following sharable mutex types:
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">interprocess_sharable_mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
||
<code class="computeroutput"><a class="link" href="../boost/interprocess/interpro_idm45189371271632.html" title="Class interprocess_sharable_mutex">interprocess_sharable_mutex</a></code>:
|
||
A non-recursive, anonymous sharable mutex that can be placed in shared
|
||
memory or memory mapped files.
|
||
</li></ul></div>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">named_sharable_mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
||
<code class="computeroutput"><a class="link" href="../boost/interprocess/named_sharable_mutex.html" title="Class named_sharable_mutex">named_sharable_mutex</a></code>:
|
||
A non-recursive, named sharable mutex.
|
||
</li></ul></div>
|
||
<p>
|
||
Boost.Interprocess offers the following upgradable mutex types:
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">interprocess_upgradable_mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
||
<code class="computeroutput"><a class="link" href="../boost/interprocess/interpro_idm45189371236304.html" title="Class interprocess_upgradable_mutex">interprocess_upgradable_mutex</a></code>:
|
||
A non-recursive, anonymous upgradable mutex that can be placed in shared
|
||
memory or memory mapped files.
|
||
</li></ul></div>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">named_upgradable_mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
||
<code class="computeroutput"><a class="link" href="../boost/interprocess/named_upgradable_mutex.html" title="Class named_upgradable_mutex">named_upgradable_mutex</a></code>:
|
||
A non-recursive, named upgradable mutex.
|
||
</li></ul></div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_locks"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_locks" title="Sharable Lock And Upgradable Lock">Sharable
|
||
Lock And Upgradable Lock</a>
|
||
</h4></div></div></div>
|
||
<div class="toc"><dl class="toc"><dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_locks.upgradable_mutexes_lock_types">Sharable
|
||
Lock And Upgradable Lock Headers</a></span></dt></dl></div>
|
||
<p>
|
||
As with plain mutexes, it's important to release the acquired lock even
|
||
in the presence of exceptions. <span class="bold"><strong>Boost.Interprocess</strong></span>
|
||
mutexes are best used with the <code class="computeroutput"><a class="link" href="../boost/interprocess/scoped_lock.html" title="Class template scoped_lock">scoped_lock</a></code>
|
||
utility, and this class only offers exclusive locking.
|
||
</p>
|
||
<p>
|
||
As we have sharable locking and upgradable locking with upgradable mutexes,
|
||
we have two new utilities: <code class="computeroutput"><a class="link" href="../boost/interprocess/sharable_lock.html" title="Class template sharable_lock">sharable_lock</a></code>
|
||
and <code class="computeroutput"><a class="link" href="../boost/interprocess/upgradable_lock.html" title="Class template upgradable_lock">upgradable_lock</a></code>.
|
||
Both classes are similar to <code class="computeroutput"><span class="identifier">scoped_lock</span></code>
|
||
but <code class="computeroutput"><span class="identifier">sharable_lock</span></code> acquires
|
||
the sharable lock in the constructor and <code class="computeroutput"><span class="identifier">upgradable_lock</span></code>
|
||
acquires the upgradable lock in the constructor.
|
||
</p>
|
||
<p>
|
||
These two utilities can be use with any synchronization object that offers
|
||
the needed operations. For example, a user defined mutex type with no upgradable
|
||
locking features can use <code class="computeroutput"><span class="identifier">sharable_lock</span></code>
|
||
if the synchronization object offers <span class="bold"><strong>lock_sharable()</strong></span>
|
||
and <span class="bold"><strong>unlock_sharable()</strong></span> operations:
|
||
</p>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h5 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_locks.upgradable_mutexes_lock_types"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.sharable_upgradable_mutexes.sharable_upgradable_locks.upgradable_mutexes_lock_types" title="Sharable Lock And Upgradable Lock Headers">Sharable
|
||
Lock And Upgradable Lock Headers</a>
|
||
</h5></div></div></div>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">sharable_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">upgradable_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
</div>
|
||
<p>
|
||
<code class="computeroutput"><span class="identifier">sharable_lock</span></code> calls <span class="bold"><strong>unlock_sharable()</strong></span> in its destructor, and <code class="computeroutput"><span class="identifier">upgradable_lock</span></code> calls <span class="bold"><strong>unlock_upgradable()</strong></span>
|
||
in its destructor, so the upgradable mutex is always unlocked when an exception
|
||
occurs.
|
||
</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">SharableOrUpgradableMutex</span> <span class="identifier">sh_or_up_mutex</span><span class="special">;</span>
|
||
|
||
<span class="special">{</span>
|
||
<span class="comment">//This will call lock_sharable()</span>
|
||
<span class="identifier">sharable_lock</span><span class="special"><</span><span class="identifier">SharableOrUpgradableMutex</span><span class="special">></span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">sh_or_up_mutex</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Some code</span>
|
||
|
||
<span class="comment">//The mutex will be unlocked here</span>
|
||
<span class="special">}</span>
|
||
|
||
<span class="special">{</span>
|
||
<span class="comment">//This won't lock the mutex()</span>
|
||
<span class="identifier">sharable_lock</span><span class="special"><</span><span class="identifier">SharableOrUpgradableMutex</span><span class="special">></span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">sh_or_up_mutex</span><span class="special">,</span> <span class="identifier">defer_lock</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Lock it on demand. This will call lock_sharable()</span>
|
||
<span class="identifier">lock</span><span class="special">.</span><span class="identifier">lock</span><span class="special">();</span>
|
||
|
||
<span class="comment">//Some code</span>
|
||
|
||
<span class="comment">//The mutex will be unlocked here</span>
|
||
<span class="special">}</span>
|
||
|
||
<span class="special">{</span>
|
||
<span class="comment">//This will call try_lock_sharable()</span>
|
||
<span class="identifier">sharable_lock</span><span class="special"><</span><span class="identifier">SharableOrUpgradableMutex</span><span class="special">></span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">sh_or_up_mutex</span><span class="special">,</span> <span class="identifier">try_to_lock</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Check if the mutex has been successfully locked</span>
|
||
<span class="keyword">if</span><span class="special">(</span><span class="identifier">lock</span><span class="special">){</span>
|
||
<span class="comment">//Some code</span>
|
||
<span class="special">}</span>
|
||
<span class="comment">//If the mutex was locked it will be unlocked</span>
|
||
<span class="special">}</span>
|
||
|
||
<span class="special">{</span>
|
||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">posix_time</span><span class="special">::</span><span class="identifier">ptime</span> <span class="identifier">abs_time</span> <span class="special">=</span> <span class="special">...</span>
|
||
|
||
<span class="comment">//This will call timed_lock_sharable()</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">SharableOrUpgradableMutex</span><span class="special">></span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">sh_or_up_mutex</span><span class="special">,</span> <span class="identifier">abs_time</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Check if the mutex has been successfully locked</span>
|
||
<span class="keyword">if</span><span class="special">(</span><span class="identifier">lock</span><span class="special">){</span>
|
||
<span class="comment">//Some code</span>
|
||
<span class="special">}</span>
|
||
<span class="comment">//If the mutex was locked it will be unlocked</span>
|
||
<span class="special">}</span>
|
||
|
||
<span class="identifier">UpgradableMutex</span> <span class="identifier">up_mutex</span><span class="special">;</span>
|
||
|
||
<span class="special">{</span>
|
||
<span class="comment">//This will call lock_upgradable()</span>
|
||
<span class="identifier">upgradable_lock</span><span class="special"><</span><span class="identifier">UpgradableMutex</span><span class="special">></span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">up_mutex</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Some code</span>
|
||
|
||
<span class="comment">//The mutex will be unlocked here</span>
|
||
<span class="special">}</span>
|
||
|
||
<span class="special">{</span>
|
||
<span class="comment">//This won't lock the mutex()</span>
|
||
<span class="identifier">upgradable_lock</span><span class="special"><</span><span class="identifier">UpgradableMutex</span><span class="special">></span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">up_mutex</span><span class="special">,</span> <span class="identifier">defer_lock</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Lock it on demand. This will call lock_upgradable()</span>
|
||
<span class="identifier">lock</span><span class="special">.</span><span class="identifier">lock</span><span class="special">();</span>
|
||
|
||
<span class="comment">//Some code</span>
|
||
|
||
<span class="comment">//The mutex will be unlocked here</span>
|
||
<span class="special">}</span>
|
||
|
||
<span class="special">{</span>
|
||
<span class="comment">//This will call try_lock_upgradable()</span>
|
||
<span class="identifier">upgradable_lock</span><span class="special"><</span><span class="identifier">UpgradableMutex</span><span class="special">></span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">up_mutex</span><span class="special">,</span> <span class="identifier">try_to_lock</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Check if the mutex has been successfully locked</span>
|
||
<span class="keyword">if</span><span class="special">(</span><span class="identifier">lock</span><span class="special">){</span>
|
||
<span class="comment">//Some code</span>
|
||
<span class="special">}</span>
|
||
<span class="comment">//If the mutex was locked it will be unlocked</span>
|
||
<span class="special">}</span>
|
||
|
||
<span class="special">{</span>
|
||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">posix_time</span><span class="special">::</span><span class="identifier">ptime</span> <span class="identifier">abs_time</span> <span class="special">=</span> <span class="special">...</span>
|
||
|
||
<span class="comment">//This will call timed_lock_upgradable()</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">UpgradableMutex</span><span class="special">></span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">up_mutex</span><span class="special">,</span> <span class="identifier">abs_time</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Check if the mutex has been successfully locked</span>
|
||
<span class="keyword">if</span><span class="special">(</span><span class="identifier">lock</span><span class="special">){</span>
|
||
<span class="comment">//Some code</span>
|
||
<span class="special">}</span>
|
||
<span class="comment">//If the mutex was locked it will be unlocked</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../boost/interprocess/upgradable_lock.html" title="Class template upgradable_lock">upgradable_lock</a></code>
|
||
and <code class="computeroutput"><a class="link" href="../boost/interprocess/sharable_lock.html" title="Class template sharable_lock">sharable_lock</a></code>
|
||
offer more features and operations, see their reference for more informations
|
||
</p>
|
||
<div class="important"><table border="0" summary="Important">
|
||
<tr>
|
||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../../doc/src/images/important.png"></td>
|
||
<th align="left">Important</th>
|
||
</tr>
|
||
<tr><td align="left" valign="top"><p>
|
||
<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">posix_time</span><span class="special">::</span><span class="identifier">ptime</span></code> absolute time points used by
|
||
Boost.Interprocess synchronization mechanisms are UTC time points, not
|
||
local time points
|
||
</p></td></tr>
|
||
</table></div>
|
||
</div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h3 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.lock_conversions"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.lock_conversions" title="Lock Transfers Through Move Semantics">Lock
|
||
Transfers Through Move Semantics</a>
|
||
</h3></div></div></div>
|
||
<div class="toc"><dl class="toc">
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_simple_transfer">Simple
|
||
Lock Transfer</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_summary">Lock
|
||
Transfer Summary</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_not_locked">Transferring
|
||
Unlocked Locks</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_failure">Transfer
|
||
Failures</a></span></dt>
|
||
</dl></div>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="bold"><strong>Interprocess uses its own move semantics emulation
|
||
code for compilers that don't support rvalues references. This is a temporary
|
||
solution until a Boost move semantics library is accepted.</strong></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
Scoped locks and similar utilities offer simple resource management possibilities,
|
||
but with advanced mutex types like upgradable mutexes, there are operations
|
||
where an acquired lock type is released and another lock type is acquired
|
||
atomically. This is implemented by upgradable mutex operations like <code class="computeroutput"><span class="identifier">unlock_and_lock_sharable</span><span class="special">()</span></code>.
|
||
</p>
|
||
<p>
|
||
These operations can be managed more effectively using <span class="bold"><strong>lock
|
||
transfer operations</strong></span>. A lock transfer operations explicitly indicates
|
||
that a mutex owned by a lock is transferred to another lock executing atomic
|
||
unlocking plus locking operations.
|
||
</p>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_simple_transfer"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_simple_transfer" title="Simple Lock Transfer">Simple
|
||
Lock Transfer</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
Imagine that a thread modifies some data in the beginning but after that,
|
||
it has to just read it in a long time. The code can acquire the exclusive
|
||
lock, modify the data and atomically release the exclusive lock and acquire
|
||
the sharable lock. With these sequence we guarantee that no other thread
|
||
can modify the data in the transition and that more readers can acquire
|
||
sharable lock, increasing concurrency. Without lock transfer operations,
|
||
this would be coded like this:
|
||
</p>
|
||
<pre class="programlisting"><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="identifier">interprocess_upgradable_mutex</span> <span class="identifier">mutex</span><span class="special">;</span>
|
||
|
||
<span class="comment">//Acquire exclusive lock</span>
|
||
<span class="identifier">mutex</span><span class="special">.</span><span class="identifier">lock</span><span class="special">();</span>
|
||
|
||
<span class="comment">//Modify data</span>
|
||
|
||
<span class="comment">//Atomically release exclusive lock and acquire sharable lock.</span>
|
||
<span class="comment">//More threads can acquire the sharable lock and read the data.</span>
|
||
<span class="identifier">mutex</span><span class="special">.</span><span class="identifier">unlock_and_lock_sharable</span><span class="special">();</span>
|
||
|
||
<span class="comment">//Read data</span>
|
||
|
||
<span class="comment">//Explicit unlocking</span>
|
||
<span class="identifier">mutex</span><span class="special">.</span><span class="identifier">unlock_sharable</span><span class="special">();</span>
|
||
</pre>
|
||
<p>
|
||
This can be simple, but in the presence of exceptions, it's complicated
|
||
to know what type of lock the mutex had when the exception was thrown and
|
||
what function we should call to unlock it:
|
||
</p>
|
||
<pre class="programlisting"><span class="keyword">try</span><span class="special">{</span>
|
||
<span class="comment">//Mutex operations</span>
|
||
<span class="special">}</span>
|
||
<span class="keyword">catch</span><span class="special">(...){</span>
|
||
<span class="comment">//What should we call? "unlock()" or "unlock_sharable()"</span>
|
||
<span class="comment">//Is the mutex locked?</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
<p>
|
||
We can use <span class="bold"><strong>lock transfer</strong></span> to simplify all
|
||
this management:
|
||
</p>
|
||
<pre class="programlisting"><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="identifier">interprocess_upgradable_mutex</span> <span class="identifier">mutex</span><span class="special">;</span>
|
||
|
||
<span class="comment">//Acquire exclusive lock</span>
|
||
<span class="identifier">scoped_lock</span> <span class="identifier">s_lock</span><span class="special">(</span><span class="identifier">mutex</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Modify data</span>
|
||
|
||
<span class="comment">//Atomically release exclusive lock and acquire sharable lock.</span>
|
||
<span class="comment">//More threads can acquire the sharable lock and read the data.</span>
|
||
<span class="identifier">sharable_lock</span><span class="special">(</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">s_lock</span><span class="special">));</span>
|
||
|
||
<span class="comment">//Read data</span>
|
||
|
||
<span class="comment">//The lock is automatically unlocked calling the appropriate unlock</span>
|
||
<span class="comment">//function even in the presence of exceptions.</span>
|
||
<span class="comment">//If the mutex was not locked, no function is called.</span>
|
||
</pre>
|
||
<p>
|
||
As we can see, even if an exception is thrown at any moment, the mutex
|
||
will be automatically unlocked calling the appropriate <code class="computeroutput"><span class="identifier">unlock</span><span class="special">()</span></code> or <code class="computeroutput"><span class="identifier">unlock_sharable</span><span class="special">()</span></code> method.
|
||
</p>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_summary"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_summary" title="Lock Transfer Summary">Lock
|
||
Transfer Summary</a>
|
||
</h4></div></div></div>
|
||
<div class="toc"><dl class="toc">
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_summary.lock_transfer_summary_scoped">Transfers
|
||
To Scoped Lock</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_summary.lock_transfer_summary_upgradable">Transfers
|
||
To Upgradable Lock</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_summary.lock_transfer_summary_sharable">Transfers
|
||
To Sharable Lock</a></span></dt>
|
||
</dl></div>
|
||
<p>
|
||
There are many lock transfer operations that we can classify according
|
||
to the operations presented in the upgradable mutex operations:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
<span class="bold"><strong>Guaranteed to succeed and non-blocking:</strong></span>
|
||
Any transition from a more restrictive lock to a less restrictive one.
|
||
Scoped -> Upgradable, Scoped -> Sharable, Upgradable -> Sharable.
|
||
</li>
|
||
<li class="listitem">
|
||
<span class="bold"><strong>Not guaranteed to succeed:</strong></span> The operation
|
||
might succeed if no one has acquired the upgradable or exclusive lock:
|
||
Sharable -> Exclusive. This operation is a try operation.
|
||
</li>
|
||
<li class="listitem">
|
||
<span class="bold"><strong>Guaranteed to succeed if using an infinite waiting:</strong></span>
|
||
Any transition that will succeed but needs to wait until all Sharable
|
||
locks are released: Upgradable -> Scoped. Since this is a blocking
|
||
operation, we can also choose not to wait infinitely and just try or
|
||
wait until a timeout is reached.
|
||
</li>
|
||
</ul></div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h5 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_summary.lock_transfer_summary_scoped"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_summary.lock_transfer_summary_scoped" title="Transfers To Scoped Lock">Transfers
|
||
To Scoped Lock</a>
|
||
</h5></div></div></div>
|
||
<p>
|
||
Transfers to <code class="computeroutput"><span class="identifier">scoped_lock</span></code>
|
||
are guaranteed to succeed only from an <code class="computeroutput"><span class="identifier">upgradable_lock</span></code>
|
||
and only if a blocking operation is requested, due to the fact that this
|
||
operation needs to wait until all sharable locks are released. The user
|
||
can also use "try" or "timed" transfer to avoid infinite
|
||
locking, but succeed is not guaranteed.
|
||
</p>
|
||
<p>
|
||
A conversion from a <code class="computeroutput"><span class="identifier">sharable_lock</span></code>
|
||
is never guaranteed and thus, only a try operation is permitted:
|
||
</p>
|
||
<pre class="programlisting"><span class="comment">//Conversions to scoped_lock</span>
|
||
<span class="special">{</span>
|
||
<span class="identifier">upgradable_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">u_lock</span><span class="special">(</span><span class="identifier">mut</span><span class="special">);</span>
|
||
<span class="comment">//This calls unlock_upgradable_and_lock()</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">e_lock</span><span class="special">(</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">u_lock</span><span class="special">));</span>
|
||
<span class="special">}</span>
|
||
<span class="special">{</span>
|
||
<span class="identifier">upgradable_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">u_lock</span><span class="special">(</span><span class="identifier">mut</span><span class="special">);</span>
|
||
<span class="comment">//This calls try_unlock_upgradable_and_lock()</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">e_lock</span><span class="special">(</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">u_lock</span><span class="special">,</span> <span class="identifier">try_to_lock</span><span class="special">));</span>
|
||
<span class="special">}</span>
|
||
<span class="special">{</span>
|
||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">posix_time</span><span class="special">::</span><span class="identifier">ptime</span> <span class="identifier">t</span> <span class="special">=</span> <span class="identifier">test</span><span class="special">::</span><span class="identifier">delay</span><span class="special">(</span><span class="number">100</span><span class="special">);</span>
|
||
<span class="identifier">upgradable_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">u_lock</span><span class="special">(</span><span class="identifier">mut</span><span class="special">);</span>
|
||
<span class="comment">//This calls timed_unlock_upgradable_and_lock()</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">e_lock</span><span class="special">(</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">u_lock</span><span class="special">));</span>
|
||
<span class="special">}</span>
|
||
<span class="special">{</span>
|
||
<span class="identifier">sharable_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">s_lock</span><span class="special">(</span><span class="identifier">mut</span><span class="special">);</span>
|
||
<span class="comment">//This calls try_unlock_sharable_and_lock()</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">e_lock</span><span class="special">(</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">s_lock</span><span class="special">,</span> <span class="identifier">try_to_lock</span><span class="special">));</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
<div class="important"><table border="0" summary="Important">
|
||
<tr>
|
||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../../doc/src/images/important.png"></td>
|
||
<th align="left">Important</th>
|
||
</tr>
|
||
<tr><td align="left" valign="top"><p>
|
||
<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">posix_time</span><span class="special">::</span><span class="identifier">ptime</span></code> absolute time points used by
|
||
Boost.Interprocess synchronization mechanisms are UTC time points,
|
||
not local time points
|
||
</p></td></tr>
|
||
</table></div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h5 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_summary.lock_transfer_summary_upgradable"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_summary.lock_transfer_summary_upgradable" title="Transfers To Upgradable Lock">Transfers
|
||
To Upgradable Lock</a>
|
||
</h5></div></div></div>
|
||
<p>
|
||
A transfer to an <code class="computeroutput"><span class="identifier">upgradable_lock</span></code>
|
||
is guaranteed to succeed only from a <code class="computeroutput"><span class="identifier">scoped_lock</span></code>
|
||
since scoped locking is a more restrictive locking than an upgradable
|
||
locking. This operation is also non-blocking.
|
||
</p>
|
||
<p>
|
||
A transfer from a <code class="computeroutput"><span class="identifier">sharable_lock</span></code>
|
||
is not guaranteed and only a "try" operation is permitted:
|
||
</p>
|
||
<pre class="programlisting"><span class="comment">//Conversions to upgradable</span>
|
||
<span class="special">{</span>
|
||
<span class="identifier">sharable_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">s_lock</span><span class="special">(</span><span class="identifier">mut</span><span class="special">);</span>
|
||
<span class="comment">//This calls try_unlock_sharable_and_lock_upgradable()</span>
|
||
<span class="identifier">upgradable_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">u_lock</span><span class="special">(</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">s_lock</span><span class="special">,</span> <span class="identifier">try_to_lock</span><span class="special">));</span>
|
||
<span class="special">}</span>
|
||
<span class="special">{</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">e_lock</span><span class="special">(</span><span class="identifier">mut</span><span class="special">);</span>
|
||
<span class="comment">//This calls unlock_and_lock_upgradable()</span>
|
||
<span class="identifier">upgradable_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">u_lock</span><span class="special">(</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">e_lock</span><span class="special">));</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h5 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_summary.lock_transfer_summary_sharable"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_summary.lock_transfer_summary_sharable" title="Transfers To Sharable Lock">Transfers
|
||
To Sharable Lock</a>
|
||
</h5></div></div></div>
|
||
<p>
|
||
All transfers to a <code class="computeroutput"><span class="identifier">sharable_lock</span></code>
|
||
are guaranteed to succeed since both <code class="computeroutput"><span class="identifier">upgradable_lock</span></code>
|
||
and <code class="computeroutput"><span class="identifier">scoped_lock</span></code> are more
|
||
restrictive than <code class="computeroutput"><span class="identifier">sharable_lock</span></code>.
|
||
These operations are also non-blocking:
|
||
</p>
|
||
<pre class="programlisting"><span class="comment">//Conversions to sharable_lock</span>
|
||
<span class="special">{</span>
|
||
<span class="identifier">upgradable_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">u_lock</span><span class="special">(</span><span class="identifier">mut</span><span class="special">);</span>
|
||
<span class="comment">//This calls unlock_upgradable_and_lock_sharable()</span>
|
||
<span class="identifier">sharable_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">s_lock</span><span class="special">(</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">u_lock</span><span class="special">));</span>
|
||
<span class="special">}</span>
|
||
<span class="special">{</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">e_lock</span><span class="special">(</span><span class="identifier">mut</span><span class="special">);</span>
|
||
<span class="comment">//This calls unlock_and_lock_sharable()</span>
|
||
<span class="identifier">sharable_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">s_lock</span><span class="special">(</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">e_lock</span><span class="special">));</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_not_locked"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_not_locked" title="Transferring Unlocked Locks">Transferring
|
||
Unlocked Locks</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
In the previous examples, the mutex used in the transfer operation was
|
||
previously locked:
|
||
</p>
|
||
<pre class="programlisting"> <span class="identifier">Mutex</span> <span class="identifier">mut</span><span class="special">;</span>
|
||
|
||
<span class="comment">//This calls mut.lock()</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">e_lock</span><span class="special">(</span><span class="identifier">mut</span><span class="special">);</span>
|
||
|
||
<span class="comment">//This calls unlock_and_lock_sharable()</span>
|
||
<span class="identifier">sharable_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">s_lock</span><span class="special">(</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">e_lock</span><span class="special">));</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
<p>
|
||
but it's possible to execute the transfer with an unlocked source, due
|
||
to explicit unlocking, a try, timed or a <code class="computeroutput"><span class="identifier">defer_lock</span></code>
|
||
constructor:
|
||
</p>
|
||
<pre class="programlisting"><span class="comment">//These operations can leave the mutex unlocked!</span>
|
||
|
||
<span class="special">{</span>
|
||
<span class="comment">//Try might fail</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">e_lock</span><span class="special">(</span><span class="identifier">mut</span><span class="special">,</span> <span class="identifier">try_to_lock</span><span class="special">);</span>
|
||
<span class="identifier">sharable_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">s_lock</span><span class="special">(</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">e_lock</span><span class="special">));</span>
|
||
<span class="special">}</span>
|
||
<span class="special">{</span>
|
||
<span class="comment">//Timed operation might fail</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">e_lock</span><span class="special">(</span><span class="identifier">mut</span><span class="special">,</span> <span class="identifier">time</span><span class="special">);</span>
|
||
<span class="identifier">sharable_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">s_lock</span><span class="special">(</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">e_lock</span><span class="special">));</span>
|
||
<span class="special">}</span>
|
||
<span class="special">{</span>
|
||
<span class="comment">//Avoid mutex locking</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">e_lock</span><span class="special">(</span><span class="identifier">mut</span><span class="special">,</span> <span class="identifier">defer_lock</span><span class="special">);</span>
|
||
<span class="identifier">sharable_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">s_lock</span><span class="special">(</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">e_lock</span><span class="special">));</span>
|
||
<span class="special">}</span>
|
||
<span class="special">{</span>
|
||
<span class="comment">//Explicitly call unlock</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">e_lock</span><span class="special">(</span><span class="identifier">mut</span><span class="special">);</span>
|
||
<span class="identifier">e_lock</span><span class="special">.</span><span class="identifier">unlock</span><span class="special">();</span>
|
||
<span class="comment">//Mutex was explicitly unlocked</span>
|
||
<span class="identifier">sharable_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">s_lock</span><span class="special">(</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">e_lock</span><span class="special">));</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
<p>
|
||
If the source mutex was not locked:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
The target lock does not execute the atomic <code class="computeroutput"><span class="identifier">unlock_xxx_and_lock_xxx</span></code>
|
||
operation.
|
||
</li>
|
||
<li class="listitem">
|
||
The target lock is also unlocked.
|
||
</li>
|
||
<li class="listitem">
|
||
The source lock is released() and the ownership of the mutex is transferred
|
||
to the target.
|
||
</li>
|
||
</ul></div>
|
||
<pre class="programlisting"><span class="special">{</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">e_lock</span><span class="special">(</span><span class="identifier">mut</span><span class="special">,</span> <span class="identifier">defer_lock</span><span class="special">);</span>
|
||
<span class="identifier">sharable_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">s_lock</span><span class="special">(</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">e_lock</span><span class="special">));</span>
|
||
|
||
<span class="comment">//Assertions</span>
|
||
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">e_lock</span><span class="special">.</span><span class="identifier">mutex</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">s_lock</span><span class="special">.</span><span class="identifier">mutex</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">e_lock</span><span class="special">.</span><span class="identifier">owns</span><span class="special">()</span> <span class="special">==</span> <span class="keyword">false</span><span class="special">);</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_failure"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.lock_conversions.lock_transfer_failure" title="Transfer Failures">Transfer
|
||
Failures</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
When executing a lock transfer, the operation can fail:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
The executed atomic mutex unlock plus lock function might throw.
|
||
</li>
|
||
<li class="listitem">
|
||
The executed atomic function might be a "try" or "timed"
|
||
function that can fail.
|
||
</li>
|
||
</ul></div>
|
||
<p>
|
||
In the first case, the mutex ownership is not transferred and the source
|
||
lock's destructor will unlock the mutex:
|
||
</p>
|
||
<pre class="programlisting"><span class="special">{</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">e_lock</span><span class="special">(</span><span class="identifier">mut</span><span class="special">,</span> <span class="identifier">defer_lock</span><span class="special">);</span>
|
||
|
||
<span class="comment">//This operations throws because</span>
|
||
<span class="comment">//"unlock_and_lock_sharable()" throws!!!</span>
|
||
<span class="identifier">sharable_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">s_lock</span><span class="special">(</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">e_lock</span><span class="special">));</span>
|
||
|
||
<span class="comment">//Some code ...</span>
|
||
|
||
<span class="comment">//e_lock's destructor will call "unlock()"</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
<p>
|
||
In the second case, if an internal "try" or "timed"
|
||
operation fails (returns "false") then the mutex ownership is
|
||
<span class="bold"><strong>not</strong></span> transferred, the source lock is unchanged
|
||
and the target lock's state will the same as a default construction:
|
||
</p>
|
||
<pre class="programlisting"><span class="special">{</span>
|
||
<span class="identifier">sharable_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">s_lock</span><span class="special">(</span><span class="identifier">mut</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Internal "try_unlock_sharable_and_lock_upgradable()" returns false</span>
|
||
<span class="identifier">upgradable_lock</span><span class="special"><</span><span class="identifier">Mutex</span><span class="special">></span> <span class="identifier">u_lock</span><span class="special">(</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">s_lock</span><span class="special">,</span> <span class="identifier">try_to_lock</span><span class="special">));</span>
|
||
|
||
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">s_lock</span><span class="special">.</span><span class="identifier">mutex</span><span class="special">()</span> <span class="special">==</span> <span class="special">&</span><span class="identifier">mut</span><span class="special">);</span>
|
||
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">s_lock</span><span class="special">.</span><span class="identifier">owns</span><span class="special">()</span> <span class="special">==</span> <span class="keyword">true</span><span class="special">);</span>
|
||
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">u_lock</span><span class="special">.</span><span class="identifier">mutex</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">u_lock</span><span class="special">.</span><span class="identifier">owns</span><span class="special">()</span> <span class="special">==</span> <span class="keyword">false</span><span class="special">);</span>
|
||
|
||
<span class="comment">//u_lock's destructor does nothing</span>
|
||
<span class="comment">//s_lock's destructor calls "unlock()"</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h3 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.file_lock"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.file_lock" title="File Locks">File
|
||
Locks</a>
|
||
</h3></div></div></div>
|
||
<div class="toc"><dl class="toc">
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.file_lock.file_lock_whats_a_file_lock">What's
|
||
A File Lock?</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.file_lock.file_lock_operations">File
|
||
Locking Operations</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.file_lock.file_lock_scoped_locks">Scoped
|
||
Lock and Sharable Lock With File Locking</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.file_lock.file_lock_not_thread_safe">Caution:
|
||
Synchronization limitations</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.file_lock.file_lock_careful_iostream">Be
|
||
Careful With Iostream Writing</a></span></dt>
|
||
</dl></div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.file_lock.file_lock_whats_a_file_lock"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.file_lock.file_lock_whats_a_file_lock" title="What's A File Lock?">What's
|
||
A File Lock?</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
A file lock is an interprocess synchronization mechanism to protect concurrent
|
||
writes and reads to files using a mutex <span class="emphasis"><em>embedded</em></span> in
|
||
the file. This <span class="emphasis"><em>embedded mutex</em></span> has sharable and exclusive
|
||
locking capabilities. With a file lock, an existing file can be used as
|
||
a mutex without the need of creating additional synchronization objects
|
||
to control concurrent file reads or writes.
|
||
</p>
|
||
<p>
|
||
Generally speaking, we can have two file locking capabilities:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
<span class="bold"><strong>Advisory locking:</strong></span> The operating system
|
||
kernel maintains a list of files that have been locked. But does not
|
||
prevent writing to those files even if a process has acquired a sharable
|
||
lock or does not prevent reading from the file when a process has acquired
|
||
the exclusive lock. Any process can ignore an advisory lock. This means
|
||
that advisory locks are for <span class="bold"><strong>cooperating</strong></span>
|
||
processes, processes that can trust each other. This is similar to
|
||
a mutex protecting data in a shared memory segment: any process connected
|
||
to that memory can overwrite the data but <span class="bold"><strong>cooperative</strong></span>
|
||
processes use mutexes to protect the data first acquiring the mutex
|
||
lock.
|
||
</li>
|
||
<li class="listitem">
|
||
<span class="bold"><strong>Mandatory locking:</strong></span> The OS kernel checks
|
||
every read and write request to verify that the operation can be performed
|
||
according to the acquired lock. Reads and writes block until the lock
|
||
is released.
|
||
</li>
|
||
</ul></div>
|
||
<p>
|
||
<span class="bold"><strong>Boost.Interprocess</strong></span> implements <span class="bold"><strong>advisory blocking</strong></span> because of portability reasons.
|
||
This means that every process accessing to a file concurrently, must cooperate
|
||
using file locks to synchronize the access.
|
||
</p>
|
||
<p>
|
||
In some systems file locking can be even further refined, leading to <span class="bold"><strong>record locking</strong></span>, where a user can specify a <span class="bold"><strong>byte range</strong></span> within the file where the lock is applied.
|
||
This allows concurrent write access by several processes if they need to
|
||
access a different byte range in the file. <span class="bold"><strong>Boost.Interprocess</strong></span>
|
||
does <span class="bold"><strong>not</strong></span> offer record locking for the
|
||
moment, but might offer it in the future. To use a file lock just include:
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">file_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
<p>
|
||
A file locking is a class that has <span class="bold"><strong>process lifetime</strong></span>.
|
||
This means that if a process holding a file lock ends or crashes, the operating
|
||
system will automatically unlock it. This feature is very useful in some
|
||
situations where we want to assure automatic unlocking even when the process
|
||
crashes and avoid leaving blocked resources in the system. A file lock
|
||
is constructed using the name of the file as an argument:
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">file_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
|
||
<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
|
||
<span class="special">{</span>
|
||
<span class="comment">//This throws if the file does not exist or it can't</span>
|
||
<span class="comment">//open it with read-write access!</span>
|
||
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">::</span><span class="identifier">file_lock</span> <span class="identifier">flock</span><span class="special">(</span><span class="string">"my_file"</span><span class="special">);</span>
|
||
<span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.file_lock.file_lock_operations"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.file_lock.file_lock_operations" title="File Locking Operations">File
|
||
Locking Operations</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
File locking has normal mutex operations plus sharable locking capabilities.
|
||
This means that we can have multiple readers holding the sharable lock
|
||
and writers holding the exclusive lock waiting until the readers end their
|
||
job.
|
||
</p>
|
||
<p>
|
||
However, file locking does <span class="bold"><strong>not</strong></span> support
|
||
upgradable locking or promotion or demotion (lock transfers), so it's more
|
||
limited than an upgradable lock. These are the operations:
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>void lock()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread tries to obtain
|
||
exclusive ownership of the file lock, and if another thread has exclusive
|
||
or sharable ownership of the mutex, it waits until it can obtain the ownership.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> <span class="bold"><strong>interprocess_exception</strong></span>
|
||
on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>bool try_lock()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread tries to acquire
|
||
exclusive ownership of the file lock without waiting. If no other thread
|
||
has exclusive or sharable ownership of the file lock, this succeeds.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Returns:</strong></span> If it can acquire exclusive ownership
|
||
immediately returns true. If it has to wait, returns false.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> <span class="bold"><strong>interprocess_exception</strong></span>
|
||
on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>bool timed_lock(const boost::posix_time::ptime
|
||
&abs_time)</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread tries to acquire
|
||
exclusive ownership of the file lock waiting if necessary until no other
|
||
thread has exclusive or sharable ownership of the file lock or abs_time
|
||
is reached.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Returns:</strong></span> If acquires exclusive ownership,
|
||
returns true. Otherwise returns false.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> <span class="bold"><strong>interprocess_exception</strong></span>
|
||
on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>void unlock()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Precondition:</strong></span> The thread must have exclusive
|
||
ownership of the file lock.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread releases the
|
||
exclusive ownership of the file lock.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> An exception derived from <span class="bold"><strong>interprocess_exception</strong></span> on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>void lock_sharable()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread tries to obtain
|
||
sharable ownership of the file lock, and if another thread has exclusive
|
||
ownership of the file lock, waits until it can obtain the ownership.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> <span class="bold"><strong>interprocess_exception</strong></span>
|
||
on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>bool try_lock_sharable()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread tries to acquire
|
||
sharable ownership of the file lock without waiting. If no other thread
|
||
has exclusive ownership of the file lock, this succeeds.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Returns:</strong></span> If it can acquire sharable ownership
|
||
immediately returns true. If it has to wait, returns false.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> <span class="bold"><strong>interprocess_exception</strong></span>
|
||
on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>bool timed_lock_sharable(const boost::posix_time::ptime
|
||
&abs_time)</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread tries to acquire
|
||
sharable ownership of the file lock waiting if necessary until no other
|
||
thread has exclusive ownership of the file lock or abs_time is reached.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Returns:</strong></span> If acquires sharable ownership,
|
||
returns true. Otherwise returns false.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> <span class="bold"><strong>interprocess_exception</strong></span>
|
||
on error.
|
||
</p>
|
||
<div class="blurb">
|
||
<div class="titlepage"><div><div><p class="title"><b></b></p></div></div></div>
|
||
<p>
|
||
<span class="emphasis"><em><span class="bold"><strong>void unlock_sharable()</strong></span></em></span>
|
||
</p>
|
||
</div>
|
||
<p>
|
||
<span class="bold"><strong>Precondition:</strong></span> The thread must have sharable
|
||
ownership of the file lock.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Effects:</strong></span> The calling thread releases the
|
||
sharable ownership of the file lock.
|
||
</p>
|
||
<p>
|
||
<span class="bold"><strong>Throws:</strong></span> An exception derived from <span class="bold"><strong>interprocess_exception</strong></span> on error.
|
||
</p>
|
||
<p>
|
||
For more file locking methods, please <code class="computeroutput"><a class="link" href="../boost/interprocess/file_lock.html" title="Class file_lock">file_lock
|
||
reference</a></code>.
|
||
</p>
|
||
<div class="important"><table border="0" summary="Important">
|
||
<tr>
|
||
<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../../doc/src/images/important.png"></td>
|
||
<th align="left">Important</th>
|
||
</tr>
|
||
<tr><td align="left" valign="top"><p>
|
||
<code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">posix_time</span><span class="special">::</span><span class="identifier">ptime</span></code> absolute time points used by
|
||
Boost.Interprocess synchronization mechanisms are UTC time points, not
|
||
local time points
|
||
</p></td></tr>
|
||
</table></div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.file_lock.file_lock_scoped_locks"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.file_lock.file_lock_scoped_locks" title="Scoped Lock and Sharable Lock With File Locking">Scoped
|
||
Lock and Sharable Lock With File Locking</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
<code class="computeroutput"><a class="link" href="../boost/interprocess/scoped_lock.html" title="Class template scoped_lock">scoped_lock</a></code>
|
||
and <code class="computeroutput"><a class="link" href="../boost/interprocess/sharable_lock.html" title="Class template sharable_lock">sharable_lock</a></code>
|
||
can be used to make file locking easier in the presence of exceptions,
|
||
just like with mutexes:
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">file_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">sharable_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="comment">//...</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 process reads the file</span>
|
||
<span class="comment">// ...</span>
|
||
<span class="comment">//Open the file lock</span>
|
||
<span class="identifier">file_lock</span> <span class="identifier">f_lock</span><span class="special">(</span><span class="string">"my_file"</span><span class="special">);</span>
|
||
|
||
<span class="special">{</span>
|
||
<span class="comment">//Construct a sharable lock with the file lock.</span>
|
||
<span class="comment">//This will call "f_lock.sharable_lock()".</span>
|
||
<span class="identifier">sharable_lock</span><span class="special"><</span><span class="identifier">file_lock</span><span class="special">></span> <span class="identifier">sh_lock</span><span class="special">(</span><span class="identifier">f_lock</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Now read the file...</span>
|
||
|
||
<span class="comment">//The sharable lock is automatically released by</span>
|
||
<span class="comment">//sh_lock's destructor</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">file_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">scoped_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
|
||
<span class="comment">//...</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 process writes the file</span>
|
||
<span class="comment">// ...</span>
|
||
<span class="comment">//Open the file lock</span>
|
||
<span class="identifier">file_lock</span> <span class="identifier">f_lock</span><span class="special">(</span><span class="string">"my_file"</span><span class="special">);</span>
|
||
|
||
<span class="special">{</span>
|
||
<span class="comment">//Construct an exclusive lock with the file lock.</span>
|
||
<span class="comment">//This will call "f_lock.lock()".</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">file_lock</span><span class="special">></span> <span class="identifier">e_lock</span><span class="special">(</span><span class="identifier">f_lock</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Now write the file...</span>
|
||
|
||
<span class="comment">//The exclusive lock is automatically released by</span>
|
||
<span class="comment">//e_lock's destructor</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
<p>
|
||
However, lock transfers are only allowed between same type of locks, that
|
||
is, from a sharable lock to another sharable lock or from a scoped lock
|
||
to another scoped lock. A transfer from a scoped lock to a sharable lock
|
||
is not allowed, because <code class="computeroutput"><a class="link" href="../boost/interprocess/file_lock.html" title="Class file_lock">file_lock</a></code>
|
||
has no lock promotion or demotion functions like <code class="computeroutput"><span class="identifier">unlock_and_lock_sharable</span><span class="special">()</span></code>. This will produce a compilation error:
|
||
</p>
|
||
<pre class="programlisting"><span class="comment">//Open the file lock</span>
|
||
<span class="identifier">file_lock</span> <span class="identifier">f_lock</span><span class="special">(</span><span class="string">"my_file"</span><span class="special">);</span>
|
||
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">file_lock</span><span class="special">></span> <span class="identifier">e_lock</span><span class="special">(</span><span class="identifier">f_lock</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Compilation error, f_lock has no "unlock_and_lock_sharable()" member!</span>
|
||
<span class="identifier">sharable_lock</span><span class="special"><</span><span class="identifier">file_lock</span><span class="special">></span> <span class="identifier">e_lock</span><span class="special">(</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">f_lock</span><span class="special">));</span>
|
||
</pre>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.file_lock.file_lock_not_thread_safe"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.file_lock.file_lock_not_thread_safe" title="Caution: Synchronization limitations">Caution:
|
||
Synchronization limitations</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
If you plan to use file locks just like named mutexes, be careful, because
|
||
portable file locks have synchronization limitations, mainly because different
|
||
implementations (POSIX, Windows) offer different guarantees. Interprocess
|
||
file locks have the following limitations:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
It's unspecified if a <code class="computeroutput"><span class="identifier">file_lock</span></code>
|
||
synchronizes <span class="bold"><strong>two threads from the same process</strong></span>.
|
||
</li>
|
||
<li class="listitem">
|
||
It's unspecified if a process can use two <code class="computeroutput"><span class="identifier">file_lock</span></code>
|
||
objects pointing to the same file.
|
||
</li>
|
||
</ul></div>
|
||
<p>
|
||
The first limitation comes mainly from POSIX, since a file handle is a
|
||
per-process attribute and not a per-thread attribute. This means that if
|
||
a thread uses a <code class="computeroutput"><span class="identifier">file_lock</span></code>
|
||
object to lock a file, other threads will see the file as locked. Windows
|
||
file locking mechanism, on the other hand, offer thread-synchronization
|
||
guarantees so a thread trying to lock the already locked file, would block.
|
||
</p>
|
||
<p>
|
||
The second limitation comes from the fact that file locking synchronization
|
||
state is tied with a single file descriptor in Windows. This means that
|
||
if two <code class="computeroutput"><span class="identifier">file_lock</span></code> objects
|
||
are created pointing to the same file, no synchronization is guaranteed.
|
||
In POSIX, when two file descriptors are used to lock a file if a descriptor
|
||
is closed, all file locks set by the calling process are cleared.
|
||
</p>
|
||
<p>
|
||
To sum up, if you plan to use portable file locking in your processes,
|
||
use the following restrictions:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
<span class="bold"><strong>For each file, use a single <code class="computeroutput"><span class="identifier">file_lock</span></code>
|
||
object per process.</strong></span>
|
||
</li>
|
||
<li class="listitem">
|
||
<span class="bold"><strong>Use the same thread to lock and unlock a file.</strong></span>
|
||
</li>
|
||
<li class="listitem">
|
||
If you are using a std::fstream/native file handle to write to the
|
||
file while using file locks on that file, <span class="bold"><strong>don't
|
||
close the file before releasing all the locks of the file.</strong></span>
|
||
</li>
|
||
</ul></div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.file_lock.file_lock_careful_iostream"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.file_lock.file_lock_careful_iostream" title="Be Careful With Iostream Writing">Be
|
||
Careful With Iostream Writing</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
As we've seen file locking can be useful to synchronize two processes,
|
||
but <span class="bold"><strong>make sure data is written to the file</strong></span>
|
||
before unlocking the file lock. Take in care that iostream classes do some
|
||
kind of buffering, so if you want to make sure that other processes can
|
||
see the data you've written, you have the following alternatives:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
Use native file functions (read()/write() in Unix systems and ReadFile/WriteFile
|
||
in Windows systems) instead of iostream.
|
||
</li>
|
||
<li class="listitem">
|
||
Flush data before unlocking the file lock in writers using <code class="computeroutput"><span class="identifier">fflush</span></code> if you are using standard
|
||
C functions or the <code class="computeroutput"><span class="identifier">flush</span><span class="special">()</span></code> member function when using C++ iostreams.
|
||
In windows you can't even use another class to access the same file.
|
||
</li>
|
||
</ul></div>
|
||
<pre class="programlisting"><span class="comment">//...</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 process writes the file</span>
|
||
<span class="comment">// ...</span>
|
||
<span class="comment">//Open the file lock</span>
|
||
<span class="identifier">fstream</span> <span class="identifier">file</span><span class="special">(</span><span class="string">"my_file"</span><span class="special">)</span>
|
||
<span class="identifier">file_lock</span> <span class="identifier">f_lock</span><span class="special">(</span><span class="string">"my_lock_file"</span><span class="special">);</span>
|
||
|
||
<span class="special">{</span>
|
||
<span class="identifier">scoped_lock</span><span class="special"><</span><span class="identifier">file_lock</span><span class="special">></span> <span class="identifier">e_lock</span><span class="special">(</span><span class="identifier">f_lock</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Now write the file...</span>
|
||
|
||
<span class="comment">//Flush data before unlocking the exclusive lock</span>
|
||
<span class="identifier">file</span><span class="special">.</span><span class="identifier">flush</span><span class="special">();</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
</div>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h3 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.message_queue"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.message_queue" title="Message Queue">Message
|
||
Queue</a>
|
||
</h3></div></div></div>
|
||
<div class="toc"><dl class="toc">
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.message_queue.message_queue_whats_a_mq">What's
|
||
A Message Queue?</a></span></dt>
|
||
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.message_queue.message_queue_example">Using
|
||
a message queue</a></span></dt>
|
||
</dl></div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.message_queue.message_queue_whats_a_mq"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.message_queue.message_queue_whats_a_mq" title="What's A Message Queue?">What's
|
||
A Message Queue?</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
A message queue is similar to a list of messages. Threads can put messages
|
||
in the queue and they can also remove messages from the queue. Each message
|
||
can have also a <span class="bold"><strong>priority</strong></span> so that higher
|
||
priority messages are read before lower priority messages. Each message
|
||
has some attributes:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
A priority.
|
||
</li>
|
||
<li class="listitem">
|
||
The length of the message.
|
||
</li>
|
||
<li class="listitem">
|
||
The data (if length is bigger than 0).
|
||
</li>
|
||
</ul></div>
|
||
<p>
|
||
A thread can send a message to or receive a message from the message queue
|
||
using 3 methods:
|
||
</p>
|
||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
|
||
<li class="listitem">
|
||
<span class="bold"><strong>Blocking</strong></span>: If the message queue is
|
||
full when sending or the message queue is empty when receiving, the
|
||
thread is blocked until there is room for a new message or there is
|
||
a new message.
|
||
</li>
|
||
<li class="listitem">
|
||
<span class="bold"><strong>Try</strong></span>: If the message queue is full
|
||
when sending or the message queue is empty when receiving, the thread
|
||
returns immediately with an error.
|
||
</li>
|
||
<li class="listitem">
|
||
<span class="bold"><strong>Timed</strong></span>: If the message queue is full
|
||
when sending or the message queue is empty when receiving, the thread
|
||
retries the operation until succeeds (returning successful state) or
|
||
a timeout is reached (returning a failure).
|
||
</li>
|
||
</ul></div>
|
||
<p>
|
||
A message queue <span class="bold"><strong>just copies raw bytes between processes</strong></span>
|
||
and does not send objects. This means that if we want to send an object
|
||
using a message queue <span class="bold"><strong>the object must be binary serializable</strong></span>.
|
||
For example, we can send integers between processes but <span class="bold"><strong>not</strong></span>
|
||
a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></code>. You should use <span class="bold"><strong>Boost.Serialization</strong></span>
|
||
or use advanced <span class="bold"><strong>Boost.Interprocess</strong></span> mechanisms
|
||
to send complex data between processes.
|
||
</p>
|
||
<p>
|
||
The <span class="bold"><strong>Boost.Interprocess</strong></span> message queue is
|
||
a named interprocess communication: the message queue is created with a
|
||
name and it's opened with a name, just like a file. When creating a message
|
||
queue, the user must specify the maximum message size and the maximum message
|
||
number that the message queue can store. These parameters will define the
|
||
resources (for example the size of the shared memory used to implement
|
||
the message queue if shared memory is used).
|
||
</p>
|
||
<pre class="programlisting"><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">//Create a message_queue. If the queue</span>
|
||
<span class="comment">//exists throws an exception</span>
|
||
<span class="identifier">message_queue</span> <span class="identifier">mq</span>
|
||
<span class="special">(</span><span class="identifier">create_only</span> <span class="comment">//only create</span>
|
||
<span class="special">,</span><span class="string">"message_queue"</span> <span class="comment">//name</span>
|
||
<span class="special">,</span><span class="number">100</span> <span class="comment">//max message number</span>
|
||
<span class="special">,</span><span class="number">100</span> <span class="comment">//max message size</span>
|
||
<span class="special">);</span>
|
||
</pre>
|
||
<pre class="programlisting"><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">//Creates or opens a message_queue. If the queue</span>
|
||
<span class="comment">//does not exist creates it, otherwise opens it.</span>
|
||
<span class="comment">//Message number and size are ignored if the queue</span>
|
||
<span class="comment">//is opened</span>
|
||
<span class="identifier">message_queue</span> <span class="identifier">mq</span>
|
||
<span class="special">(</span><span class="identifier">open_or_create</span> <span class="comment">//open or create</span>
|
||
<span class="special">,</span><span class="string">"message_queue"</span> <span class="comment">//name</span>
|
||
<span class="special">,</span><span class="number">100</span> <span class="comment">//max message number</span>
|
||
<span class="special">,</span><span class="number">100</span> <span class="comment">//max message size</span>
|
||
<span class="special">);</span>
|
||
</pre>
|
||
<pre class="programlisting"><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">//Opens a message_queue. If the queue</span>
|
||
<span class="comment">//does not exist throws an exception.</span>
|
||
<span class="identifier">message_queue</span> <span class="identifier">mq</span>
|
||
<span class="special">(</span><span class="identifier">open_only</span> <span class="comment">//only open</span>
|
||
<span class="special">,</span><span class="string">"message_queue"</span> <span class="comment">//name</span>
|
||
<span class="special">);</span>
|
||
</pre>
|
||
<p>
|
||
The message queue is explicitly removed calling the static <code class="computeroutput"><span class="identifier">remove</span></code> function:
|
||
</p>
|
||
<pre class="programlisting"><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="identifier">message_queue</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"message_queue"</span><span class="special">);</span>
|
||
</pre>
|
||
<p>
|
||
The function can fail if the message queue is still being used by any process.
|
||
</p>
|
||
</div>
|
||
<div class="section">
|
||
<div class="titlepage"><div><div><h4 class="title">
|
||
<a name="interprocess.synchronization_mechanisms.message_queue.message_queue_example"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.message_queue.message_queue_example" title="Using a message queue">Using
|
||
a message queue</a>
|
||
</h4></div></div></div>
|
||
<p>
|
||
To use a message queue you must include the following header:
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">ipc</span><span class="special">/</span><span class="identifier">message_queue</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
</pre>
|
||
<p>
|
||
In the following example, the first process creates the message queue,
|
||
and writes an array of integers on it. The other process just reads the
|
||
array and checks that the sequence number is correct. This is the first
|
||
process:
|
||
</p>
|
||
<p>
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">ipc</span><span class="special">/</span><span class="identifier">message_queue</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">vector</span><span class="special">></span>
|
||
|
||
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span>
|
||
|
||
<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span>
|
||
<span class="special">{</span>
|
||
<span class="keyword">try</span><span class="special">{</span>
|
||
<span class="comment">//Erase previous message queue</span>
|
||
<span class="identifier">message_queue</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"message_queue"</span><span class="special">);</span>
|
||
|
||
<span class="comment">//Create a message_queue.</span>
|
||
<span class="identifier">message_queue</span> <span class="identifier">mq</span>
|
||
<span class="special">(</span><span class="identifier">create_only</span> <span class="comment">//only create</span>
|
||
<span class="special">,</span><span class="string">"message_queue"</span> <span class="comment">//name</span>
|
||
<span class="special">,</span><span class="number">100</span> <span class="comment">//max message number</span>
|
||
<span class="special">,</span><span class="keyword">sizeof</span><span class="special">(</span><span class="keyword">int</span><span class="special">)</span> <span class="comment">//max message size</span>
|
||
<span class="special">);</span>
|
||
|
||
<span class="comment">//Send 100 numbers</span>
|
||
<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special"><</span> <span class="number">100</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
|
||
<span class="identifier">mq</span><span class="special">.</span><span class="identifier">send</span><span class="special">(&</span><span class="identifier">i</span><span class="special">,</span> <span class="keyword">sizeof</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="special">}</span>
|
||
<span class="special">}</span>
|
||
<span class="keyword">catch</span><span class="special">(</span><span class="identifier">interprocess_exception</span> <span class="special">&</span><span class="identifier">ex</span><span class="special">){</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">ex</span><span class="special">.</span><span class="identifier">what</span><span class="special">()</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</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">return</span> <span class="number">0</span><span class="special">;</span>
|
||
<span class="special">}</span>
|
||
</pre>
|
||
<p>
|
||
</p>
|
||
<p>
|
||
This is the second process:
|
||
</p>
|
||
<p>
|
||
</p>
|
||
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">ipc</span><span class="special">/</span><span class="identifier">message_queue</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">iostream</span><span class="special">></span>
|
||
<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">vector</span><span class="special">></span>
|
||
|
||
<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span>
|
||
|
||
<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span>
|
||
<span class="special">{</span>
|
||
<span class="keyword">try</span><span class="special">{</span>
|
||
<span class="comment">//Open a message queue.</span>
|
||
<span class="identifier">message_queue</span> <span class="identifier">mq</span>
|
||
<span class="special">(</span><span class="identifier">open_only</span> <span class="comment">//only open</span>
|
||
<span class="special">,</span><span class="string">"message_queue"</span> <span class="comment">//name</span>
|
||
<span class="special">);</span>
|
||
|
||
<span class="keyword">unsigned</span> <span class="keyword">int</span> <span class="identifier">priority</span><span class="special">;</span>
|
||
<span class="identifier">message_queue</span><span class="special">::</span><span class="identifier">size_type</span> <span class="identifier">recvd_size</span><span class="special">;</span>
|
||
|
||
<span class="comment">//Receive 100 numbers</span>
|
||
<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special"><</span> <span class="number">100</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
|
||
<span class="keyword">int</span> <span class="identifier">number</span><span class="special">;</span>
|
||
<span class="identifier">mq</span><span class="special">.</span><span class="identifier">receive</span><span class="special">(&</span><span class="identifier">number</span><span class="special">,</span> <span class="keyword">sizeof</span><span class="special">(</span><span class="identifier">number</span><span class="special">),</span> <span class="identifier">recvd_size</span><span class="special">,</span> <span class="identifier">priority</span><span class="special">);</span>
|
||
<span class="keyword">if</span><span class="special">(</span><span class="identifier">number</span> <span class="special">!=</span> <span class="identifier">i</span> <span class="special">||</span> <span class="identifier">recvd_size</span> <span class="special">!=</span> <span class="keyword">sizeof</span><span class="special">(</span><span class="identifier">number</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="keyword">catch</span><span class="special">(</span><span class="identifier">interprocess_exception</span> <span class="special">&</span><span class="identifier">ex</span><span class="special">){</span>
|
||
<span class="identifier">message_queue</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"message_queue"</span><span class="special">);</span>
|
||
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">ex</span><span class="special">.</span><span class="identifier">what</span><span class="special">()</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</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="identifier">message_queue</span><span class="special">::</span><span class="identifier">remove</span><span class="special">(</span><span class="string">"message_queue"</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 know more about this class and all its operations, please see the <code class="computeroutput"><a class="link" href="../boost/interprocess/message_queue.html" title="Type definition message_queue">message_queue</a></code> class
|
||
reference.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
|
||
<td align="left"></td>
|
||
<td align="right"><div class="copyright-footer">Copyright © 2005-2015 Ion Gaztanaga<p>
|
||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
|
||
</p>
|
||
</div></td>
|
||
</tr></table>
|
||
<hr>
|
||
<div class="spirit-nav">
|
||
<a accesskey="p" href="offset_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="managed_memory_segments.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
|
||
</div>
|
||
</body>
|
||
</html>
|