Sophie

Sophie

distrib > Fedora > 14 > i386 > by-pkgid > 623999701586b0ea103ff2ccad7954a6 > files > 5284

boost-doc-1.44.0-1.fc14.noarch.rpm

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Synchronization mechanisms</title>
<link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
<link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset">
<link rel="up" href="../interprocess.html" title="Chapter&#160;9.&#160;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>
<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.upgradable_mutexes">
      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>
<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" 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" 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>
<p>
        </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>
<p>
        </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" 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>
<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>
<p>
        </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" 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="sidebar">
<p class="title"><b></b></p>
<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="sidebar">
<p class="title"><b></b></p>
<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="sidebar">
<p class="title"><b></b></p>
<p>
          <span class="emphasis"><em><span class="bold"><strong>bool timed_lock(const boost::posix_time::ptime
          &amp;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="sidebar">
<p class="title"><b></b></p>
<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>
<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>
<p>
        </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">interprocess_mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" 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>
<p>
        </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">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">&gt;</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
              <code class="computeroutput"><a class="link" href="../boost/interprocess/interprocess_recursive__id829710.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>
<p>
        </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">named_mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" 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>
<p>
        </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">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">&gt;</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" 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>
<p>
        </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">scoped_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</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>
<p>
        </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">&lt;</span><span class="identifier">MutexType</span><span class="special">&gt;</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">&lt;</span><span class="identifier">MutexType</span><span class="special">&gt;</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">&lt;</span><span class="identifier">MutexType</span><span class="special">&gt;</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>
<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>
<p>
            
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">interprocess_mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</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>
        </p>
<p>
          This is the process main process. Creates the shared memory, constructs
          the cyclic buffer and start writing traces:
        </p>
<p>
          </p>
<p>
            
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">shared_memory_object</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">mapped_region</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">scoped_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="string">"doc_anonymous_mutex_shared_data.hpp"</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cstdio</span><span class="special">&gt;</span>

<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span>

<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span>
<span class="special">{</span>
   <span class="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">&lt;</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">&lt;</span><span class="identifier">interprocess_mutex</span><span class="special">&gt;</span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">data</span><span class="special">-&gt;</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">-&gt;</span><span class="identifier">items</span><span class="special">[(</span><span class="identifier">data</span><span class="special">-&gt;</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">-&gt;</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">&lt;</span><span class="identifier">interprocess_mutex</span><span class="special">&gt;</span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">data</span><span class="special">-&gt;</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">-&gt;</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">&amp;</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">&lt;&lt;</span> <span class="identifier">ex</span><span class="special">.</span><span class="identifier">what</span><span class="special">()</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
      <span class="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>
        </p>
<p>
          The second process opens the shared memory, obtains access to the cyclic
          buffer and starts writing traces:
        </p>
<p>
          </p>
<p>
            
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">shared_memory_object</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">mapped_region</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">scoped_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="string">"doc_anonymous_mutex_shared_data.hpp"</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cstdio</span><span class="special">&gt;</span>

<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span>

<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span>
<span class="special">{</span>
   <span class="comment">//Remove shared memory on 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">&lt;</span><span class="identifier">shared_memory_log</span><span class="special">*&gt;(</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">&lt;</span> <span class="number">100</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
      <span class="comment">//Lock the mutex
</span>      <span class="identifier">scoped_lock</span><span class="special">&lt;</span><span class="identifier">interprocess_mutex</span><span class="special">&gt;</span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">data</span><span class="special">-&gt;</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">-&gt;</span><span class="identifier">items</span><span class="special">[(</span><span class="identifier">data</span><span class="special">-&gt;</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">-&gt;</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">&lt;</span><span class="identifier">interprocess_mutex</span><span class="special">&gt;</span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">data</span><span class="special">-&gt;</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">-&gt;</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>
        </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>
<p>
            
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">scoped_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">named_mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">fstream</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cstdio</span><span class="special">&gt;</span>


<span class="keyword">int</span> <span class="identifier">main</span> <span class="special">()</span>
<span class="special">{</span>
   <span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">interprocess</span><span class="special">;</span>
   <span class="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">&lt;</span> <span class="number">10</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
         
         <span class="comment">//Do some operations...
</span>
         <span class="comment">//Write to file atomically
</span>         <span class="identifier">scoped_lock</span><span class="special">&lt;</span><span class="identifier">named_mutex</span><span class="special">&gt;</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">&lt;&lt;</span> <span class="string">"Process name, "</span><span class="special">;</span>
         <span class="identifier">file</span> <span class="special">&lt;&lt;</span> <span class="string">"This is iteration #"</span> <span class="special">&lt;&lt;</span> <span class="identifier">i</span><span class="special">;</span>
         <span class="identifier">file</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
      <span class="special">}</span>
   <span class="special">}</span>
   <span class="keyword">catch</span><span class="special">(</span><span class="identifier">interprocess_exception</span> <span class="special">&amp;</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">&lt;&lt;</span> <span class="identifier">ex</span><span class="special">.</span><span class="identifier">what</span><span class="special">()</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
      <span class="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>
        </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>
<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" 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>
<p>
        </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">interprocess_condition</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" 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>
<p>
        </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">named_condition</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" 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>
<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" 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>
<p>
            
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">interprocess_mutex</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">interprocess_condition</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</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>
        </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>
<p>
            
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">shared_memory_object</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">mapped_region</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">scoped_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cstdio</span><span class="special">&gt;</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">&lt;</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">&lt;</span><span class="identifier">interprocess_mutex</span><span class="special">&gt;</span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">data</span><span class="special">-&gt;</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">-&gt;</span><span class="identifier">message_in</span><span class="special">){</span>
            <span class="identifier">data</span><span class="special">-&gt;</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">-&gt;</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">-&gt;</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">-&gt;</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">-&gt;</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">&amp;</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">&lt;&lt;</span> <span class="identifier">ex</span><span class="special">.</span><span class="identifier">what</span><span class="special">()</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
      <span class="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>
        </p>
<p>
          The second process opens the shared memory and prints each message until
          the "last message" message is received:
        </p>
<p>
          </p>
<p>
            
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">shared_memory_object</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">mapped_region</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">scoped_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">cstring</span><span class="special">&gt;</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">&lt;</span><span class="identifier">trace_queue</span><span class="special">*&gt;(</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">&lt;</span><span class="identifier">interprocess_mutex</span><span class="special">&gt;</span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">data</span><span class="special">-&gt;</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">-&gt;</span><span class="identifier">message_in</span><span class="special">){</span>
            <span class="identifier">data</span><span class="special">-&gt;</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">-&gt;</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">&lt;&lt;</span> <span class="identifier">data</span><span class="special">-&gt;</span><span class="identifier">items</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
            <span class="comment">//Notify the other process that the buffer is empty
</span>            <span class="identifier">data</span><span class="special">-&gt;</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">-&gt;</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">&amp;</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">&lt;&lt;</span> <span class="identifier">ex</span><span class="special">.</span><span class="identifier">what</span><span class="special">()</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
      <span class="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>
        </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>
<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" 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>
<p>
        </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">interprocess_semaphore</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" 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>
<p>
        </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">named_semaphore</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" 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>
<p>
            
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">interprocess_semaphore</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</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>
        </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>
<p>
            
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">shared_memory_object</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">mapped_region</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</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">&lt;</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">-&gt;</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">-&gt;</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">-&gt;</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">-&gt;</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">-&gt;</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>
        </p>
<p>
          The second process opens the shared memory and copies the received integers
          to it's own buffer:
        </p>
<p>
          </p>
<p>
            
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">shared_memory_object</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">mapped_region</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</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">&lt;</span><span class="identifier">shared_memory_buffer</span><span class="special">*&gt;(</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">&lt;</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">-&gt;</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">-&gt;</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">-&gt;</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">-&gt;</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">-&gt;</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>
        </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.upgradable_mutexes"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes" title="Upgradable Mutexes">
      Upgradable Mutexes</a>
</h3></div></div></div>
<div class="toc"><dl>
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_whats_a_mutex">
        What's An Upgradable Mutex?</a></span></dt>
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_mutexes_operations">
        Upgradable Mutex Operations</a></span></dt>
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_mutexes_mutex_interprocess_mutexes">
        Boost.Interprocess Upgradable Mutex Types And Headers</a></span></dt>
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_mutexes_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.upgradable_mutexes.upgradable_whats_a_mutex"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_whats_a_mutex" title="What's An Upgradable Mutex?">
        What's An Upgradable Mutex?</a>
</h4></div></div></div>
<p>
          An upgradable mutex is a special mutex 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
          an upgradable mutex we can acquire 3 lock types:
        </p>
<div class="itemizedlist"><ul class="itemizedlist" 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 has a sharable or upgradable lock 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 acquire a sharable lock or an upgradable
              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>
<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="id1333009"></a><p class="title"><b>Table&#160;9.5.&#160;Locking Possibilities</b></p>
<div class="table-contents"><table class="table" summary="Locking Possibilities">
<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"><p>
          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="id1333124"></a><p class="title"><b>Table&#160;9.6.&#160;Transition Possibilities</b></p>
<div class="table-contents"><table class="table" summary="Transition Possibilities">
<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.upgradable_mutexes.upgradable_mutexes_operations"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_mutexes_operations" title="Upgradable Mutex Operations">
        Upgradable Mutex Operations</a>
</h4></div></div></div>
<div class="toc"><dl>
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_mutexes_operations.upgradable_mutexes_operations_exclusive">
          Exclusive Locking</a></span></dt>
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_mutexes_operations.upgradable_mutexes_operations_sharable">
          Sharable Locking</a></span></dt>
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_mutexes_operations.upgradable_mutexes_operations_upgradable">
          Upgradable Locking</a></span></dt>
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_mutexes_operations.upgradable_mutexes_operations_demotions">
          Demotions</a></span></dt>
<dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_mutexes_operations.upgradable_mutexes_operations_promotions">
          Promotions</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.upgradable_mutexes.upgradable_mutexes_operations.upgradable_mutexes_operations_exclusive"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_mutexes_operations.upgradable_mutexes_operations_exclusive" title="Exclusive Locking">
          Exclusive Locking</a>
</h5></div></div></div>
<div class="sidebar">
<p class="title"><b></b></p>
<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 exclusive,
            sharable or upgradable 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="sidebar">
<p class="title"><b></b></p>
<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 exclusive, sharable or upgradable ownership of the mutex 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="sidebar">
<p class="title"><b></b></p>
<p>
            <span class="emphasis"><em><span class="bold"><strong>bool timed_lock(const boost::posix_time::ptime
            &amp;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 has exclusive, sharable or upgradable ownership of the
            mutex 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="sidebar">
<p class="title"><b></b></p>
<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.upgradable_mutexes.upgradable_mutexes_operations.upgradable_mutexes_operations_sharable"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_mutexes_operations.upgradable_mutexes_operations_sharable" title="Sharable Locking">
          Sharable Locking</a>
</h5></div></div></div>
<div class="sidebar">
<p class="title"><b></b></p>
<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
            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="sidebar">
<p class="title"><b></b></p>
<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 has exclusive or upgradable 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="sidebar">
<p class="title"><b></b></p>
<p>
            <span class="emphasis"><em><span class="bold"><strong>bool timed_lock_sharable(const boost::posix_time::ptime
            &amp;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 has exclusive or upgradable 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="sidebar">
<p class="title"><b></b></p>
<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.upgradable_mutexes.upgradable_mutexes_operations.upgradable_mutexes_operations_upgradable"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_mutexes_operations.upgradable_mutexes_operations_upgradable" title="Upgradable Locking">
          Upgradable Locking</a>
</h5></div></div></div>
<div class="sidebar">
<p class="title"><b></b></p>
<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="sidebar">
<p class="title"><b></b></p>
<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 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="sidebar">
<p class="title"><b></b></p>
<p>
            <span class="emphasis"><em><span class="bold"><strong>bool timed_lock_upgradable(const boost::posix_time::ptime
            &amp;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 has exclusive or upgradable 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="sidebar">
<p class="title"><b></b></p>
<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.upgradable_mutexes.upgradable_mutexes_operations.upgradable_mutexes_operations_demotions"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_mutexes_operations.upgradable_mutexes_operations_demotions" title="Demotions">
          Demotions</a>
</h5></div></div></div>
<div class="sidebar">
<p class="title"><b></b></p>
<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="sidebar">
<p class="title"><b></b></p>
<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="sidebar">
<p class="title"><b></b></p>
<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.upgradable_mutexes.upgradable_mutexes_operations.upgradable_mutexes_operations_promotions"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_mutexes_operations.upgradable_mutexes_operations_promotions" title="Promotions">
          Promotions</a>
</h5></div></div></div>
<div class="sidebar">
<p class="title"><b></b></p>
<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="sidebar">
<p class="title"><b></b></p>
<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="sidebar">
<p class="title"><b></b></p>
<p>
            <span class="emphasis"><em><span class="bold"><strong>bool timed_unlock_upgradable_and_lock(const
            boost::posix_time::ptime &amp;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="sidebar">
<p class="title"><b></b></p>
<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="sidebar">
<p class="title"><b></b></p>
<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>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_mutexes_mutex_interprocess_mutexes"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_mutexes_mutex_interprocess_mutexes" title="Boost.Interprocess Upgradable Mutex Types And Headers">
        Boost.Interprocess Upgradable Mutex Types And Headers</a>
</h4></div></div></div>
<p>
          Boost.Interprocess offers the following upgradable mutex types:
        </p>
<p>
        </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">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">&gt;</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
              <code class="computeroutput"><a class="link" href="../boost/interprocess/interprocess_upgradable_id829946.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>
<p>
        </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">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">&gt;</span>
</pre>
<div class="itemizedlist"><ul class="itemizedlist" 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.upgradable_mutexes.upgradable_mutexes_locks"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_mutexes_locks" title="Sharable Lock And Upgradable Lock">
        Sharable Lock And Upgradable Lock</a>
</h4></div></div></div>
<div class="toc"><dl><dt><span class="section"><a href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_mutexes_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.upgradable_mutexes.upgradable_mutexes_locks.upgradable_mutexes_lock_types"></a><a class="link" href="synchronization_mechanisms.html#interprocess.synchronization_mechanisms.upgradable_mutexes.upgradable_mutexes_locks.upgradable_mutexes_lock_types" title="Sharable Lock And Upgradable Lock Headers">
          Sharable Lock And Upgradable Lock Headers</a>
</h5></div></div></div>
<p>
          </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">sharable_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
</pre>
<p>
          </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">upgradable_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</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. Scoped lock has many constructors to lock, try_lock, timed_lock
          a mutex or not to lock it at all.
        </p>
<p>
        </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 call lock_sharable()
</span>   <span class="identifier">sharable_lock</span><span class="special">&lt;</span><span class="identifier">MutexType</span><span class="special">&gt;</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 won't lock the mutex()
</span>   <span class="identifier">sharable_lock</span><span class="special">&lt;</span><span class="identifier">MutexType</span><span class="special">&gt;</span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">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">&lt;</span><span class="identifier">MutexType</span><span class="special">&gt;</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 call timed_lock_sharable()
</span>   <span class="identifier">scoped_lock</span><span class="special">&lt;</span><span class="identifier">MutexType</span><span class="special">&gt;</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>

<span class="special">{</span>
   <span class="comment">//This will call lock_upgradable()
</span>   <span class="identifier">upgradable_lock</span><span class="special">&lt;</span><span class="identifier">MutexType</span><span class="special">&gt;</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 won't lock the mutex()
</span>   <span class="identifier">upgradable_lock</span><span class="special">&lt;</span><span class="identifier">MutexType</span><span class="special">&gt;</span> <span class="identifier">lock</span><span class="special">(</span><span class="identifier">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">&lt;</span><span class="identifier">MutexType</span><span class="special">&gt;</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 call timed_lock_upgradable()
</span>   <span class="identifier">scoped_lock</span><span class="special">&lt;</span><span class="identifier">MutexType</span><span class="special">&gt;</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>
          <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>
</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>
<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="sidebar">
<p class="title"><b></b></p>
<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>
<p>
        </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>
<p>
        </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>
<p>
        </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>
<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" 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 -&gt; Upgradable, Scoped -&gt; Sharable, Upgradable -&gt; 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 -&gt; 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 -&gt; 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>
<p>
          </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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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>
<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>
<p>
          </p>
<pre class="programlisting"><span class="comment">//Conversions to upgradable
</span><span class="special">{</span>
   <span class="identifier">sharable_lock</span><span class="special">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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>
<p>
          </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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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>
<p>
        </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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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>
<p>
        </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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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" 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>
<p>
        </p>
<pre class="programlisting"><span class="special">{</span>
   <span class="identifier">scoped_lock</span><span class="special">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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" 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>
<p>
        </p>
<pre class="programlisting"><span class="special">{</span>
   <span class="identifier">scoped_lock</span><span class="special">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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>
<p>
        </p>
<pre class="programlisting"><span class="special">{</span>
   <span class="identifier">sharable_lock</span><span class="special">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&lt;</span><span class="identifier">Mutex</span><span class="special">&gt;</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">&amp;</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>
<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" 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>
<p>
        </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">file_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</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>
<p>
        </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">file_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>

<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
<span class="special">{</span>
   <span class="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="sidebar">
<p class="title"><b></b></p>
<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="sidebar">
<p class="title"><b></b></p>
<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="sidebar">
<p class="title"><b></b></p>
<p>
          <span class="emphasis"><em><span class="bold"><strong>bool timed_lock(const boost::posix_time::ptime
          &amp;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 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="sidebar">
<p class="title"><b></b></p>
<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="sidebar">
<p class="title"><b></b></p>
<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="sidebar">
<p class="title"><b></b></p>
<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 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="sidebar">
<p class="title"><b></b></p>
<p>
          <span class="emphasis"><em><span class="bold"><strong>bool timed_lock_sharable(const boost::posix_time::ptime
          &amp;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 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="sidebar">
<p class="title"><b></b></p>
<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>
<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>
<p>
        </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">file_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">sharable_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="comment">//...
</span>
<span class="keyword">using</span> <span class="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 filel lock.
</span>   <span class="comment">//This will call "f_lock.sharable_lock()".
</span>   <span class="identifier">sharable_lock</span><span class="special">&lt;</span><span class="identifier">file_lock</span><span class="special">&gt;</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>
<p>
        </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">file_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">sync</span><span class="special">/</span><span class="identifier">scoped_lock</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>

<span class="comment">//...
</span>
<span class="keyword">using</span> <span class="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 a sharable lock with the filel lock.
</span>   <span class="comment">//This will call "f_lock.lock()".
</span>   <span class="identifier">scoped_lock</span><span class="special">&lt;</span><span class="identifier">file_lock</span><span class="special">&gt;</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>
<p>
        </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">&lt;</span><span class="identifier">file_lock</span><span class="special">&gt;</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">&lt;</span><span class="identifier">file_lock</span><span class="special">&gt;</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" 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" 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 reading
          and writing to a file, 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" 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.
            </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_file"</span><span class="special">);</span>

<span class="special">{</span>
   <span class="identifier">scoped_lock</span><span class="special">&lt;</span><span class="identifier">file_lock</span><span class="special">&gt;</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>
<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" 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" 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>
<p>
        </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>
<p>
        </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">//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>
<p>
        </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">//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>
<p>
        </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>
<p>
        </p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">ipc</span><span class="special">/</span><span class="identifier">message_queue</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</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>
<p>
            
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">ipc</span><span class="special">/</span><span class="identifier">message_queue</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">vector</span><span class="special">&gt;</span>

<span class="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">&lt;</span> <span class="number">100</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
         <span class="identifier">mq</span><span class="special">.</span><span class="identifier">send</span><span class="special">(&amp;</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">&amp;</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">&lt;&lt;</span> <span class="identifier">ex</span><span class="special">.</span><span class="identifier">what</span><span class="special">()</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
      <span class="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>
        </p>
<p>
          This is the second process:
        </p>
<p>
          </p>
<p>
            
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">interprocess</span><span class="special">/</span><span class="identifier">ipc</span><span class="special">/</span><span class="identifier">message_queue</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">vector</span><span class="special">&gt;</span>

<span class="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 create
</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">std</span><span class="special">::</span><span class="identifier">size_t</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">&lt;</span> <span class="number">100</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
         <span class="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">(&amp;</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">&amp;</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">&lt;&lt;</span> <span class="identifier">ex</span><span class="special">.</span><span class="identifier">what</span><span class="special">()</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
      <span class="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>
        </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="Class 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 &#169; 2005 - 2008 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>