mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 09:42:16 +00:00
Compare commits
34 Commits
svn-branch
...
boost-1.33
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
283ce1df6c | ||
|
|
e552e010fd | ||
|
|
c52357636b | ||
|
|
2cb4dbb07f | ||
|
|
9ca3c5b13f | ||
|
|
7445f79dd4 | ||
|
|
aa240e61d9 | ||
|
|
2954e932ce | ||
|
|
5be79cc858 | ||
|
|
4a9d97d22d | ||
|
|
f4f3433854 | ||
|
|
26bffa3740 | ||
|
|
69e52a9882 | ||
|
|
cc8de48849 | ||
|
|
9d7c119f94 | ||
|
|
6ba9fd1b60 | ||
|
|
fb6250eb94 | ||
|
|
bc73368c96 | ||
|
|
3068f0c62c | ||
|
|
8e00803c83 | ||
|
|
087b69b629 | ||
|
|
3b237267fb | ||
|
|
b9dbb1ed45 | ||
|
|
41d3b29ec0 | ||
|
|
05ceb8b1e2 | ||
|
|
80d3925b8d | ||
|
|
2cd6cbeacc | ||
|
|
6382846f6c | ||
|
|
349d0fd74b | ||
|
|
9c88855bf4 | ||
|
|
f0e6cdfcb5 | ||
|
|
af9864a1b5 | ||
|
|
8ac145e667 | ||
|
|
39f7afc7d0 |
@@ -30,7 +30,6 @@ import ./threads ;
|
||||
mutex
|
||||
once
|
||||
recursive_mutex
|
||||
read_write_mutex
|
||||
thread
|
||||
tss_hooks
|
||||
tss_dll
|
||||
@@ -46,7 +45,6 @@ import ./threads ;
|
||||
: ## requirements ##
|
||||
<sysinclude>$(BOOST_ROOT) #:should be unnecessary (because already included in thread_base)
|
||||
<define>BOOST_THREAD_BUILD_LIB=1
|
||||
<runtime-link>static
|
||||
# the common names rule ensures that the library will
|
||||
# be named according to the rules used by the install
|
||||
# and auto-link features:
|
||||
@@ -102,7 +100,8 @@ import ./threads ;
|
||||
<template>boost_thread_lib_base
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name_ptw32)
|
||||
$(pthreads-win32)
|
||||
$(boost_thread_lib_settings_ptw32)
|
||||
: ## default build ##
|
||||
;
|
||||
|
||||
dll $(boost_thread_lib_name_ptw32)
|
||||
@@ -110,7 +109,8 @@ import ./threads ;
|
||||
<template>boost_thread_dll_base
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name_ptw32)
|
||||
$(pthreads-win32)
|
||||
$(boost_thread_lib_settings_ptw32)
|
||||
: ## default build ##
|
||||
;
|
||||
|
||||
stage bin-stage
|
||||
|
||||
@@ -12,14 +12,8 @@ last-revision="$Date$">
|
||||
<para>Mac OS Carbon implementation written by Mac Murrett.</para>
|
||||
<para>Dave Moore provided initial submissions and further comments on the
|
||||
<code>barrier</code>
|
||||
,
|
||||
<code>thread_pool</code>
|
||||
,
|
||||
<code>read_write_mutex</code>
|
||||
,
|
||||
<code>read_write_try_mutex</code>
|
||||
and
|
||||
<code>read_write_timed_mutex</code>
|
||||
<code>thread_pool</code>
|
||||
classes.</para>
|
||||
<para>Important contributions were also made by Jeremy Siek (lots of input
|
||||
on the design and on the implementation), Alexander Terekhov (lots of input
|
||||
|
||||
@@ -54,7 +54,7 @@ last-revision="$Date$">
|
||||
<title>ACM Computing Surveys</title>
|
||||
<volumenum>Vol. 5</volumenum>
|
||||
<issuenum>No. 4</issuenum>
|
||||
<date>December, 1983</date>
|
||||
<date>December, 1973</date>
|
||||
</biblioset>
|
||||
<biblioset relation="article">
|
||||
<author>0-201-63392-2
|
||||
|
||||
1561
doc/concepts.xml
1561
doc/concepts.xml
File diff suppressed because it is too large
Load Diff
@@ -1,458 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<header name="boost/thread/read_write_mutex.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
<namespace name="read_write_scheduling_policy">
|
||||
<enum name="read_write_scheduling_policy">
|
||||
<enumvalue name="writer_priority" />
|
||||
<enumvalue name="reader_priority" />
|
||||
<enumvalue name="alternating_many_reads" />
|
||||
<enumvalue name="alternating_single_read" />
|
||||
|
||||
<purpose>
|
||||
<para>Specifies the
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
to use when a set of threads try to obtain different types of
|
||||
locks simultaneously.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The only clock type supported by &Boost.Threads; is
|
||||
<code>TIME_UTC</code>. The epoch for <code>TIME_UTC</code>
|
||||
is 1970-01-01 00:00:00.</para>
|
||||
</description>
|
||||
</enum>
|
||||
</namespace>
|
||||
|
||||
<class name="read_write_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>read_write_mutex</classname> class is a model of the
|
||||
<link linkend="threads.concepts.ReadWriteMutex">ReadWriteMutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>read_write_mutex</classname> class is a model of the
|
||||
<link linkend="threads.concepts.ReadWriteMutex">ReadWriteMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
locking mechanics.</para>
|
||||
|
||||
<para>For classes that model related mutex concepts, see
|
||||
<classname>try_read_write_mutex</classname> and <classname>timed_read_write_mutex</classname>.</para>
|
||||
|
||||
<para>The <classname>read_write_mutex</classname> class supplies the following typedefs,
|
||||
which <link linkend="threads.concepts.read-write-lock-models">model</link>
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
<tgroup cols="2" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Lock Name</entry>
|
||||
<entry>Lock Concept</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_read_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_read_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
|
||||
<para>The <classname>read_write_mutex</classname> class uses an
|
||||
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
locking strategy, so attempts to recursively lock a <classname>read_write_mutex</classname>
|
||||
object or attempts to unlock one by threads that don't own a lock on it result in
|
||||
<emphasis role="bold">undefined behavior</emphasis>.
|
||||
This strategy allows implementations to be as efficient as possible
|
||||
on any given platform. It is, however, recommended that
|
||||
implementations include debugging support to detect misuse when
|
||||
<code>NDEBUG</code> is not defined.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="threads.concepts.read-write-mutex-models">read/write mutex models</link>
|
||||
in &Boost.Threads;, <classname>read_write_mutex</classname> has two types of
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies">scheduling policies</link>, an
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
between threads trying to obtain different types of locks and an
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link>
|
||||
between threads trying to obtain the same type of lock.
|
||||
The <classname>read_write_mutex</classname> class allows the
|
||||
programmer to choose what
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
will be used; however, like all read/write mutex models,
|
||||
<classname>read_write_mutex</classname> leaves the
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
|
||||
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>.
|
||||
</para>
|
||||
|
||||
<note>Self-deadlock is virtually guaranteed if a thread tries to
|
||||
lock the same <classname>read_write_mutex</classname> multiple times
|
||||
unless all locks are read-locks (but see below)</note>
|
||||
</description>
|
||||
|
||||
<inherit access="private">
|
||||
<type><classname>boost::noncopyable</classname></type>
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<inherit access="private">
|
||||
<type><classname>boost::noncopyable</classname></type>
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<typedef name="scoped_read_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_read_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<constructor>
|
||||
<parameter name="count">
|
||||
<paramtype>boost::read_write_scheduling_policy</paramtype>
|
||||
</parameter>
|
||||
|
||||
<effects>Constructs a <classname>read_write_mutex</classname> object.
|
||||
</effects>
|
||||
|
||||
<postconditions><code>*this</code> is in an unlocked state.
|
||||
</postconditions>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<effects>Destroys a <classname>read_write_mutex</classname> object.</effects>
|
||||
|
||||
<requires><code>*this</code> is in an unlocked state.</requires>
|
||||
|
||||
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
|
||||
locked mutex is a serious programming error resulting in undefined
|
||||
behavior such as a program crash.</notes>
|
||||
</destructor>
|
||||
</class>
|
||||
|
||||
<class name="try_read_write_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>try_read_write_mutex</classname> class is a model of the
|
||||
<link linkend="threads.concepts.TryReadWriteMutex">TryReadWriteMutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>try_read_write_mutex</classname> class is a model of the
|
||||
<link linkend="threads.concepts.TryReadWriteMutex">TryReadWriteMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
locking mechanics.</para>
|
||||
|
||||
<para>For classes that model related mutex concepts, see
|
||||
<classname>read_write_mutex</classname> and <classname>timed_read_write_mutex</classname>.</para>
|
||||
|
||||
<para>The <classname>try_read_write_mutex</classname> class supplies the following typedefs,
|
||||
which <link linkend="threads.concepts.read-write-lock-models">model</link>
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
<tgroup cols="2" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Lock Name</entry>
|
||||
<entry>Lock Concept</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_read_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_read_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_read_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_read_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
|
||||
<para>The <classname>try_read_write_mutex</classname> class uses an
|
||||
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
locking strategy, so attempts to recursively lock a <classname>try_read_write_mutex</classname>
|
||||
object or attempts to unlock one by threads that don't own a lock on it result in
|
||||
<emphasis role="bold">undefined behavior</emphasis>.
|
||||
This strategy allows implementations to be as efficient as possible
|
||||
on any given platform. It is, however, recommended that
|
||||
implementations include debugging support to detect misuse when
|
||||
<code>NDEBUG</code> is not defined.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="threads.concepts.read-write-mutex-models">read/write mutex models</link>
|
||||
in &Boost.Threads;, <classname>try_read_write_mutex</classname> has two types of
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies">scheduling policies</link>, an
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
between threads trying to obtain different types of locks and an
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link>
|
||||
between threads trying to obtain the same type of lock.
|
||||
The <classname>try_read_write_mutex</classname> class allows the
|
||||
programmer to choose what
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
will be used; however, like all read/write mutex models,
|
||||
<classname>try_read_write_mutex</classname> leaves the
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
|
||||
<link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
</para>
|
||||
|
||||
<note>Self-deadlock is virtually guaranteed if a thread tries to
|
||||
lock the same <classname>try_read_write_mutex</classname> multiple times
|
||||
unless all locks are read-locks (but see below)</note>
|
||||
</description>
|
||||
|
||||
<inherit access="private">
|
||||
<type><classname>boost::noncopyable</classname></type>
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<typedef name="scoped_read_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_read_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_read_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_read_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<constructor>
|
||||
<parameter name="count">
|
||||
<paramtype>boost::read_write_scheduling_policy</paramtype>
|
||||
</parameter>
|
||||
|
||||
<effects>Constructs a <classname>try_read_write_mutex</classname> object.
|
||||
</effects>
|
||||
|
||||
<postconditions><code>*this</code> is in an unlocked state.
|
||||
</postconditions>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<effects>Destroys a <classname>try_read_write_mutex</classname> object.</effects>
|
||||
|
||||
<requires><code>*this</code> is in an unlocked state.</requires>
|
||||
|
||||
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
|
||||
locked mutex is a serious programming error resulting in undefined
|
||||
behavior such as a program crash.</notes>
|
||||
</destructor>
|
||||
</class>
|
||||
|
||||
<class name="timed_read_write_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>timed_read_write_mutex</classname> class is a model of the
|
||||
<link linkend="threads.concepts.TimedReadWriteMutex">TimedReadWriteMutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>timed_read_write_mutex</classname> class is a model of the
|
||||
<link linkend="threads.concepts.TimedReadWriteMutex">TimedReadWriteMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
locking mechanics.</para>
|
||||
|
||||
<para>For classes that model related mutex concepts, see
|
||||
<classname>read_write_mutex</classname> and <classname>try_read_write_mutex</classname>.</para>
|
||||
|
||||
<para>The <classname>timed_read_write_mutex</classname> class supplies the following typedefs,
|
||||
which <link linkend="threads.concepts.read-write-lock-models">model</link>
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
<tgroup cols="2" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Lock Name</entry>
|
||||
<entry>Lock Concept</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_read_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_read_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_read_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTimedReadWriteLock">ScopedTimedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_read_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_read_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_read_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
|
||||
<para>The <classname>timed_read_write_mutex</classname> class uses an
|
||||
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
locking strategy, so attempts to recursively lock a <classname>timed_read_write_mutex</classname>
|
||||
object or attempts to unlock one by threads that don't own a lock on it result in
|
||||
<emphasis role="bold">undefined behavior</emphasis>.
|
||||
This strategy allows implementations to be as efficient as possible
|
||||
on any given platform. It is, however, recommended that
|
||||
implementations include debugging support to detect misuse when
|
||||
<code>NDEBUG</code> is not defined.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="threads.concepts.read-write-mutex-models">read/write mutex models</link>
|
||||
in &Boost.Threads;, <classname>timed_read_write_mutex</classname> has two types of
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies">scheduling policies</link>, an
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
between threads trying to obtain different types of locks and an
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link>
|
||||
between threads trying to obtain the same type of lock.
|
||||
The <classname>timed_read_write_mutex</classname> class allows the
|
||||
programmer to choose what
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
will be used; however, like all read/write mutex models,
|
||||
<classname>timed_read_write_mutex</classname> leaves the
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
|
||||
<link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
</para>
|
||||
|
||||
<note>Self-deadlock is virtually guaranteed if a thread tries to
|
||||
lock the same <classname>timed_read_write_mutex</classname> multiple times
|
||||
unless all locks are read-locks (but see below)</note>
|
||||
</description>
|
||||
|
||||
<typedef name="scoped_read_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_read_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_timed_read_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_read_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_read_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_timed_read_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_timed_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<constructor>
|
||||
<parameter name="count">
|
||||
<paramtype>boost::read_write_scheduling_policy</paramtype>
|
||||
</parameter>
|
||||
|
||||
<effects>Constructs a <classname>timed_read_write_mutex</classname> object.
|
||||
</effects>
|
||||
|
||||
<postconditions><code>*this</code> is in an unlocked state.
|
||||
</postconditions>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<effects>Destroys a <classname>timed_read_write_mutex</classname> object.</effects>
|
||||
|
||||
<requires><code>*this</code> is in an unlocked state.</requires>
|
||||
|
||||
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
|
||||
locked mutex is a serious programming error resulting in undefined
|
||||
behavior such as a program crash.</notes>
|
||||
</destructor>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
@@ -13,7 +13,6 @@
|
||||
<xi:include href="mutex-ref.xml"/>
|
||||
<xi:include href="once-ref.xml"/>
|
||||
<xi:include href="recursive_mutex-ref.xml"/>
|
||||
<xi:include href="read_write_mutex-ref.xml"/>
|
||||
<xi:include href="thread-ref.xml"/>
|
||||
<xi:include href="tss-ref.xml"/>
|
||||
<xi:include href="xtime-ref.xml"/>
|
||||
|
||||
@@ -32,7 +32,7 @@ xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<librarycategory name="category:concurrent" />
|
||||
<title>Boost.Threads</title>
|
||||
</libraryinfo>
|
||||
<title>&Boost.Threads;</title>
|
||||
<title>Boost.Threads</title>
|
||||
<xi:include href="overview.xml"/>
|
||||
<xi:include href="design.xml"/>
|
||||
<xi:include href="concepts.xml"/>
|
||||
|
||||
@@ -17,54 +17,50 @@
|
||||
// insist on threading support being available:
|
||||
#include <boost/config/requires_threads.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
# if defined(BOOST_THREAD_BUILD_DLL) //Build dll
|
||||
# define BOOST_THREAD_DECL __declspec(dllexport)
|
||||
# elif defined(BOOST_THREAD_BUILD_LIB) //Build lib
|
||||
# define BOOST_THREAD_DECL
|
||||
# elif defined(BOOST_THREAD_USE_DLL) //Use dll
|
||||
# define BOOST_THREAD_DECL __declspec(dllimport)
|
||||
# define BOOST_DYN_LINK
|
||||
# elif defined(BOOST_THREAD_USE_LIB) //Use lib
|
||||
# define BOOST_THREAD_DECL
|
||||
# else //Use default
|
||||
#if defined(BOOST_THREAD_BUILD_DLL) //Build dll
|
||||
#elif defined(BOOST_THREAD_BUILD_LIB) //Build lib
|
||||
#elif defined(BOOST_THREAD_USE_DLL) //Use dll
|
||||
#elif defined(BOOST_THREAD_USE_LIB) //Use lib
|
||||
#else //Use default
|
||||
# if defined(BOOST_HAS_WINTHREADS)
|
||||
# if defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)
|
||||
//For VC++, choose according to threading library setting
|
||||
# if defined(_DLL)
|
||||
//Threading library is dll: use Boost.Threads dll
|
||||
# define BOOST_THREAD_USE_DLL
|
||||
# define BOOST_THREAD_DECL __declspec(dllimport)
|
||||
# define BOOST_DYN_LINK
|
||||
# else
|
||||
//Threading library is lib: used Boost.Threads lib
|
||||
# define BOOST_THREAD_USE_LIB
|
||||
# define BOOST_THREAD_DECL
|
||||
# endif
|
||||
//For compilers supporting auto-tss cleanup
|
||||
//with Boost.Threads lib, use Boost.Threads lib
|
||||
# define BOOST_THREAD_USE_LIB
|
||||
# else
|
||||
//For compilers not yet supporting auto-tss cleanup
|
||||
//with Boost.Threads lib, use Boost.Threads dll
|
||||
# define BOOST_THREAD_USE_DLL
|
||||
# define BOOST_THREAD_DECL __declspec(dllimport)
|
||||
# define BOOST_DYN_LINK
|
||||
# endif
|
||||
# else
|
||||
# define BOOST_THREAD_USE_LIB
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_DECLSPEC)
|
||||
# if defined(BOOST_THREAD_BUILD_DLL) //Build dll
|
||||
# define BOOST_THREAD_DECL __declspec(dllexport)
|
||||
# elif defined(BOOST_THREAD_USE_DLL) //Use dll
|
||||
# define BOOST_THREAD_DECL __declspec(dllimport)
|
||||
# else
|
||||
# define BOOST_THREAD_DECL
|
||||
# endif
|
||||
#else
|
||||
# define BOOST_THREAD_DECL
|
||||
# if defined(BOOST_THREAD_USE_LIB) //Use dll
|
||||
# define BOOST_THREAD_USE_DLL
|
||||
# define BOOST_DYN_LINK
|
||||
# elif defined(BOOST_THREAD_USE_DLL) //Use lib
|
||||
# define BOOST_THREAD_USE_LIB
|
||||
# else //Use default
|
||||
# define BOOST_THREAD_USE_LIB
|
||||
# endif
|
||||
#endif // BOOST_HAS_WINTHREADS
|
||||
#endif // BOOST_HAS_DECLSPEC
|
||||
|
||||
//
|
||||
// Automatically link to the correct build variant where possible.
|
||||
//
|
||||
#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_THREAD_NO_LIB) && !defined(BOOST_THREAD_BUILD_DLL) && !defined(BOOST_THREAD_BUILD_LIB)
|
||||
//
|
||||
// Tell the autolink to link dynamically, this will get undef'ed by auto_link.hpp
|
||||
// once it's done with it:
|
||||
//
|
||||
#if defined(BOOST_THREAD_USE_DLL)
|
||||
# define BOOST_DYN_LINK
|
||||
#endif
|
||||
//
|
||||
// Set the name of our library, this will get undef'ed by auto_link.hpp
|
||||
// once it's done with it:
|
||||
//
|
||||
@@ -82,3 +78,9 @@
|
||||
#endif // auto-linking disabled
|
||||
|
||||
#endif // BOOST_THREAD_CONFIG_WEK1032003_HPP
|
||||
|
||||
// Change Log:
|
||||
// 22 Jan 05 Roland Schwarz (speedsnail)
|
||||
// Usage of BOOST_HAS_DECLSPEC macro.
|
||||
// Default again is static lib usage.
|
||||
// BOOST_DYN_LINK only defined when autolink included.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,273 +0,0 @@
|
||||
// Copyright (C) 2002-2003
|
||||
// David Moore, William E. Kempf
|
||||
//
|
||||
// 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. David Moore makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
// A Boost::threads implementation of a synchronization
|
||||
// primitive which can allow multiple readers or a single
|
||||
// writer to have access to a shared resource.
|
||||
|
||||
#ifndef BOOST_READ_WRITE_MUTEX_JDM030602_HPP
|
||||
#define BOOST_READ_WRITE_MUTEX_JDM030602_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/detail/lock.hpp>
|
||||
#include <boost/thread/detail/read_write_lock.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace read_write_scheduling_policy {
|
||||
enum read_write_scheduling_policy_enum
|
||||
{
|
||||
writer_priority, //Prefer writers; can starve readers
|
||||
reader_priority, //Prefer readers; can starve writers
|
||||
alternating_many_reads, //Alternate readers and writers; before a writer, release all queued readers
|
||||
alternating_single_read //Alternate readers and writers; before a writer, release only on queued reader
|
||||
};
|
||||
} // namespace read_write_scheduling_policy
|
||||
|
||||
namespace detail {
|
||||
|
||||
namespace thread {
|
||||
|
||||
// Shared implementation construct for explicit Scheduling Policies
|
||||
// This implementation is susceptible to self-deadlock, though....
|
||||
template<typename Mutex>
|
||||
struct read_write_mutex_impl
|
||||
{
|
||||
typedef Mutex mutex_type;
|
||||
typedef detail::thread::scoped_lock<Mutex> scoped_lock;
|
||||
typedef detail::thread::scoped_try_lock<Mutex> scoped_try_lock;
|
||||
typedef detail::thread::scoped_timed_lock<Mutex> scoped_timed_lock;
|
||||
|
||||
read_write_mutex_impl(read_write_scheduling_policy::read_write_scheduling_policy_enum sp)
|
||||
: m_num_waiting_writers(0),
|
||||
m_num_waiting_readers(0),
|
||||
m_num_readers_to_wake(0),
|
||||
m_state_waiting_promotion(false),
|
||||
m_state(0),
|
||||
m_sp(sp),
|
||||
m_readers_next(true) { }
|
||||
|
||||
Mutex m_prot;
|
||||
boost::condition m_waiting_writers;
|
||||
boost::condition m_waiting_readers;
|
||||
int m_num_waiting_writers;
|
||||
int m_num_waiting_readers;
|
||||
int m_num_readers_to_wake;
|
||||
boost::condition m_waiting_promotion;
|
||||
bool m_state_waiting_promotion;
|
||||
int m_state; // -1 = excl locked
|
||||
// 0 = unlocked
|
||||
// 1-> INT_MAX - shared locked
|
||||
const read_write_scheduling_policy::read_write_scheduling_policy_enum m_sp;
|
||||
bool m_readers_next;
|
||||
|
||||
void do_read_lock();
|
||||
void do_write_lock();
|
||||
void do_write_unlock();
|
||||
void do_read_unlock();
|
||||
bool do_try_write_lock();
|
||||
bool do_try_read_lock();
|
||||
bool do_timed_write_lock(const xtime &xt);
|
||||
bool do_timed_read_lock(const xtime &xt);
|
||||
|
||||
void do_demote_to_read_lock();
|
||||
bool do_try_demote_to_read_lock();
|
||||
bool do_timed_demote_to_read_lock(const xtime &xt);
|
||||
|
||||
void do_promote_to_write_lock();
|
||||
bool do_try_promote_to_write_lock();
|
||||
bool do_timed_promote_to_write_lock(const xtime &xt);
|
||||
|
||||
bool locked();
|
||||
read_write_lock_state::read_write_lock_state_enum state();
|
||||
|
||||
private:
|
||||
|
||||
void do_unlock_scheduling_impl();
|
||||
void do_timeout_scheduling_impl();
|
||||
void do_demote_scheduling_impl();
|
||||
void do_scheduling_impl();
|
||||
|
||||
bool do_demote_to_read_lock_impl();
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace thread
|
||||
|
||||
class BOOST_THREAD_DECL read_write_mutex : private noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
read_write_mutex(read_write_scheduling_policy::read_write_scheduling_policy_enum sp) : m_impl(sp) { }
|
||||
~read_write_mutex() { }
|
||||
|
||||
read_write_scheduling_policy::read_write_scheduling_policy_enum policy() const { return m_impl.m_sp; }
|
||||
|
||||
friend class detail::thread::read_write_lock_ops<read_write_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_read_write_lock<
|
||||
read_write_mutex> scoped_read_write_lock;
|
||||
|
||||
typedef detail::thread::scoped_read_lock<
|
||||
read_write_mutex> scoped_read_lock;
|
||||
|
||||
typedef detail::thread::scoped_write_lock<
|
||||
read_write_mutex> scoped_write_lock;
|
||||
|
||||
private:
|
||||
|
||||
// Operations that will eventually be done only
|
||||
// via lock types
|
||||
void do_write_lock();
|
||||
void do_read_lock();
|
||||
void do_write_unlock();
|
||||
void do_read_unlock();
|
||||
|
||||
void do_demote_to_read_lock();
|
||||
|
||||
void do_promote_to_write_lock();
|
||||
|
||||
bool locked();
|
||||
read_write_lock_state::read_write_lock_state_enum state();
|
||||
|
||||
detail::thread::read_write_mutex_impl<mutex> m_impl;
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL try_read_write_mutex : private noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
try_read_write_mutex(read_write_scheduling_policy::read_write_scheduling_policy_enum sp) : m_impl(sp) { }
|
||||
~try_read_write_mutex() { }
|
||||
|
||||
read_write_scheduling_policy::read_write_scheduling_policy_enum policy() const { return m_impl.m_sp; }
|
||||
|
||||
friend class detail::thread::read_write_lock_ops<try_read_write_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_read_write_lock<
|
||||
try_read_write_mutex> scoped_read_write_lock;
|
||||
typedef detail::thread::scoped_try_read_write_lock<
|
||||
try_read_write_mutex> scoped_try_read_write_lock;
|
||||
|
||||
typedef detail::thread::scoped_read_lock<
|
||||
try_read_write_mutex> scoped_read_lock;
|
||||
typedef detail::thread::scoped_try_read_lock<
|
||||
try_read_write_mutex> scoped_try_read_lock;
|
||||
|
||||
typedef detail::thread::scoped_write_lock<
|
||||
try_read_write_mutex> scoped_write_lock;
|
||||
typedef detail::thread::scoped_try_write_lock<
|
||||
try_read_write_mutex> scoped_try_write_lock;
|
||||
|
||||
private:
|
||||
|
||||
// Operations that will eventually be done only
|
||||
// via lock types
|
||||
void do_write_lock();
|
||||
void do_read_lock();
|
||||
void do_write_unlock();
|
||||
void do_read_unlock();
|
||||
bool do_try_write_lock();
|
||||
bool do_try_read_lock();
|
||||
|
||||
|
||||
void do_demote_to_read_lock();
|
||||
bool do_try_demote_to_read_lock();
|
||||
|
||||
void do_promote_to_write_lock();
|
||||
bool do_try_promote_to_write_lock();
|
||||
|
||||
bool locked();
|
||||
read_write_lock_state::read_write_lock_state_enum state();
|
||||
|
||||
detail::thread::read_write_mutex_impl<try_mutex> m_impl;
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL timed_read_write_mutex : private noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
timed_read_write_mutex(read_write_scheduling_policy::read_write_scheduling_policy_enum sp) : m_impl(sp) { }
|
||||
~timed_read_write_mutex() { }
|
||||
|
||||
read_write_scheduling_policy::read_write_scheduling_policy_enum policy() const { return m_impl.m_sp; }
|
||||
|
||||
friend class detail::thread::read_write_lock_ops<timed_read_write_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_read_write_lock<
|
||||
timed_read_write_mutex> scoped_read_write_lock;
|
||||
typedef detail::thread::scoped_try_read_write_lock<
|
||||
timed_read_write_mutex> scoped_try_read_write_lock;
|
||||
typedef detail::thread::scoped_timed_read_write_lock<
|
||||
timed_read_write_mutex> scoped_timed_read_write_lock;
|
||||
|
||||
typedef detail::thread::scoped_read_lock<
|
||||
timed_read_write_mutex> scoped_read_lock;
|
||||
typedef detail::thread::scoped_try_read_lock<
|
||||
timed_read_write_mutex> scoped_try_read_lock;
|
||||
typedef detail::thread::scoped_timed_read_lock<
|
||||
timed_read_write_mutex> scoped_timed_read_lock;
|
||||
|
||||
typedef detail::thread::scoped_write_lock<
|
||||
timed_read_write_mutex> scoped_write_lock;
|
||||
typedef detail::thread::scoped_try_write_lock<
|
||||
timed_read_write_mutex> scoped_try_write_lock;
|
||||
typedef detail::thread::scoped_timed_write_lock<
|
||||
timed_read_write_mutex> scoped_timed_write_lock;
|
||||
|
||||
private:
|
||||
|
||||
// Operations that will eventually be done only
|
||||
// via lock types
|
||||
void do_write_lock();
|
||||
void do_read_lock();
|
||||
void do_write_unlock();
|
||||
void do_read_unlock();
|
||||
bool do_try_write_lock();
|
||||
bool do_try_read_lock();
|
||||
bool do_timed_write_lock(const xtime &xt);
|
||||
bool do_timed_read_lock(const xtime &xt);
|
||||
|
||||
void do_demote_to_read_lock();
|
||||
bool do_try_demote_to_read_lock();
|
||||
bool do_timed_demote_to_read_lock(const xtime &xt);
|
||||
|
||||
void do_promote_to_write_lock();
|
||||
bool do_try_promote_to_write_lock();
|
||||
bool do_timed_promote_to_write_lock(const xtime &xt);
|
||||
|
||||
bool locked();
|
||||
read_write_lock_state::read_write_lock_state_enum state();
|
||||
|
||||
detail::thread::read_write_mutex_impl<timed_mutex> m_impl;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
// Change Log:
|
||||
// 10 Mar 02
|
||||
// Original version.
|
||||
// 4 May 04 GlassfordM
|
||||
// Implement lock promotion and demotion.
|
||||
// Add locked() and state() member functions for debugging
|
||||
// (should these be made public?).
|
||||
// Rename to improve consistency and eliminate abbreviations:
|
||||
// Use "read" and "write" instead of "shared" and "exclusive".
|
||||
// Change "rd" to "read", "wr" to "write", "rw" to "read_write".
|
||||
// Add mutex_type typdef.
|
||||
@@ -70,6 +70,7 @@ public:
|
||||
void add_thread(thread* thrd);
|
||||
void remove_thread(thread* thrd);
|
||||
void join_all();
|
||||
int size();
|
||||
|
||||
private:
|
||||
std::list<thread*> m_threads;
|
||||
|
||||
@@ -11,11 +11,17 @@
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#include <boost/thread/once.hpp>
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
# if BOOST_WORKAROUND(__BORLANDC__,<= 0x551)
|
||||
using std::size_t;
|
||||
# endif
|
||||
# include <windows.h>
|
||||
# if defined(BOOST_NO_STRINGSTREAM)
|
||||
# include <strstream>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -519,7 +519,7 @@ bool recursive_try_mutex::do_trylock()
|
||||
# if defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
|
||||
int res = 0;
|
||||
res = pthread_mutex_trylock(&m_mutex);
|
||||
assert(res == 0);
|
||||
assert(res == 0 || res == EBUSY);
|
||||
|
||||
if (res == 0)
|
||||
{
|
||||
|
||||
@@ -220,6 +220,7 @@ bool thread::operator!=(const thread& other) const
|
||||
|
||||
void thread::join()
|
||||
{
|
||||
assert(m_joinable); //See race condition comment below
|
||||
int res = 0;
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_thread), INFINITE);
|
||||
@@ -367,4 +368,9 @@ void thread_group::join_all()
|
||||
}
|
||||
}
|
||||
|
||||
int thread_group::size()
|
||||
{
|
||||
return m_threads.size();
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
@@ -27,7 +27,7 @@ inline void to_time(int milliseconds, boost::xtime& xt)
|
||||
xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
|
||||
NANOSECONDS_PER_MILLISECOND);
|
||||
|
||||
if (xt.nsec > NANOSECONDS_PER_SECOND)
|
||||
if (xt.nsec >= NANOSECONDS_PER_SECOND)
|
||||
{
|
||||
++xt.sec;
|
||||
xt.nsec -= NANOSECONDS_PER_SECOND;
|
||||
@@ -39,7 +39,7 @@ inline void to_timespec(const boost::xtime& xt, timespec& ts)
|
||||
{
|
||||
ts.tv_sec = static_cast<int>(xt.sec);
|
||||
ts.tv_nsec = static_cast<int>(xt.nsec);
|
||||
if(ts.tv_nsec > NANOSECONDS_PER_SECOND)
|
||||
if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
|
||||
{
|
||||
ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
|
||||
ts.tv_nsec %= NANOSECONDS_PER_SECOND;
|
||||
@@ -75,7 +75,7 @@ inline void to_timespec_duration(const boost::xtime& xt, timespec& ts)
|
||||
ts.tv_sec -= 1;
|
||||
ts.tv_nsec += NANOSECONDS_PER_SECOND;
|
||||
}
|
||||
if(ts.tv_nsec > NANOSECONDS_PER_SECOND)
|
||||
if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
|
||||
{
|
||||
ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
|
||||
ts.tv_nsec %= NANOSECONDS_PER_SECOND;
|
||||
|
||||
@@ -38,7 +38,7 @@ import testing ;
|
||||
<define>BOOST_ALL_NO_LIB=1
|
||||
<define>BOOST_THREAD_USE_LIB=1
|
||||
<define>BOOST_THREAD_TEST=1
|
||||
<runtime-link>static
|
||||
#<runtime-link>static
|
||||
<threading>multi
|
||||
: ## default build ##
|
||||
;
|
||||
@@ -69,7 +69,6 @@ import testing ;
|
||||
[ run test_once.cpp <template>boost_thread_test_dll ]
|
||||
[ run test_xtime.cpp <template>boost_thread_test_dll ]
|
||||
[ run test_barrier.cpp <template>boost_thread_test_dll ]
|
||||
[ run test_read_write_mutex.cpp <template>boost_thread_test_dll ]
|
||||
|
||||
[ run test_thread.cpp <template>boost_thread_test_lib : : : : test_thread_lib ]
|
||||
[ run test_mutex.cpp <template>boost_thread_test_lib : : : : test_mutex_lib ]
|
||||
@@ -78,6 +77,5 @@ import testing ;
|
||||
[ run test_once.cpp <template>boost_thread_test_lib : : : : test_once_lib ]
|
||||
[ run test_xtime.cpp <template>boost_thread_test_lib : : : : test_xtime_lib ]
|
||||
[ run test_barrier.cpp <template>boost_thread_test_lib : : : : test_barrier_lib ]
|
||||
[ run test_read_write_mutex.cpp <template>boost_thread_test_lib : : : : test_read_write_mutex_lib ]
|
||||
;
|
||||
}
|
||||
|
||||
@@ -19,18 +19,27 @@
|
||||
import testing ;
|
||||
|
||||
project
|
||||
: requirements <library>../build//boost_thread
|
||||
<library>../../test/build//boost_unit_test_framework
|
||||
: requirements <library>../../test/build//boost_unit_test_framework
|
||||
<threading>multi
|
||||
;
|
||||
|
||||
rule thread-run ( sources )
|
||||
{
|
||||
return
|
||||
[ run $(sources) ../build//boost_thread ]
|
||||
[ run $(sources) ../build//boost_thread/<link>static
|
||||
: : : : $(sources[1]:B)_lib ]
|
||||
;
|
||||
}
|
||||
|
||||
{
|
||||
test-suite "threads"
|
||||
: [ run test_thread.cpp ]
|
||||
[ run test_mutex.cpp ]
|
||||
[ run test_condition.cpp ]
|
||||
[ run test_tss.cpp ]
|
||||
[ run test_once.cpp ]
|
||||
[ run test_xtime.cpp ]
|
||||
[ run test_barrier.cpp ]
|
||||
: [ thread-run test_thread.cpp ]
|
||||
[ thread-run test_mutex.cpp ]
|
||||
[ thread-run test_condition.cpp ]
|
||||
[ thread-run test_tss.cpp ]
|
||||
[ thread-run test_once.cpp ]
|
||||
[ thread-run test_xtime.cpp ]
|
||||
[ thread-run test_barrier.cpp ]
|
||||
;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ void test_barrier()
|
||||
|
||||
g.join_all();
|
||||
|
||||
BOOST_TEST(global_parameter == 5);
|
||||
BOOST_CHECK(global_parameter == 5);
|
||||
}
|
||||
|
||||
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <boost/thread/condition.hpp>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/unit_test_suite_ex.hpp>
|
||||
|
||||
#define DEFAULT_EXECUTION_MONITOR_TYPE execution_monitor::use_sleep_only
|
||||
#include <libs/thread/test/util.inl>
|
||||
|
||||
@@ -1,336 +0,0 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// 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.
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <boost/thread/read_write_mutex.hpp>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace {
|
||||
|
||||
int shared_val = 0;
|
||||
|
||||
boost::xtime xsecs(int secs)
|
||||
{
|
||||
boost::xtime ret;
|
||||
BOOST_TEST(boost::TIME_UTC == boost::xtime_get(&ret, boost::TIME_UTC));
|
||||
ret.sec += secs;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename RW>
|
||||
class thread_adapter
|
||||
{
|
||||
public:
|
||||
thread_adapter(void (*func)(void*,RW &), void* param1,RW ¶m2)
|
||||
: _func(func), _param1(param1) ,_param2(param2){ }
|
||||
void operator()() const { _func(_param1, _param2); }
|
||||
|
||||
private:
|
||||
void (*_func)(void*, RW &);
|
||||
void* _param1;
|
||||
RW& _param2;
|
||||
};
|
||||
|
||||
template <typename RW>
|
||||
struct data
|
||||
{
|
||||
data(int id, RW &m, int secs=0)
|
||||
: m_id(id), m_value(-1), m_secs(secs), m_rw(m)
|
||||
{
|
||||
}
|
||||
int m_id;
|
||||
int m_value;
|
||||
int m_secs;
|
||||
|
||||
RW& m_rw; // Reader/Writer mutex
|
||||
};
|
||||
|
||||
// plain_writer excercises the "infinite" lock for each
|
||||
// read_write_mutex type.
|
||||
|
||||
template<typename RW>
|
||||
void plain_writer(void *arg,RW &rw)
|
||||
{
|
||||
data<RW> *pdata = (data<RW> *) arg;
|
||||
// std::cout << "-->W" << pdata->m_id << "\n";
|
||||
|
||||
typename RW::scoped_read_write_lock l(rw, boost::read_write_lock_state::write_locked);
|
||||
|
||||
boost::thread::sleep(xsecs(3));
|
||||
shared_val += 10;
|
||||
|
||||
pdata->m_value = shared_val;
|
||||
}
|
||||
|
||||
template<typename RW>
|
||||
void plain_reader(void *arg,RW &rw)
|
||||
{
|
||||
data<RW> *pdata = (data<RW> *) arg;
|
||||
typename RW::scoped_read_write_lock l(rw, boost::read_write_lock_state::read_locked);
|
||||
|
||||
pdata->m_value = shared_val;
|
||||
}
|
||||
|
||||
template<typename RW>
|
||||
void try_writer(void *arg,RW &rw)
|
||||
{
|
||||
data<RW> *pdata = (data<RW> *) arg;
|
||||
// std::cout << "-->W" << pdata->m_id << "\n";
|
||||
|
||||
typename RW::scoped_try_read_write_lock l(rw, boost::read_write_lock_state::unlocked);
|
||||
|
||||
if (l.try_write_lock())
|
||||
{
|
||||
|
||||
boost::thread::sleep(xsecs(3));
|
||||
shared_val += 10;
|
||||
|
||||
pdata->m_value = shared_val;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename RW>
|
||||
void try_reader(void *arg,RW &rw)
|
||||
{
|
||||
data<RW> *pdata = (data<RW> *) arg;
|
||||
typename RW::scoped_try_read_write_lock l(rw, boost::read_write_lock_state::unlocked);
|
||||
|
||||
if (l.try_read_lock())
|
||||
{
|
||||
pdata->m_value = shared_val;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename RW>
|
||||
void timed_writer(void *arg,RW &rw)
|
||||
{
|
||||
data<RW> *pdata = (data<RW> *) arg;
|
||||
|
||||
boost::xtime xt;
|
||||
xt = xsecs(pdata->m_secs);
|
||||
typename RW::scoped_timed_read_write_lock l(rw,boost::read_write_lock_state::unlocked);
|
||||
|
||||
if (l.timed_write_lock(xt))
|
||||
{
|
||||
boost::thread::sleep(xsecs(3));
|
||||
shared_val += 10;
|
||||
|
||||
pdata->m_value = shared_val;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename RW>
|
||||
void timed_reader(void *arg,RW &rw)
|
||||
{
|
||||
data<RW> *pdata = (data<RW> *) arg;
|
||||
boost::xtime xt;
|
||||
xt = xsecs(pdata->m_secs);
|
||||
|
||||
typename RW::scoped_timed_read_write_lock l(rw,boost::read_write_lock_state::unlocked);
|
||||
|
||||
if (l.timed_read_lock(xt))
|
||||
{
|
||||
pdata->m_value = shared_val;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename RW>
|
||||
void dump_times(const char *prefix,data<RW> *pdata)
|
||||
{
|
||||
std::cout << " " << prefix << pdata->m_id <<
|
||||
" In:" << pdata->m_start.LowPart <<
|
||||
" Holding:" << pdata->m_holding.LowPart <<
|
||||
" Out: " << pdata->m_end.LowPart << std::endl;
|
||||
}
|
||||
|
||||
template<typename RW>
|
||||
void test_plain_read_write_mutex(RW &rw)
|
||||
{
|
||||
shared_val = 0;
|
||||
data<RW> r1(1,rw);
|
||||
data<RW> r2(2,rw);
|
||||
data<RW> w1(1,rw);
|
||||
data<RW> w2(2,rw);
|
||||
|
||||
// Writer one launches, holds the lock for 3 seconds.
|
||||
boost::thread tw1(thread_adapter<RW>(plain_writer,&w1,rw));
|
||||
|
||||
// Writer two launches, tries to grab the lock, "clearly"
|
||||
// after Writer one will already be holding it.
|
||||
boost::thread::sleep(xsecs(1));
|
||||
boost::thread tw2(thread_adapter<RW>(plain_writer,&w2,rw));
|
||||
|
||||
// Reader one launches, "clearly" after writer two, and "clearly"
|
||||
// while writer 1 still holds the lock
|
||||
boost::thread::sleep(xsecs(1));
|
||||
boost::thread tr1(thread_adapter<RW>(plain_reader,&r1,rw));
|
||||
boost::thread tr2(thread_adapter<RW>(plain_reader,&r2,rw));
|
||||
|
||||
tr2.join();
|
||||
tr1.join();
|
||||
tw2.join();
|
||||
tw1.join();
|
||||
|
||||
if (rw.policy() == boost::read_write_scheduling_policy::writer_priority)
|
||||
{
|
||||
BOOST_TEST(w1.m_value == 10);
|
||||
BOOST_TEST(w2.m_value == 20);
|
||||
BOOST_TEST(r1.m_value == 20); // Readers get in after 2nd writer
|
||||
BOOST_TEST(r2.m_value == 20);
|
||||
}
|
||||
else if (rw.policy() == boost::read_write_scheduling_policy::reader_priority)
|
||||
{
|
||||
BOOST_TEST(w1.m_value == 10);
|
||||
BOOST_TEST(w2.m_value == 20);
|
||||
BOOST_TEST(r1.m_value == 10); // Readers get in before 2nd writer
|
||||
BOOST_TEST(r2.m_value == 10);
|
||||
}
|
||||
else if (rw.policy() == boost::read_write_scheduling_policy::alternating_many_reads)
|
||||
{
|
||||
BOOST_TEST(w1.m_value == 10);
|
||||
BOOST_TEST(w2.m_value == 20);
|
||||
BOOST_TEST(r1.m_value == 10); // Readers get in before 2nd writer
|
||||
BOOST_TEST(r2.m_value == 10);
|
||||
}
|
||||
else if (rw.policy() == boost::read_write_scheduling_policy::alternating_single_read)
|
||||
{
|
||||
BOOST_TEST(w1.m_value == 10);
|
||||
BOOST_TEST(w2.m_value == 20);
|
||||
|
||||
// One Reader gets in before 2nd writer, but we can't tell
|
||||
// which reader will "win", so just check their sum.
|
||||
BOOST_TEST((r1.m_value + r2.m_value == 30));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename RW>
|
||||
void test_try_read_write_mutex(RW &rw)
|
||||
{
|
||||
data<RW> r1(1,rw);
|
||||
data<RW> w1(2,rw);
|
||||
data<RW> w2(3,rw);
|
||||
|
||||
// We start with some specialized tests for "try" behavior
|
||||
|
||||
shared_val = 0;
|
||||
|
||||
// Writer one launches, holds the lock for 3 seconds.
|
||||
|
||||
boost::thread tw1(thread_adapter<RW>(try_writer,&w1,rw));
|
||||
|
||||
// Reader one launches, "clearly" after writer #1 holds the lock
|
||||
// and before it releases the lock.
|
||||
boost::thread::sleep(xsecs(1));
|
||||
boost::thread tr1(thread_adapter<RW>(try_reader,&r1,rw));
|
||||
|
||||
// Writer two launches in the same timeframe.
|
||||
boost::thread tw2(thread_adapter<RW>(try_writer,&w2,rw));
|
||||
|
||||
tw2.join();
|
||||
tr1.join();
|
||||
tw1.join();
|
||||
|
||||
BOOST_TEST(w1.m_value == 10);
|
||||
BOOST_TEST(r1.m_value == -1); // Try would return w/o waiting
|
||||
BOOST_TEST(w2.m_value == -1); // Try would return w/o waiting
|
||||
|
||||
// We finish by repeating the plain tests with the try lock
|
||||
// This is important to verify that try locks are proper read_write_mutexes as
|
||||
// well.
|
||||
test_plain_read_write_mutex(rw);
|
||||
|
||||
}
|
||||
|
||||
template<typename RW>
|
||||
void test_timed_read_write_mutex(RW &rw)
|
||||
{
|
||||
data<RW> r1(1,rw,1);
|
||||
data<RW> r2(2,rw,3);
|
||||
data<RW> w1(3,rw,3);
|
||||
data<RW> w2(4,rw,1);
|
||||
|
||||
// We begin with some specialized tests for "timed" behavior
|
||||
|
||||
shared_val = 0;
|
||||
|
||||
// Writer one will hold the lock for 3 seconds.
|
||||
boost::thread tw1(thread_adapter<RW>(timed_writer,&w1,rw));
|
||||
|
||||
boost::thread::sleep(xsecs(1));
|
||||
// Writer two will "clearly" try for the lock after the readers
|
||||
// have tried for it. Writer will wait up 1 second for the lock.
|
||||
// This write will fail.
|
||||
boost::thread tw2(thread_adapter<RW>(timed_writer,&w2,rw));
|
||||
|
||||
// Readers one and two will "clearly" try for the lock after writer
|
||||
// one already holds it. 1st reader will wait 1 second, and will fail
|
||||
// to get the lock. 2nd reader will wait 3 seconds, and will get
|
||||
// the lock.
|
||||
|
||||
boost::thread tr1(thread_adapter<RW>(timed_reader,&r1,rw));
|
||||
boost::thread tr2(thread_adapter<RW>(timed_reader,&r2,rw));
|
||||
|
||||
|
||||
tw1.join();
|
||||
tr1.join();
|
||||
tr2.join();
|
||||
tw2.join();
|
||||
|
||||
|
||||
BOOST_TEST(w1.m_value == 10);
|
||||
BOOST_TEST(r1.m_value == -1);
|
||||
BOOST_TEST(r2.m_value == 10);
|
||||
BOOST_TEST(w2.m_value == -1);
|
||||
|
||||
// We follow by repeating the try tests with the timed lock.
|
||||
// This is important to verify that timed locks are proper try locks as
|
||||
// well
|
||||
test_try_read_write_mutex(rw);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void test_read_write_mutex()
|
||||
{
|
||||
int i;
|
||||
for(i = (int) boost::read_write_scheduling_policy::writer_priority;
|
||||
i <= (int) boost::read_write_scheduling_policy::alternating_single_read;
|
||||
i++)
|
||||
{
|
||||
boost::read_write_mutex plain_rw(static_cast<boost::read_write_scheduling_policy::read_write_scheduling_policy_enum>(i));
|
||||
boost::try_read_write_mutex try_rw(static_cast<boost::read_write_scheduling_policy::read_write_scheduling_policy_enum>(i));
|
||||
boost::timed_read_write_mutex timed_rw(static_cast<boost::read_write_scheduling_policy::read_write_scheduling_policy_enum>(i));
|
||||
|
||||
std::cout << "plain test, sp=" << i << "\n";
|
||||
test_plain_read_write_mutex(plain_rw);
|
||||
|
||||
std::cout << "try test, sp=" << i << "\n";
|
||||
test_try_read_write_mutex(try_rw);
|
||||
|
||||
std::cout << "timed test, sp=" << i << "\n";
|
||||
test_timed_read_write_mutex(timed_rw);
|
||||
}
|
||||
}
|
||||
|
||||
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
boost::unit_test_framework::test_suite* test =
|
||||
BOOST_TEST_SUITE("Boost.Threads: read_write_mutex test suite");
|
||||
|
||||
test->add(BOOST_TEST_CASE(&test_read_write_mutex));
|
||||
|
||||
return test;
|
||||
}
|
||||
@@ -29,9 +29,9 @@ void simple_thread()
|
||||
void comparison_thread(boost::thread* parent)
|
||||
{
|
||||
boost::thread thrd;
|
||||
BOOST_TEST(thrd != *parent);
|
||||
BOOST_CHECK(thrd != *parent);
|
||||
boost::thread thrd2;
|
||||
BOOST_TEST(thrd == thrd2);
|
||||
BOOST_CHECK(thrd == thrd2);
|
||||
}
|
||||
|
||||
void test_sleep()
|
||||
@@ -41,7 +41,7 @@ void test_sleep()
|
||||
|
||||
// Ensure it's in a range instead of checking actual equality due to time
|
||||
// lapse
|
||||
BOOST_CHECK(in_range(xt));
|
||||
BOOST_CHECK(in_range(xt, 2));
|
||||
}
|
||||
|
||||
void do_test_creation()
|
||||
|
||||
@@ -30,8 +30,8 @@ inline boost::xtime delay(int secs, int msecs=0, int nsecs=0)
|
||||
const int NANOSECONDS_PER_MILLISECOND = 1000000;
|
||||
|
||||
boost::xtime xt;
|
||||
BOOST_CHECK_EQUAL(boost::xtime_get(&xt, boost::TIME_UTC),
|
||||
static_cast<int>(boost::TIME_UTC));
|
||||
if (boost::TIME_UTC != boost::xtime_get (&xt, boost::TIME_UTC))
|
||||
BOOST_ERROR ("boost::xtime_get != boost::TIME_UTC");
|
||||
|
||||
nsecs += xt.nsec;
|
||||
msecs += nsecs / NANOSECONDS_PER_MILLISECOND;
|
||||
@@ -140,10 +140,10 @@ void timed_test(F func, int secs,
|
||||
}
|
||||
|
||||
template <typename F, typename T>
|
||||
class binder
|
||||
class thread_binder
|
||||
{
|
||||
public:
|
||||
binder(const F& func, const T& param)
|
||||
thread_binder(const F& func, const T& param)
|
||||
: func(func), param(param) { }
|
||||
void operator()() const { func(param); }
|
||||
|
||||
@@ -153,9 +153,9 @@ private:
|
||||
};
|
||||
|
||||
template <typename F, typename T>
|
||||
binder<F, T> bind(const F& func, const T& param)
|
||||
thread_binder<F, T> bind(const F& func, const T& param)
|
||||
{
|
||||
return binder<F, T>(func, param);
|
||||
return thread_binder<F, T>(func, param);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
||||
Reference in New Issue
Block a user