mirror of
https://github.com/boostorg/thread.git
synced 2026-01-29 20:12:10 +00:00
243 lines
8.9 KiB
HTML
243 lines
8.9 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content=
|
|
"text/html; charset=iso-8859-1">
|
|
<meta name="keywords" content="threads, BTL, thread library, C++">
|
|
<link rel="stylesheet" type="text/css" href="styles.css">
|
|
|
|
<title>Boost.Threads, semaphore</title>
|
|
</head>
|
|
|
|
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080">
|
|
<table summary="header" border="0" cellpadding="7" cellspacing="0"
|
|
width="100%">
|
|
<tr>
|
|
<td valign="top" width="300">
|
|
<h3><img height="86" alt="C++ Boost" src=
|
|
"../../../c++boost.gif" width="277"></h3>
|
|
</td>
|
|
|
|
<td valign="top">
|
|
<h1 align="center">Boost.Threads</h1>
|
|
|
|
<h2 align="center">semaphore</h2>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<hr>
|
|
|
|
<p><a href="#Introduction">Introduction</a><br>
|
|
<a href="#Header">Header</a><br>
|
|
<a href="#Synopsis">Synopsis</a><br>
|
|
<a href="#Members">Members</a><br>
|
|
<a href="#Example">Example</a></p>
|
|
|
|
<h2><a name="Introduction">Introduction</a></h2>
|
|
|
|
<p>The <tt>semaphore</tt> class defines a classic synchronization
|
|
primitive invented by the Dutch computer scientist Edsger W. Dijkstra.
|
|
A semaphore manages an internal counter. This counter never goes below
|
|
zero, or above a specified maximum value. When calling <tt>
|
|
semaphore::down</tt> the calling thread will block until the value is
|
|
non-zero and then decrement the value in a single atomic operation.
|
|
When calling <tt>semaphore::up</tt> the calling thread will increment
|
|
the value in a single atomic operation, failing if the value has
|
|
already reached the specified maximum.</p>
|
|
|
|
<p><b>Rationale:</b> The semaphore is the simplest synchronization
|
|
primitive available and is generally the primitive used to build other
|
|
synchronization concepts at some level of implementation. For this
|
|
reason <b>Boost.Threads</b> defines the <tt>semaphore</tt> type in the
|
|
classic form. This simplifies usage and implementation, but it means
|
|
that the interface is not as safe as other <b>Boost.Threads</b>
|
|
interfaces.</p>
|
|
|
|
<p><b><a name="Danger">Danger</a>:</b> Unlike the <a href=
|
|
"mutex_concept.html">mutex models</a> supplied by <b>Boost.Threads,</b>
|
|
there is no <a href="lock_concept.html">lock_concept</a> for the
|
|
semaphore to help ensure proper usage. Great care must be taken when
|
|
using a <tt>semaphore</tt> object to ensure <a href=
|
|
"definitions.html#Deadlock">deadlock</a> or <a href=
|
|
"definitions.html#Race condition">race conditions</a> do not occur.</p>
|
|
|
|
<p>The dangers are spelled out by <a href=
|
|
"bibliography.html#Andrews-83">[Andrews-83]</a> (function names
|
|
updated, see historical note below):</p>
|
|
|
|
<blockquote>
|
|
<p>Although semaphores can be used to program almost any kind of
|
|
synchronization, <b>down()</b> and <b>up()</b> are rather
|
|
unstructured primitives, and so it is easy to err when using them.
|
|
Execution of each critical section must begin with a <b>down()</b>
|
|
and end with a <b>up()</b> (on the same semaphore). Omitting a <b>
|
|
down()</b> or <b>up()</b>, or accidentally coding a <b>down()</b>
|
|
on one semaphore and a <b>up()</b> on another can have disastrous
|
|
effects, since mutually exclusive execution would no longer be
|
|
ensured. Also, when using semaphores, a programmer can forget to
|
|
include in critical sections all statements that reference shared
|
|
objects. This, too, could destroy the mutual exclusion required
|
|
within critical sections. A second difficulty with using semaphores
|
|
is that both condition synchronization and mutual exclusion are
|
|
programmed using the same pair of primitives. This makes it
|
|
difficult to identify the purpose of a given <b>down()</b> or <b>
|
|
up()</b> operation without looking at the other operations on the
|
|
corresponding semaphore. Since mutual exclusion and condition
|
|
synchronization are distinct concepts, they should have distinct
|
|
notations.</p>
|
|
</blockquote>
|
|
|
|
<p><b>Historical note:</b> Dijkstra's original name for <b>
|
|
down()</b> was <b>P</b> (short for the Dutch "passeren",
|
|
"to pass"), and for <b>up()</b> was <b>V</b> (short for the
|
|
Dutch "vrygeven", "to release").</p>
|
|
|
|
<h2><a name="Header">Header</a></h2>
|
|
<pre>
|
|
#include <a href=
|
|
"../../../boost/thread/semaphore.hpp"><boost/thread/semaphore.hpp></a>
|
|
</pre>
|
|
|
|
<h2><a name="Synopsis">Synopsis</a></h2>
|
|
<pre>
|
|
namespace boost
|
|
{
|
|
class semaphore : private <a href=
|
|
"../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
|
|
// Class semaphore meets the <a href=
|
|
"overview.html#NonCopyable">NonCopyable</a> requirement.
|
|
{
|
|
public:
|
|
explicit semaphore(unsigned count=0, unsigned max=0);
|
|
~semaphore();
|
|
|
|
bool up(unsigned count=1, unsigned* prev=0);
|
|
void down();
|
|
bool down(const xtime& xt);
|
|
private:
|
|
unsigned m_count; <i>exposition only [ISO 17.3.2.3/2]
|
|
</i> unsigned m_max; <i>exposition only [ISO 17.3.2.3/2]</i>
|
|
};
|
|
}
|
|
</pre>
|
|
|
|
<h2><a name="Members">Members</a></h2>
|
|
<hr>
|
|
|
|
<h3>Constructor</h3>
|
|
<pre>
|
|
explicit semaphore(unsigned count=0, unsigned max=0);
|
|
</pre>
|
|
|
|
<p><b>Effects:</b> As if:</p>
|
|
|
|
<p><code> m_count = count;<br>
|
|
m_max = (max == 0 ?
|
|
std::numeric_limits<unsigned>::max() ? max );</code></p>
|
|
<hr>
|
|
|
|
<h3>Destructor</h3>
|
|
<pre>
|
|
~semaphore();
|
|
</pre>
|
|
|
|
<p><b>Effects:</b> Destroys <code>*this</code>.</p>
|
|
<hr>
|
|
|
|
<h3>up</h3>
|
|
<pre>
|
|
bool up(unsigned count=1, unsigned* prev=0);
|
|
</pre>
|
|
|
|
<p><b>Effects:</b> As if:</p>
|
|
|
|
<p><code> unsigned ct;<br>
|
|
bool ret;<br>
|
|
{ // as a single atomic operation:<br>
|
|
ct = m_count;<br>
|
|
if (m_count == m_max)
|
|
ret = false;<br>
|
|
else<br>
|
|
{<br>
|
|
|
|
ret = true;<br>
|
|
|
|
++m_count;<br>
|
|
}<br>
|
|
}<br>
|
|
if (prev) *prev = m_count;<br>
|
|
return ret;</code></p>
|
|
<hr>
|
|
|
|
<h3>down</h3>
|
|
<pre>
|
|
void down();
|
|
</pre>
|
|
|
|
<p><b>Effects:</b> If <code>m_count == 0</code>, places the current
|
|
thread in the <a href="definitions.html#State">blocked</a> state until
|
|
<code>m_count != 0</code>. Finally, <code>--m_count</code>.</p>
|
|
<hr>
|
|
<pre>
|
|
bool down(const <a href="xtime.html">xtime</a>& xt);
|
|
</pre>
|
|
|
|
<p><b>Effects:</b> If <code>m_count == 0</code>, places the current
|
|
thread in the <a href="definitions.html#State">blocked</a> state until
|
|
<code>m_count != 0</code> or <code>xt</code> is reached. Finally,
|
|
<code>--m_count</code>.</p>
|
|
|
|
<p><b>Returns:</b> If xt was reached, true, else false.</p>
|
|
<hr>
|
|
|
|
<h2><a name="Example">Example</a> Usage</h2>
|
|
<pre>
|
|
#include <a href=
|
|
"../../../boost/thread/semaphore.hpp"><boost/thread/semaphore.hpp></a>
|
|
#include <a href=
|
|
"../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
|
#include <iostream>
|
|
|
|
int global_data = 0;
|
|
boost::semaphore global_semaphore(1);
|
|
|
|
void change_global_data(void*)
|
|
{
|
|
global_semaphore.down();
|
|
++global_data;
|
|
std::cout << "global_data == " << global_data << std::endl;
|
|
global_semaphore.up();
|
|
}
|
|
|
|
int main(int, char*[])
|
|
{
|
|
const int num_threads = 4;
|
|
boost::thread_group thrds;
|
|
for (int i=0; i < num_threads; ++i)
|
|
thrds.create_thread(&change_global_data, 0);
|
|
|
|
thrds.join_all();
|
|
|
|
return 0;
|
|
}
|
|
</pre>
|
|
|
|
<p>The output is:</p>
|
|
<pre>
|
|
global_data == 1
|
|
global_data == 2
|
|
global_data == 3
|
|
global_data == 4
|
|
</pre>
|
|
<hr>
|
|
|
|
<p>Revised
|
|
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01
|
|
October, 2001
|
|
<!--webbot bot="Timestamp" endspan i-checksum="38291" --></p>
|
|
|
|
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">
|
|
William E. Kempf</a> 2001 all rights reserved.</i></p>
|
|
</body>
|
|
</html>
|
|
|