mirror of
https://github.com/boostorg/thread.git
synced 2026-01-23 18:12:12 +00:00
295 lines
12 KiB
HTML
295 lines
12 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
|
<link rel="stylesheet" type="text/css" href="../../../boost.css">
|
|
<title>Boost.Threads - Header <boost/thread/condition.hpp></title>
|
|
</head>
|
|
<body link="#0000ff" vlink="#800080">
|
|
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
|
"header">
|
|
<tr>
|
|
<td valign="top" width="300">
|
|
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
|
|
</td>
|
|
<td valign="top">
|
|
<h1 align="center">Boost.Threads</h1>
|
|
<h2 align="center">Header <<a href="../../../boost/thread/condition.hpp">boost/thread/condition.hpp</a>></h2>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<hr>
|
|
<h2>Contents</h2>
|
|
<dl class="page-index">
|
|
<dt><a href="#introduction">Introduction</a></dt>
|
|
<dt><a href="#classes">Classes</a></dt>
|
|
<dl class="page-index">
|
|
<dt><a href="#class-condition">Class <code>condition</code></a></dt>
|
|
<dl class="page-index">
|
|
<dt><a href="#class-condition-synopsis">Class <code>condition</code> synopsis</a></dt>
|
|
<dt><a href="#class-condition-ctors">Class <code>condition</code> constructors
|
|
and destructor</a></dt>
|
|
<dt><a href="#class-condition-modifiers">Class <code>condition</code> modifier
|
|
functions</a></dt>
|
|
</dl>
|
|
</dl>
|
|
<dt><a href="#examples">Example(s)</a></dt>
|
|
</dl>
|
|
<hr>
|
|
<h2><a name="introduction"></a>Introduction</h2>
|
|
<p>Include the header <<a href="../../../boost/thread/condition.hpp">boost/thread/condition.hpp</a>>
|
|
to define the class condition.</p>
|
|
<h2><a name="classes"></a>Classes</h2>
|
|
<h3><a name="class-condition"></a>Class <code>condition</code></h3>
|
|
<p>An object of class <code>condition</code> is a synchronization primitive used
|
|
to cause a thread to wait until a particular shared-data condition (or time)
|
|
is met. A <code>condition</code> object is always used in conjunction with a
|
|
mutex object (an object whose type is a model of <a href="mutex_concept.html">Mutex</a>
|
|
or one of its refinements). The mutex object must be locked prior to waiting
|
|
on the <code>condition</code>, which is verified by passing a lock object (an
|
|
object whose type is a model of <a href="lock_concept.html">Lock</a> or one
|
|
of its refinements) to the <code>condition</code> object's <code>wait</code>
|
|
functions. Upon blocking on the condition object, the thread unlocks the mutex
|
|
object. When the thread returns from a call to one of the condition object's
|
|
wait functions the mutex object is again locked. The tricky unlock/lock sequence
|
|
is performed automatically by the <code> condition</code> object's <code>wait</code>
|
|
functions.</p>
|
|
<p>The <code>condition</code> type is often used to implement the <i> Monitor
|
|
Object</i> and other important patterns (see <a href="bibliography.html#Schmidt-00">[Schmidt
|
|
00]</a> and <a href="bibliography.html#Hoare-74">[Hoare 74]</a>). Monitors are
|
|
one of the most important patterns for creating reliable multithreaded programs.</p>
|
|
<p>See <a href="definitions.html">Formal Definitions</a> for definitions of thread
|
|
states <a href="definitions.html#state"> blocked</a> and <a href="definitions.html#state">ready</a>.
|
|
Note that "waiting" is a synonym for blocked.</p>
|
|
<h4><a name="class-condition-synopsis"></a>Class <code>condition</code> synopsis</h4>
|
|
<pre>
|
|
namespace boost
|
|
{
|
|
class condition : private <a href="../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
|
|
// Class condition meets the <a href="overview.html#non-copyable">NonCopyable</a> requirement.
|
|
{
|
|
public:
|
|
condition();
|
|
~condition();
|
|
|
|
void notify_one();
|
|
void notify_all();
|
|
template <typename <a href="lock_concept.html#Lock-concept">Lock</a>>
|
|
void wait(<a href="lock_concept.html#Lock-concept">Lock</a>& lock);
|
|
template <typename <a href="lock_concept.html#Lock-concept">Lock</a>, typename <a href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a>>
|
|
void wait(<a href="lock_concept.html#Lock-concept">Lock</a>& lock, <a href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a> pred);
|
|
template <typename <a href="lock_concept.html#Lock-concept">Lock</a>>
|
|
bool timed_wait(<a href="lock_concept.html#Lock-concept">Lock</a>& lock, const xtime& xt);
|
|
template <typename <a href="lock_concept.html#Lock-concept">Lock</a>, typename <a href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a>>
|
|
bool timed_wait(<a href="lock_concept.html#Lock-concept">Lock</a>& lock, const xtime& XT, <a href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a> pred);
|
|
};
|
|
};
|
|
</pre>
|
|
<h4><a name="class-condition-ctors"></a>Class <code>condition</code> constructors
|
|
and destructor</h4>
|
|
<pre>
|
|
condition();
|
|
</pre>
|
|
<dl class="function-semantics">
|
|
<dt><b>Effects:</b> Constructs a <code>condition</code> object.</dt>
|
|
</dl>
|
|
<pre>
|
|
~condition();
|
|
</pre>
|
|
<dl class="function-semantics">
|
|
<dt><b>Effects:</b> Destroys <code>*this</code>.</dt>
|
|
</dl>
|
|
<h4><a name="class-condition-modifiers"></a>Class <code>condition</code> modifier
|
|
functions</h4>
|
|
<pre>
|
|
void notify_one();
|
|
</pre>
|
|
<dl class="function-semantics">
|
|
<dt><b>Effects:</b> If there is a thread waiting on <code>*this</code>, change
|
|
that thread's state to ready. Otherwise there is no effect.</dt>
|
|
<dt><b>Note:</b> If more than one thread is waiting on the condition, it is
|
|
unspecified which is made ready. After returning to a ready state the notified
|
|
thread must still acquire the mutex again (which occurs within the call to
|
|
one of the <code>condition</code> object's wait functions).</dt>
|
|
</dl>
|
|
<pre>
|
|
void notify_all();
|
|
</pre>
|
|
<dl class="function-semantics">
|
|
<dt><b>Effects:</b> Change the state of all threads waiting on <code> *this</code>
|
|
to ready. If there are no waiting threads, <code> notify_all()</code> has
|
|
no effect.</dt>
|
|
</dl>
|
|
<pre>
|
|
template <typename ScopedLock>
|
|
void wait(ScopedLock& lock);
|
|
</pre>
|
|
<dl class="function-semantics">
|
|
<dt><b>Requires:</b> <code>ScopedLock</code> meets the <a href="lock_concept.html#ScopedLock">ScopedLock</a>
|
|
requirements.</dt>
|
|
<dt><b>Effects:</b> Releases the lock on the <a href="mutex_concept.html">mutex
|
|
model</a> associated with <code>lock</code>, blocks the current thread of
|
|
execution until readied by a call to <code>this->notify_one()</code> or
|
|
<code> this->notify_all()</code>, and then reacquires the lock.</dt>
|
|
<dt><b>Throws:</b> <code><a href="exceptions.html#class-lock_error">lock_error</a></code>
|
|
if <code>!lock.locked()</code></dt>
|
|
<dt><b>Danger:</b> This version should always be used within a loop checking
|
|
that the state logically associated with the <code>condition</code> has become
|
|
true. Without the loop, race conditions can ensue due to possible "spurious
|
|
wake ups". The second version encapsulates this loop idiom internally
|
|
and is generally the preferred method.</dt>
|
|
</dl>
|
|
<pre>
|
|
Template<typename ScopedLock, typename Pr>
|
|
void wait(ScopedLock& lock, Pr pred);
|
|
</pre>
|
|
<dl class="function-semantics">
|
|
<dt><b>Requires:</b> <code>ScopedLock</code> meets the <a href="lock_concept.html#ScopedLock">ScopedLock</a>
|
|
requirements, return from <code>pred()</code> convertible to bool.</dt>
|
|
<dt><b>Effects:</b> As if: <code>while (!pred()) wait(lock)</code></dt>
|
|
<dt><b>Throws:</b> <code><a href="exceptions.html#class-lock_error">lock_error</a></code>
|
|
if <code>!lock.locked()</code></dt>
|
|
</dl>
|
|
<pre>
|
|
template <typename ScopedLock>
|
|
bool timed_wait(ScopedLock& lock, const <a href="xtime.html">xtime</a>& XT);
|
|
</pre>
|
|
<dl class="function-semantics">
|
|
<dt><b>Requires:</b> <code>ScopedLock</code> meets the <a href="lock_concept.html#ScopedLock">ScopedLock</a>
|
|
requirements.</dt>
|
|
<dt><b>Effects:</b> Releases the lock on the <a href="mutex_concept.html">mutex
|
|
model</a> associated with the <code> lock</code>, blocks the current thread
|
|
of execution until readied by a call to <code>this->notify_one()</code>
|
|
or <code> this->notify_all()</code>, or until <code>XT</code>, and then
|
|
reacquires the lock.</dt>
|
|
<dt><b>Returns:</b> <code>false</code> if <code>XT</code> is reached, otherwise
|
|
<code>true</code>.</dt>
|
|
<dt><b>Throws:</b> <code><a href="exceptions.html#class-lock_error">lock_error</a></code>
|
|
if <code>!lock.locked()</code></dt>
|
|
<dt><b>Danger:</b> This version should always be used within a loop checking
|
|
that the state logically associated with the <code>condition</code> has become
|
|
true. Without the loop, race conditions can ensue due to "spurious wake
|
|
ups". The second version encapsulates this loop idiom internally and
|
|
is generally the preferred method.</dt>
|
|
</dl>
|
|
<pre>
|
|
Template<typename ScopedLock, typename Pr>
|
|
bool timed_wait(ScopedLock& lock, const <a href="xtime.html">xtime</a>& XT, Pr pred);
|
|
</pre>
|
|
<dl class="function-semantics">
|
|
<dt><b>Requires:</b> <code>ScopedLock</code> meets the <a href="lock_concept.html#ScopedLock">ScopedLock</a>
|
|
requirements, return from <code>pred()</code> convertible to bool.</dt>
|
|
<dt><b>Effects:</b> As if:<br>
|
|
<pre>
|
|
while (!pred())
|
|
{
|
|
if (!timed_wait(lock, XT))
|
|
return false;
|
|
}
|
|
return true;
|
|
</pre>
|
|
</dt>
|
|
<dt><b>Returns:</b> <code>false</code> if <code>XT</code> is reached, otherwise
|
|
<code>true</code>.</dt>
|
|
<dt><b>Throws:</b> <code><a href="exceptions.html#class-lock_error">lock_error</a></code>
|
|
if <code>!lock.locked()</code></dt>
|
|
</dl>
|
|
<h2><a name="examples"></a>Example(s)</h2>
|
|
<pre>
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <a href="../../../boost/utility.hpp"><boost/utility.hpp></a>
|
|
#include <a href="../../../boost/thread/condition.hpp"><boost/thread/condition.hpp></a>
|
|
#include <a href="../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
|
|
|
class bounded_buffer : private boost::noncopyable
|
|
{
|
|
public:
|
|
typedef boost::mutex::scoped_lock lock;
|
|
|
|
bounded_buffer(int n) : begin(0), end(0), buffered(0), circular_buf(n) { }
|
|
|
|
void send (int m) {
|
|
lock lk(monitor);
|
|
while (buffered == circular_buf.size())
|
|
buffer_not_full.wait(lk);
|
|
circular_buf[end] = m;
|
|
end = (end+1) % circular_buf.size();
|
|
++buffered;
|
|
buffer_not_empty.notify_one();
|
|
}
|
|
int receive() {
|
|
lock lk(monitor);
|
|
while (buffered == 0)
|
|
buffer_not_empty.wait(lk);
|
|
int i = circular_buf[begin];
|
|
begin = (begin+1) % circular_buf.size();
|
|
--buffered;
|
|
buffer_not_full.notify_one();
|
|
return i;
|
|
}
|
|
|
|
private:
|
|
int begin, end, buffered;
|
|
std::vector<int> circular_buf;
|
|
boost::condition buffer_not_full, buffer_not_empty;
|
|
boost::mutex monitor;
|
|
};
|
|
|
|
bounded_buffer buf(2);
|
|
|
|
void sender() {
|
|
int n = 0;
|
|
while (n < 100) {
|
|
buf.send(n);
|
|
std::cout << "sent: " << n << std::endl;
|
|
++n;
|
|
}
|
|
buf.send(-1);
|
|
}
|
|
|
|
void receiver() {
|
|
int n;
|
|
do {
|
|
n = buf.receive();
|
|
std::cout << "received: " << n << std::endl;
|
|
} while (n != -1); // -1 indicates end of buffer
|
|
}
|
|
|
|
int main(int, char*[])
|
|
{
|
|
boost::thread thrd1(&sender);
|
|
boost::thread thrd2(&receiver);
|
|
thrd1.join();
|
|
thrd2.join();
|
|
return 0;
|
|
}
|
|
</pre>
|
|
<p>Typical output (dependent on scheduling policies) is:</p>
|
|
<pre>
|
|
sent: 0
|
|
sent: 1
|
|
received: 0
|
|
received: 1
|
|
sent: 2
|
|
sent: 3
|
|
received: 2
|
|
received: 3
|
|
sent: 4
|
|
received: 4
|
|
</pre>
|
|
<p>Revised
|
|
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
|
05 November, 2001
|
|
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
|
</p>
|
|
<p><i>© Copyright <a href="mailto:wekempf@cox.net">William E. Kempf</a> 2001-2002.
|
|
All Rights Reserved.</i></p>
|
|
<p>Permission to use, copy, modify, distribute and sell this software and its
|
|
documentation for any purpose is hereby granted without fee, provided that the
|
|
above copyright notice appear in all copies and that both that copyright notice
|
|
and this permission notice appear in supporting documentation. William E. Kempf
|
|
makes no representations about the suitability of this software for any purpose.
|
|
It is provided "as is" without express or implied warranty.</p>
|
|
</body>
|
|
</html>
|