mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 21:52:07 +00:00
Compare commits
75 Commits
svn-branch
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
35b8104a7c | ||
|
|
a8daedac5e | ||
|
|
5fa26fb3ac | ||
|
|
ea3e297175 | ||
|
|
a11bd6ebd9 | ||
|
|
9889bf50a2 | ||
|
|
d75fb2deda | ||
|
|
6355a5b28d | ||
|
|
595bbee41e | ||
|
|
cb3f3a1f64 | ||
|
|
0e44838905 | ||
|
|
64cd268fc7 | ||
|
|
f048dd81f2 | ||
|
|
5746f2214c | ||
|
|
099af669d4 | ||
|
|
79cac706a7 | ||
|
|
df229074ac | ||
|
|
191c27e856 | ||
|
|
e5ee01b43c | ||
|
|
c46b040f6f | ||
|
|
72e4794f5b | ||
|
|
c30b65a0ea | ||
|
|
1cb08ff60c | ||
|
|
d3d7fd9317 | ||
|
|
acf0f97663 | ||
|
|
34bd87cea7 | ||
|
|
228f11262e | ||
|
|
9683e0f1cc | ||
|
|
674ae6d571 | ||
|
|
690d44e2e6 | ||
|
|
720ccdb474 | ||
|
|
a556ff6560 | ||
|
|
33c0af8253 | ||
|
|
86072f95ac | ||
|
|
c7b96bcd7d | ||
|
|
572c18302f | ||
|
|
efd1bdec23 | ||
|
|
ba86f9ff13 | ||
|
|
56b07cb5c0 | ||
|
|
358e32e98f | ||
|
|
01297016bd | ||
|
|
64b5b67661 | ||
|
|
b6f0ec7fd9 | ||
|
|
e9c0b5e0c5 | ||
|
|
4a005ea288 | ||
|
|
9658b69af4 | ||
|
|
e3c9446e29 | ||
|
|
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 |
@@ -1,13 +1,8 @@
|
||||
# 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.
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# Boost.Threads build Jamfile
|
||||
#
|
||||
@@ -46,7 +41,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 +96,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 +105,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
|
||||
|
||||
@@ -1,26 +1,39 @@
|
||||
# (C) Copyright Vladimir Prus, David Abrahams, Michael Stevens, Hartmut Kaiser,
|
||||
# William E Kempf 2002-2006
|
||||
# Use, modification and distribution are subject to the
|
||||
# Boost Software License, Version 1.0. (See accompanying file
|
||||
# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
import os ;
|
||||
|
||||
if [ os.name ] = NT
|
||||
{
|
||||
reqts = <link>shared:<define>BOOST_THREAD_BUILD_DLL=1 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
# Declare the uses system library
|
||||
lib pthread : : <name>pthread ;
|
||||
usage = <library>pthread ;
|
||||
}
|
||||
|
||||
project boost/thread
|
||||
: source-location ../src
|
||||
: usage-requirements $(usage)
|
||||
: requirements $(reqts) <threading>multi
|
||||
: requirements <link>shared:<define>BOOST_THREAD_BUILD_DLL=1 <threading>multi
|
||||
: default-build <threading>multi
|
||||
;
|
||||
|
||||
CPP_SOURCES = condition mutex recursive_mutex thread xtime once
|
||||
exceptions barrier tss tss_hooks tss_dll tss_pe ;
|
||||
CPP_SOURCES =
|
||||
barrier
|
||||
condition
|
||||
exceptions
|
||||
mutex
|
||||
once
|
||||
recursive_mutex
|
||||
read_write_mutex
|
||||
thread
|
||||
tss_hooks
|
||||
tss_dll
|
||||
tss_pe
|
||||
tss
|
||||
xtime
|
||||
;
|
||||
|
||||
lib boost_thread
|
||||
: $(CPP_SOURCES).cpp
|
||||
: <link>shared:<define>BOOST_THREAD_BUILD_DLL=1
|
||||
<link>static:<define>BOOST_THREAD_BUILD_LIB=1
|
||||
: # default build
|
||||
: <link>shared:<define>BOOST_THREAD_BUILD_DLL=1
|
||||
<link>static:<define>BOOST_THREAD_BUILD_LIB=1
|
||||
;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
# 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.
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
# Additional configuration variables used:
|
||||
# 1. PTW32_DIR and PTW32_LIB may be used on Win32 platforms to specify that
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
# Copyright (C) 2001-2003
|
||||
# William E. Kempf
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
import toolset ;
|
||||
toolset.using doxygen ;
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<section id="thread.acknowledgements"
|
||||
last-revision="$Date$">
|
||||
<title>Acknowledgements</title>
|
||||
<para>William E. Kempf was the architect, designer, and implementor of
|
||||
&Boost.Threads;.</para>
|
||||
&Boost.Thread;.</para>
|
||||
<para>Mac OS Carbon implementation written by Mac Murrett.</para>
|
||||
<para>Dave Moore provided initial submissions and further comments on the
|
||||
<code>barrier</code>
|
||||
@@ -28,7 +32,7 @@ last-revision="$Date$">
|
||||
on the design), Paul Mclachlan, Thomas Matelich and Iain Hanson (for help
|
||||
in trying to get the build to work on other platforms), and Kevin S. Van
|
||||
Horn (for several updates/corrections to the documentation).</para>
|
||||
<para>Mike Glassford finished changes to &Boost.Threads; that were begun
|
||||
<para>Mike Glassford finished changes to &Boost.Thread; that were begun
|
||||
by William Kempf and moved them into the main CVS branch.
|
||||
He also addressed a number of issues that were brought up on the Boost
|
||||
developer's mailing list and provided some additions and changes to the
|
||||
@@ -38,7 +42,7 @@ last-revision="$Date$">
|
||||
Mike Glassford finished William Kempf's conversion of the documentation to
|
||||
BoostBook format and added a number of new sections.</para>
|
||||
<para>Discussions on the boost.org mailing list were essential in the
|
||||
development of &Boost.Threads;
|
||||
development of &Boost.Thread;
|
||||
. As of August 1, 2001, participants included Alan Griffiths, Albrecht
|
||||
Fritzsche, Aleksey Gurtovoy, Alexander Terekhov, Andrew Green, Andy Sawyer,
|
||||
Asger Alstrup Nielsen, Beman Dawes, Bill Klein, Bill Rutiser, Bill Wade,
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<header name="boost/thread/barrier.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
@@ -32,9 +36,9 @@
|
||||
and reset the barrier. This functionality allows the same set of N threads to re-use
|
||||
a barrier object to synchronize their execution at multiple points during their
|
||||
execution.</para>
|
||||
<para>See <xref linkend="threads.glossary"/> for definitions of thread
|
||||
states <link linkend="threads.glossary.thread-state">blocked</link>
|
||||
and <link linkend="threads.glossary.thread-state">ready</link>.
|
||||
<para>See <xref linkend="thread.glossary"/> for definitions of thread
|
||||
states <link linkend="thread.glossary.thread-state">blocked</link>
|
||||
and <link linkend="thread.glossary.thread-state">ready</link>.
|
||||
Note that "waiting" is a synonym for blocked.</para>
|
||||
</description>
|
||||
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<bibliography id="threads.bibliography"
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<bibliography id="thread.bibliography"
|
||||
last-revision="$Date$">
|
||||
<title>Bibliography</title>
|
||||
<biblioentry id="threads.bib.AndrewsSchneider83">
|
||||
<abbrev id="threads.bib.AndrewsSchneider83.abbrev">AndrewsSchnieder83</abbrev>
|
||||
<biblioentry id="thread.bib.AndrewsSchneider83">
|
||||
<abbrev id="thread.bib.AndrewsSchneider83.abbrev">AndrewsSchnieder83</abbrev>
|
||||
<biblioset relation="journal">
|
||||
<title>ACM Computing Surveys</title>
|
||||
<volumenum>Vol. 15</volumenum>
|
||||
@@ -38,23 +42,23 @@ last-revision="$Date$">
|
||||
Expressions, Message Passing, and Remote Procedure Call in addition to the
|
||||
basics</para>
|
||||
</biblioentry>
|
||||
<biblioentry id="threads.bib.Boost">
|
||||
<abbrev id="threads.bib.Boost.abbrev">Boost</abbrev>
|
||||
<biblioentry id="thread.bib.Boost">
|
||||
<abbrev id="thread.bib.Boost.abbrev">Boost</abbrev>
|
||||
<bibliomisc>The <emphasis>Boost</emphasis> world wide web site.
|
||||
<ulink url="http:/www.boost.org">http://www.boost.org</ulink></bibliomisc>
|
||||
<para>&Boost.Threads; is one of many Boost libraries. The Boost web
|
||||
<para>&Boost.Thread; is one of many Boost libraries. The Boost web
|
||||
site includes a great deal of documentation and general information which
|
||||
applies to all Boost libraries. Current copies of the libraries including
|
||||
documentation and test programs may be downloaded from the web
|
||||
site.</para>
|
||||
</biblioentry>
|
||||
<biblioentry id="threads.bib.Hansen73">
|
||||
<abbrev id="threads.bib.Hansen73.abbrev">Hansen73</abbrev>
|
||||
<biblioentry id="thread.bib.Hansen73">
|
||||
<abbrev id="thread.bib.Hansen73.abbrev">Hansen73</abbrev>
|
||||
<biblioset relation="journal">
|
||||
<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
|
||||
@@ -74,8 +78,8 @@ last-revision="$Date$">
|
||||
Brinch Hansen was years ahead of others in recognizing pattern concepts
|
||||
applied to software, too.</para>
|
||||
</biblioentry>
|
||||
<biblioentry id="threads.bib.Butenhof97">
|
||||
<abbrev id="threads.bib.Butenhof97.abbrev">Butenhof97</abbrev>
|
||||
<biblioentry id="thread.bib.Butenhof97">
|
||||
<abbrev id="thread.bib.Butenhof97.abbrev">Butenhof97</abbrev>
|
||||
<title>
|
||||
<ulink url="http://cseng.aw.com/book/0,3828,0201633922,00.html"
|
||||
>Programming with POSIX Threads </ulink>
|
||||
@@ -92,8 +96,8 @@ last-revision="$Date$">
|
||||
them. Many of the insights given apply to all multithreaded programming, not
|
||||
just POSIX Threads</para>
|
||||
</biblioentry>
|
||||
<biblioentry id="threads.bib.Hoare74">
|
||||
<abbrev id="threads.bib.Hoare74.abbrev">Hoare74</abbrev>
|
||||
<biblioentry id="thread.bib.Hoare74">
|
||||
<abbrev id="thread.bib.Hoare74.abbrev">Hoare74</abbrev>
|
||||
<biblioset relation="journal">
|
||||
<title>Communications of the ACM</title>
|
||||
<volumenum>Vol. 17</volumenum>
|
||||
@@ -115,8 +119,8 @@ last-revision="$Date$">
|
||||
multithreading patterns. This is one of the most often referenced papers in
|
||||
all of computer science, and with good reason.</para>
|
||||
</biblioentry>
|
||||
<biblioentry id="threads.bib.ISO98">
|
||||
<abbrev id="threads.bib.ISO98.abbrev">ISO98</abbrev>
|
||||
<biblioentry id="thread.bib.ISO98">
|
||||
<abbrev id="thread.bib.ISO98.abbrev">ISO98</abbrev>
|
||||
<title>
|
||||
<ulink url="http://www.ansi.org">Programming Language C++</ulink>
|
||||
</title>
|
||||
@@ -125,8 +129,8 @@ last-revision="$Date$">
|
||||
<para>This is the official C++ Standards document. Available from the ANSI
|
||||
(American National Standards Institute) Electronic Standards Store.</para>
|
||||
</biblioentry>
|
||||
<biblioentry id="threads.bib.McDowellHelmbold89">
|
||||
<abbrev id="threads.bib.McDowellHelmbold89.abbrev">McDowellHelmbold89</abbrev>
|
||||
<biblioentry id="thread.bib.McDowellHelmbold89">
|
||||
<abbrev id="thread.bib.McDowellHelmbold89.abbrev">McDowellHelmbold89</abbrev>
|
||||
<biblioset relation="journal">
|
||||
<title>Communications of the ACM</title>
|
||||
<volumenum>Vol. 21</volumenum>
|
||||
@@ -153,8 +157,8 @@ last-revision="$Date$">
|
||||
<para>Identifies many of the unique failure modes and debugging difficulties
|
||||
associated with concurrent programs.</para>
|
||||
</biblioentry>
|
||||
<biblioentry id="threads.bib.SchmidtPyarali">
|
||||
<abbrev id="threads.bib.SchmidtPyarali.abbrev">SchmidtPyarali</abbrev>
|
||||
<biblioentry id="thread.bib.SchmidtPyarali">
|
||||
<abbrev id="thread.bib.SchmidtPyarali.abbrev">SchmidtPyarali</abbrev>
|
||||
<title>
|
||||
<ulink url="http://www.cs.wustl.edu/~schmidt/win32-cv-1.html8"
|
||||
>Strategies for Implementing POSIX Condition Variables on Win32</ulink>
|
||||
@@ -172,14 +176,14 @@ last-revision="$Date$">
|
||||
</authorgroup>
|
||||
<orgname>Department of Computer Science, Washington University, St. Louis,
|
||||
Missouri</orgname>
|
||||
<para>Rationale for understanding &Boost.Threads; condition
|
||||
<para>Rationale for understanding &Boost.Thread; condition
|
||||
variables. Note that Alexander Terekhov found some bugs in the
|
||||
implementation given in this article, so pthreads-win32 and &Boost.Threads;
|
||||
implementation given in this article, so pthreads-win32 and &Boost.Thread;
|
||||
are even more complicated yet.</para>
|
||||
</biblioentry>
|
||||
<biblioentry id="threads.bib.SchmidtStalRohnertBuschmann">
|
||||
<biblioentry id="thread.bib.SchmidtStalRohnertBuschmann">
|
||||
<abbrev
|
||||
id="threads.bib.SchmidtStalRohnertBuschmann.abbrev">SchmidtStalRohnertBuschmann</abbrev>
|
||||
id="thread.bib.SchmidtStalRohnertBuschmann.abbrev">SchmidtStalRohnertBuschmann</abbrev>
|
||||
<title>
|
||||
<ulink
|
||||
url="http://www.wiley.com/Corporate/Website/Objects/Products/0,9049,104671,00.html"
|
||||
@@ -210,11 +214,11 @@ last-revision="$Date$">
|
||||
<copyright><year>2000</year></copyright>
|
||||
<para>This is a very good explanation of how to apply several patterns
|
||||
useful for concurrent programming. Among the patterns documented is the
|
||||
Monitor Pattern mentioned frequently in the &Boost.Threads;
|
||||
Monitor Pattern mentioned frequently in the &Boost.Thread;
|
||||
documentation.</para>
|
||||
</biblioentry>
|
||||
<biblioentry id="threads.bib.Stroustrup">
|
||||
<abbrev id="threads.bib.Stroustrup.abbrev">Stroustrup</abbrev>
|
||||
<biblioentry id="thread.bib.Stroustrup">
|
||||
<abbrev id="thread.bib.Stroustrup.abbrev">Stroustrup</abbrev>
|
||||
<title>
|
||||
<ulink url="http://cseng.aw.com/book/0,3828,0201700735,00.html"
|
||||
>The C++ Programming Language</ulink>
|
||||
|
||||
@@ -1,45 +1,49 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<section id="thread.build" last-revision="$Date$">
|
||||
<title>Build</title>
|
||||
<para>
|
||||
How you build the &Boost.Threads; libraries, and how you build your own applications
|
||||
How you build the &Boost.Thread; libraries, and how you build your own applications
|
||||
that use those libraries, are some of the most frequently asked questions. Build
|
||||
processes are difficult to deal with in a portable manner. That's one reason
|
||||
why &Boost.Threads; makes use of &Boost.Build;.
|
||||
why &Boost.Thread; makes use of &Boost.Build;.
|
||||
In general you should refer to the documentation for &Boost.Build;.
|
||||
This document will only supply you with some simple usage examples for how to
|
||||
use <emphasis>bjam</emphasis> to build and test &Boost.Threads;. In addition, this document
|
||||
use <emphasis>bjam</emphasis> to build and test &Boost.Thread;. In addition, this document
|
||||
will try to explain the build requirements so that users may create their own
|
||||
build processes (for instance, create an IDE specific project), both for building
|
||||
and testing &Boost.Threads;, as well as for building their own projects using
|
||||
&Boost.Threads;.
|
||||
and testing &Boost.Thread;, as well as for building their own projects using
|
||||
&Boost.Thread;.
|
||||
</para>
|
||||
<section id="thread.build.building">
|
||||
<title>Building the &Boost.Threads; Libraries</title>
|
||||
<title>Building the &Boost.Thread; Libraries</title>
|
||||
<para>
|
||||
To build the &Boost.Threads; libraries using &Boost.Build;, simply change to the
|
||||
To build the &Boost.Thread; libraries using &Boost.Build;, simply change to the
|
||||
directory <emphasis>boost_root</emphasis>/libs/thread/build and execute the command:
|
||||
<programlisting>bjam -sTOOLS=<emphasis>toolset</emphasis></programlisting>
|
||||
This will create the debug and the release builds of the &Boost.Threads; library.
|
||||
This will create the debug and the release builds of the &Boost.Thread; library.
|
||||
<note>Invoking the above command in <emphasis>boost_root</emphasis> will build all of
|
||||
the Boost distribution, including &Boost.Threads;.</note>
|
||||
the Boost distribution, including &Boost.Thread;.</note>
|
||||
</para>
|
||||
<para>
|
||||
The Jamfile supplied with &Boost.Threads; produces a dynamic link library named
|
||||
The Jamfile supplied with &Boost.Thread; produces a dynamic link library named
|
||||
<emphasis>boost_thread{build-specific-tags}.{extension}</emphasis>, where the build-specific
|
||||
tags indicate the toolset used to build the library, whether it's a debug or release
|
||||
build, what version of Boost was used, etc.; and the extension is the appropriate extension
|
||||
for a dynamic link library for the platform for which &Boost.Threads; is being built.
|
||||
for a dynamic link library for the platform for which &Boost.Thread; is being built.
|
||||
For instance, a debug library built for Win32 with VC++ 7.1 using Boost 1.31 would
|
||||
be named <emphasis>boost_thread-vc71-mt-gd-1_31.dll</emphasis>.
|
||||
</para>
|
||||
<para>
|
||||
The source files that are used to create the &Boost.Threads; library
|
||||
The source files that are used to create the &Boost.Thread; library
|
||||
are all of the *.cpp files found in <emphasis>boost_root</emphasis>/libs/thread/src.
|
||||
These need to be built with the compiler's and linker's multi-threading support enabled.
|
||||
If you want to create your own build solution you'll have to follow these same
|
||||
@@ -48,9 +52,9 @@
|
||||
</para>
|
||||
</section>
|
||||
<section id="thread.build.testing">
|
||||
<title>Testing the &Boost.Threads; Libraries</title>
|
||||
<title>Testing the &Boost.Thread; Libraries</title>
|
||||
<para>
|
||||
To test the &Boost.Threads; libraries using &Boost.Build;, simply change to the
|
||||
To test the &Boost.Thread; libraries using &Boost.Build;, simply change to the
|
||||
directory <emphasis>boost_root</emphasis>/libs/thread/test and execute the command:
|
||||
<programlisting>bjam -sTOOLS=<emphasis>toolset</emphasis> test</programlisting>
|
||||
</para>
|
||||
|
||||
440
doc/concepts.xml
440
doc/concepts.xml
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,13 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<header name="boost/thread/condition.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
@@ -21,12 +25,12 @@
|
||||
|
||||
<description>
|
||||
<para>A <classname>condition</classname> object is always used in
|
||||
conjunction with a <link linkend="threads.concepts.mutexes">mutex</link>
|
||||
conjunction with a <link linkend="thread.concepts.mutexes">mutex</link>
|
||||
object (an object whose type is a model of a <link
|
||||
linkend="threads.concepts.Mutex">Mutex</link> or one of its
|
||||
linkend="thread.concepts.Mutex">Mutex</link> or one of its
|
||||
refinements). The mutex object must be locked prior to waiting on the
|
||||
condition, which is verified by passing a lock object (an object whose
|
||||
type is a model of <link linkend="threads.concepts.Lock">Lock</link> or
|
||||
type is a model of <link linkend="thread.concepts.Lock">Lock</link> or
|
||||
one of its refinements) to the <classname>condition</classname> object's
|
||||
wait functions. Upon blocking on the <classname>condition</classname>
|
||||
object, the thread unlocks the mutex object. When the thread returns
|
||||
@@ -39,8 +43,8 @@
|
||||
&cite.SchmidtStalRohnertBuschmann; and &cite.Hoare74;). Monitors are one
|
||||
of the most important patterns for creating reliable multithreaded
|
||||
programs.</para>
|
||||
<para>See <xref linkend="threads.glossary"/> for definitions of <link
|
||||
linkend="threads.glossary.thread-state">thread states</link>
|
||||
<para>See <xref linkend="thread.glossary"/> for definitions of <link
|
||||
linkend="thread.glossary.thread-state">thread states</link>
|
||||
blocked and ready. Note that "waiting" is a synonym for blocked.</para>
|
||||
</description>
|
||||
|
||||
@@ -87,10 +91,10 @@
|
||||
</parameter>
|
||||
|
||||
<requires><simpara><code>ScopedLock</code> meets the <link
|
||||
linkend="threads.concepts.ScopedLock">ScopedLock</link>
|
||||
linkend="thread.concepts.ScopedLock">ScopedLock</link>
|
||||
requirements.</simpara></requires>
|
||||
<effects><simpara>Releases the lock on the <link
|
||||
linkend="threads.concepts.mutexes">mutex object</link>
|
||||
linkend="thread.concepts.mutexes">mutex object</link>
|
||||
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
|
||||
@@ -116,7 +120,7 @@
|
||||
</parameter>
|
||||
|
||||
<requires><simpara><code>ScopedLock</code> meets the <link
|
||||
linkend="threads.concepts.ScopedLock">ScopedLock</link>
|
||||
linkend="thread.concepts.ScopedLock">ScopedLock</link>
|
||||
requirements and the return from <code>pred()</code> is
|
||||
convertible to <code>bool</code>.</simpara></requires>
|
||||
<effects><simpara>As if: <code>while (!pred())
|
||||
@@ -141,10 +145,10 @@
|
||||
</parameter>
|
||||
|
||||
<requires><simpara><code>ScopedLock</code> meets the <link
|
||||
linkend="threads.concepts.ScopedLock">ScopedLock</link>
|
||||
linkend="thread.concepts.ScopedLock">ScopedLock</link>
|
||||
requirements.</simpara></requires>
|
||||
<effects><simpara>Releases the lock on the <link
|
||||
linkend="threads.concepts.mutexes">mutex object</link>
|
||||
linkend="thread.concepts.mutexes">mutex object</link>
|
||||
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>, or until time <code>xt</code>
|
||||
@@ -167,12 +171,16 @@
|
||||
<paramtype>ScopedLock&</paramtype>
|
||||
</parameter>
|
||||
|
||||
<parameter name="xt">
|
||||
<paramtype>const <classname>boost::xtime</classname>&</paramtype>
|
||||
</parameter>
|
||||
|
||||
<parameter name="pred">
|
||||
<paramtype>Pred</paramtype>
|
||||
</parameter>
|
||||
|
||||
<requires><simpara><code>ScopedLock</code> meets the <link
|
||||
linkend="threads.concepts.ScopedLock">ScopedLock</link>
|
||||
linkend="thread.concepts.ScopedLock">ScopedLock</link>
|
||||
requirements and the return from <code>pred()</code> is
|
||||
convertible to <code>bool</code>.</simpara></requires>
|
||||
<effects><simpara>As if: <code>while (!pred()) { if (!timed_wait(lock,
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<section id="thread.configuration" last-revision="$Date$">
|
||||
<title>Configuration</title>
|
||||
<para>&Boost.Threads; uses several configuration macros in <boost/config.hpp>,
|
||||
<para>&Boost.Thread; uses several configuration macros in <boost/config.hpp>,
|
||||
as well as configuration macros meant to be supplied by the application. These
|
||||
macros are documented here.
|
||||
</para>
|
||||
<section id="thread.configuration.public">
|
||||
<title>Library Defined Public Macros</title>
|
||||
<para>
|
||||
These macros are defined by &Boost.Threads; but are expected to be used
|
||||
These macros are defined by &Boost.Thread; but are expected to be used
|
||||
by application code.
|
||||
</para>
|
||||
<informaltable>
|
||||
@@ -29,9 +33,9 @@
|
||||
<entry>BOOST_HAS_THREADS</entry>
|
||||
<entry>
|
||||
Indicates that threading support is available. This means both that there
|
||||
is a platform specific implementation for &Boost.Threads; and that
|
||||
is a platform specific implementation for &Boost.Thread; and that
|
||||
threading support has been enabled in a platform specific manner. For instance,
|
||||
on the Win32 platform there's an implementation for &Boost.Threads;
|
||||
on the Win32 platform there's an implementation for &Boost.Thread;
|
||||
but unless the program is compiled against one of the multithreading runtimes
|
||||
(often determined by the compiler predefining the macro _MT) the BOOST_HAS_THREADS
|
||||
macro remains undefined.
|
||||
@@ -44,7 +48,7 @@
|
||||
<section id="thread.configuration.implementation">
|
||||
<title>Library Defined Implementation Macros</title>
|
||||
<para>
|
||||
These macros are defined by &Boost.Threads; and are implementation details
|
||||
These macros are defined by &Boost.Thread; and are implementation details
|
||||
of interest only to implementors.
|
||||
</para>
|
||||
<informaltable>
|
||||
@@ -60,14 +64,14 @@
|
||||
<entry>BOOST_HAS_WINTHREADS</entry>
|
||||
<entry>
|
||||
Indicates that the platform has the Microsoft Win32 threading libraries,
|
||||
and that they should be used to implement &Boost.Threads;.
|
||||
and that they should be used to implement &Boost.Thread;.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>BOOST_HAS_PTHREADS</entry>
|
||||
<entry>
|
||||
Indicates that the platform has the POSIX pthreads libraries, and that
|
||||
they should be used to implement &Boost.Threads;.
|
||||
they should be used to implement &Boost.Thread;.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<section id="threads.design" last-revision="$Date$">
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<section id="thread.design" last-revision="$Date$">
|
||||
<title>Design</title>
|
||||
<para>With client/server and three-tier architectures becoming common place
|
||||
in today's world, it's becoming increasingly important for programs to be
|
||||
@@ -15,18 +19,18 @@
|
||||
Further, these APIs are almost universally C APIs and fail to take
|
||||
advantage of C++'s strengths, or to address concepts unique to C++, such as
|
||||
exceptions.</para>
|
||||
<para>The &Boost.Threads; library is an attempt to define a portable interface
|
||||
<para>The &Boost.Thread; library is an attempt to define a portable interface
|
||||
for writing parallel processes in C++.</para>
|
||||
<section id="threads.design.goals">
|
||||
<section id="thread.design.goals">
|
||||
<title>Goals</title>
|
||||
<para>The &Boost.Threads; library has several goals that should help to set
|
||||
<para>The &Boost.Thread; library has several goals that should help to set
|
||||
it apart from other solutions. These goals are listed in order of precedence
|
||||
with full descriptions below.
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>Portability</term>
|
||||
<listitem>
|
||||
<para>&Boost.Threads; was designed to be highly portable. The goal is
|
||||
<para>&Boost.Thread; was designed to be highly portable. The goal is
|
||||
for the interface to be easily implemented on any platform that
|
||||
supports threads, and possibly even on platforms without native thread
|
||||
support.</para>
|
||||
@@ -35,8 +39,8 @@
|
||||
<varlistentry>
|
||||
<term>Safety</term>
|
||||
<listitem>
|
||||
<para>&Boost.Threads; was designed to be as safe as possible. Writing
|
||||
<link linkend="threads.glossary.thread-safe">thread-safe</link>
|
||||
<para>&Boost.Thread; was designed to be as safe as possible. Writing
|
||||
<link linkend="thread.glossary.thread-safe">thread-safe</link>
|
||||
code is very difficult and successful libraries must strive to
|
||||
insulate the programmer from dangerous constructs as much as
|
||||
possible. This is accomplished in several ways:
|
||||
@@ -45,14 +49,14 @@
|
||||
<para>C++ language features are used to make correct usage easy
|
||||
(if possible) and error-prone usage impossible or at least more
|
||||
difficult. For example, see the <link
|
||||
linkend="threads.concepts.Mutex">Mutex</link> and <link
|
||||
linkend="threads.concepts.Lock">Lock</link> designs, and note
|
||||
linkend="thread.concepts.Mutex">Mutex</link> and <link
|
||||
linkend="thread.concepts.Lock">Lock</link> designs, and note
|
||||
how they interact.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Certain traditional concurrent programming features are
|
||||
considered so error-prone that they are not provided at all. For
|
||||
example, see <xref linkend="threads.rationale.events" />.</para>
|
||||
example, see <xref linkend="thread.rationale.events" />.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Dangerous features, or features which may be misused, are
|
||||
@@ -65,9 +69,9 @@
|
||||
<varlistentry>
|
||||
<term>Flexibility</term>
|
||||
<listitem>
|
||||
<para>&Boost.Threads; was designed to be flexible. This goal is often
|
||||
<para>&Boost.Thread; was designed to be flexible. This goal is often
|
||||
at odds with <emphasis>safety</emphasis>. When functionality might be
|
||||
compromised by the desire to keep the interface safe, &Boost.Threads;
|
||||
compromised by the desire to keep the interface safe, &Boost.Thread;
|
||||
has been designed to provide the functionality, but to make it's use
|
||||
prohibitive for general use. In other words, the interfaces have been
|
||||
designed such that it's usually obvious when something is unsafe, and
|
||||
@@ -77,11 +81,11 @@
|
||||
<varlistentry>
|
||||
<term>Efficiency</term>
|
||||
<listitem>
|
||||
<para>&Boost.Threads; was designed to be as efficient as
|
||||
<para>&Boost.Thread; was designed to be as efficient as
|
||||
possible. When building a library on top of another library there is
|
||||
always a danger that the result will be so much slower than the
|
||||
"native" API that programmers are inclined to ignore the higher level
|
||||
API. &Boost.Threads; was designed to minimize the chances of this
|
||||
API. &Boost.Thread; was designed to minimize the chances of this
|
||||
occurring. The interfaces have been crafted to allow an implementation
|
||||
the greatest chance of being as efficient as possible. This goal is
|
||||
often at odds with the goal for <emphasis>safety</emphasis>. Every
|
||||
@@ -94,18 +98,18 @@
|
||||
</section>
|
||||
<section>
|
||||
<title>Iterative Phases</title>
|
||||
<para>Another goal of &Boost.Threads; was to take a dynamic, iterative
|
||||
<para>Another goal of &Boost.Thread; was to take a dynamic, iterative
|
||||
approach in its development. The computing industry is still exploring the
|
||||
concepts of parallel programming. Most thread libraries supply only simple
|
||||
primitive concepts for thread synchronization. These concepts are very
|
||||
simple, but it is very difficult to use them safely or to provide formal
|
||||
proofs for constructs built on top of them. There has been a lot of research
|
||||
into other concepts, such as in "Communicating Sequential Processes."
|
||||
&Boost.Threads; was designed in iterative steps, with each step providing
|
||||
&Boost.Thread; was designed in iterative steps, with each step providing
|
||||
the building blocks necessary for the next step and giving the researcher
|
||||
the tools necessary to explore new concepts in a portable manner.</para>
|
||||
<para>Given the goal of following a dynamic, iterative approach
|
||||
&Boost.Threads; shall go through several growth cycles. Each phase in its
|
||||
&Boost.Thread; shall go through several growth cycles. Each phase in its
|
||||
development shall be roughly documented here.</para>
|
||||
</section>
|
||||
<section>
|
||||
@@ -119,10 +123,10 @@
|
||||
much help to a programmer who wants to use the library in his multithreaded
|
||||
application. So there's a very great need for portable primitives that will
|
||||
allow the library developer to create <link
|
||||
linkend="threads.glossary.thread-safe">thread-safe</link>
|
||||
linkend="thread.glossary.thread-safe">thread-safe</link>
|
||||
implementations. This need far out weighs the need for portable methods to
|
||||
create and manage threads.</para>
|
||||
<para>Because of this need, the first phase of &Boost.Threads; focuses
|
||||
<para>Because of this need, the first phase of &Boost.Thread; focuses
|
||||
solely on providing portable primitive concepts for thread
|
||||
synchronization. Types provided in this phase include the
|
||||
<classname>boost::mutex</classname>,
|
||||
@@ -135,16 +139,16 @@
|
||||
synchronization primitives, though there are others that will be added in
|
||||
later phases.</para>
|
||||
</section>
|
||||
<section id="threads.design.phase2">
|
||||
<section id="thread.design.phase2">
|
||||
<title>Phase 2, Thread Management and Thread Specific Storage</title>
|
||||
<para>This phase addresses the creation and management of threads and
|
||||
provides a mechanism for thread specific storage (data associated with a
|
||||
thread instance). Thread management is a tricky issue in C++, so this
|
||||
phase addresses only the basic needs of multithreaded program. Later
|
||||
phases are likely to add additional functionality in this area. This
|
||||
phase of &Boost.Threads; adds the <classname>boost::thread</classname> and
|
||||
phase of &Boost.Thread; adds the <classname>boost::thread</classname> and
|
||||
<classname>boost::thread_specific_ptr</classname> types. With these
|
||||
additions the &Boost.Threads; library can be considered minimal but
|
||||
additions the &Boost.Thread; library can be considered minimal but
|
||||
complete.</para>
|
||||
</section>
|
||||
<section>
|
||||
|
||||
@@ -1,26 +1,30 @@
|
||||
<!ENTITY Boost.Threads "<emphasis role='bold'>Boost.Threads</emphasis>">
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<!ENTITY Boost.Thread "<emphasis role='bold'>Boost.Thread</emphasis>">
|
||||
<!ENTITY Boost.Build "<emphasis role='bold'>Boost.Build</emphasis>">
|
||||
<!ENTITY cite.AndrewsSchneider83 "<citation><xref
|
||||
linkend='threads.bib.AndrewsSchneider83'
|
||||
endterm='threads.bib.AndrewsSchneider83.abbrev'/></citation>">
|
||||
<!ENTITY cite.Boost "<citation><xref linkend='threads.bib.Boost'
|
||||
endterm='threads.bib.Boost.abbrev'/></citation>">
|
||||
<!ENTITY cite.Hansen73 "<citation><xref linkend='threads.bib.Hansen73'
|
||||
endterm='threads.bib.Hansen73.abbrev'/></citation>">
|
||||
<!ENTITY cite.Butenhof97 "<citation><xref linkend='threads.bib.Butenhof97'
|
||||
endterm='threads.bib.Butenhof97.abbrev'/></citation>">
|
||||
<!ENTITY cite.Hoare74 "<citation><xref linkend='threads.bib.Hoare74'
|
||||
endterm='threads.bib.Hoare74.abbrev'/></citation>">
|
||||
<!ENTITY cite.ISO98 "<citation><xref linkend='threads.bib.ISO98'
|
||||
endterm='threads.bib.ISO98.abbrev'/></citation>">
|
||||
linkend='thread.bib.AndrewsSchneider83'
|
||||
endterm='thread.bib.AndrewsSchneider83.abbrev'/></citation>">
|
||||
<!ENTITY cite.Boost "<citation><xref linkend='thread.bib.Boost'
|
||||
endterm='thread.bib.Boost.abbrev'/></citation>">
|
||||
<!ENTITY cite.Hansen73 "<citation><xref linkend='thread.bib.Hansen73'
|
||||
endterm='thread.bib.Hansen73.abbrev'/></citation>">
|
||||
<!ENTITY cite.Butenhof97 "<citation><xref linkend='thread.bib.Butenhof97'
|
||||
endterm='thread.bib.Butenhof97.abbrev'/></citation>">
|
||||
<!ENTITY cite.Hoare74 "<citation><xref linkend='thread.bib.Hoare74'
|
||||
endterm='thread.bib.Hoare74.abbrev'/></citation>">
|
||||
<!ENTITY cite.ISO98 "<citation><xref linkend='thread.bib.ISO98'
|
||||
endterm='thread.bib.ISO98.abbrev'/></citation>">
|
||||
<!ENTITY cite.McDowellHelmbold89 "<citation><xref
|
||||
linkend='threads.bib.McDowellHelmbold89'
|
||||
endterm='threads.bib.McDowellHelmbold89.abbrev'/></citation>">
|
||||
linkend='thread.bib.McDowellHelmbold89'
|
||||
endterm='thread.bib.McDowellHelmbold89.abbrev'/></citation>">
|
||||
<!ENTITY cite.SchmidtPyarali "<citation><xref
|
||||
linkend='threads.bib.SchmidtPyarali'
|
||||
endterm='threads.bib.SchmidtPyarali.abbrev'/></citation>">
|
||||
linkend='thread.bib.SchmidtPyarali'
|
||||
endterm='thread.bib.SchmidtPyarali.abbrev'/></citation>">
|
||||
<!ENTITY cite.SchmidtStalRohnertBuschmann "<citation><xref
|
||||
linkend='threads.bib.SchmidtStalRohnertBuschmann'
|
||||
endterm='threads.bib.SchmidtStalRohnertBuschmann.abbrev'/></citation>">
|
||||
<!ENTITY cite.Stroustrup "<citation><xref linkend='threads.bib.Stroustrup'
|
||||
endterm='threads.bib.Stroustrup.abbrev'/></citation>">
|
||||
linkend='thread.bib.SchmidtStalRohnertBuschmann'
|
||||
endterm='thread.bib.SchmidtStalRohnertBuschmann.abbrev'/></citation>">
|
||||
<!ENTITY cite.Stroustrup "<citation><xref linkend='thread.bib.Stroustrup'
|
||||
endterm='thread.bib.Stroustrup.abbrev'/></citation>">
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<header name="boost/thread/exceptions.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
@@ -34,7 +38,7 @@
|
||||
<purpose>
|
||||
<simpara>The <classname>thread_resource_error</classname> class
|
||||
defines an exception type that is thrown by constructors in the
|
||||
&Boost.Threads; library when thread-related resources can not be
|
||||
&Boost.Thread; library when thread-related resources can not be
|
||||
acquired.</simpara>
|
||||
</purpose>
|
||||
|
||||
|
||||
65
doc/faq.xml
65
doc/faq.xml
@@ -1,45 +1,49 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<section id="threads.faq" last-revision="$Date$">
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<section id="thread.faq" last-revision="$Date$">
|
||||
<title>Frequently Asked Questions</title>
|
||||
<qandaset>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Are lock objects <link
|
||||
linkend="threads.glossary.thread-safe">thread safe</link>?</para>
|
||||
linkend="thread.glossary.thread-safe">thread safe</link>?</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para><emphasis role="bold">No!</emphasis> Lock objects are not meant to
|
||||
be shared between threads. They are meant to be short-lived objects
|
||||
created on automatic storage within a code block. Any other usage is
|
||||
just likely to lead to errors and won't really be of actual benefit anyway.
|
||||
Share <link linkend="threads.concepts.mutexes">Mutexes</link>, not
|
||||
Share <link linkend="thread.concepts.mutexes">Mutexes</link>, not
|
||||
Locks. For more information see the <link
|
||||
linkend="threads.rationale.locks">rationale</link> behind the
|
||||
linkend="thread.rationale.locks">rationale</link> behind the
|
||||
design for lock objects.</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Why was &Boost.Threads; modeled after (specific library
|
||||
<para>Why was &Boost.Thread; modeled after (specific library
|
||||
name)?</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>It wasn't. &Boost.Threads; was designed from scratch. Extensive
|
||||
<para>It wasn't. &Boost.Thread; was designed from scratch. Extensive
|
||||
design discussions involved numerous people representing a wide range of
|
||||
experience across many platforms. To ensure portability, the initial
|
||||
implements were done in parallel using POSIX Threads and the Win32
|
||||
threading API. But the &Boost.Threads; design is very much in the spirit
|
||||
threading API. But the &Boost.Thread; design is very much in the spirit
|
||||
of C++, and thus doesn't model such C based APIs.</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Why wasn't &Boost.Threads; modeled after (specific library
|
||||
<para>Why wasn't &Boost.Thread; modeled after (specific library
|
||||
name)?</para>
|
||||
</question>
|
||||
<answer>
|
||||
@@ -54,12 +58,12 @@
|
||||
</qandaentry>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Why do <link linkend="threads.concepts.mutexes">Mutexes</link>
|
||||
<para>Why do <link linkend="thread.concepts.mutexes">Mutexes</link>
|
||||
have noncopyable semantics?</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>To ensure that <link
|
||||
linkend="threads.glossary.deadlock">deadlocks</link> don't occur. The
|
||||
linkend="thread.glossary.deadlock">deadlocks</link> don't occur. The
|
||||
only logical form of copy would be to use some sort of shallow copy
|
||||
semantics in which multiple mutex objects could refer to the same mutex
|
||||
state. This means that if ObjA has a mutex object as part of its state
|
||||
@@ -73,20 +77,20 @@
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>How can you prevent <link
|
||||
linkend="threads.glossary.deadlock">deadlock</link> from occurring when
|
||||
linkend="thread.glossary.deadlock">deadlock</link> from occurring when
|
||||
a thread must lock multiple mutexes?</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>Always lock them in the same order. One easy way of doing this is
|
||||
to use each mutex's address to determine the order in which they are
|
||||
locked. A future &Boost.Threads; concept may wrap this pattern up in a
|
||||
locked. A future &Boost.Thread; concept may wrap this pattern up in a
|
||||
reusable class.</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Don't noncopyable <link
|
||||
linkend="threads.concepts.mutexes">Mutex</link> semantics mean that a
|
||||
linkend="thread.concepts.mutexes">Mutex</link> semantics mean that a
|
||||
class with a mutex member will be noncopyable as well?</para>
|
||||
</question>
|
||||
<answer>
|
||||
@@ -94,7 +98,7 @@
|
||||
copy constructor and assignment operator, so they will have to be coded
|
||||
explicitly. This is a <emphasis role="bold">good thing</emphasis>,
|
||||
however, since the compiler generated operations would not be <link
|
||||
linkend="threads.glossary.thread-safe">thread-safe</link>. The following
|
||||
linkend="thread.glossary.thread-safe">thread-safe</link>. The following
|
||||
is a simple example of a class with copyable semantics and internal
|
||||
synchronization through a mutex member.</para>
|
||||
<programlisting>
|
||||
@@ -144,7 +148,7 @@ private:
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>How can you lock a <link
|
||||
linkend="threads.concepts.mutexes">Mutex</link> member in a const member
|
||||
linkend="thread.concepts.mutexes">Mutex</link> member in a const member
|
||||
function, in order to implement the Monitor Pattern?</para>
|
||||
</question>
|
||||
<answer>
|
||||
@@ -165,8 +169,8 @@ private:
|
||||
</question>
|
||||
<answer>
|
||||
<para>Condition variables result in user code much less prone to <link
|
||||
linkend="threads.glossary.race-condition">race conditions</link> than
|
||||
event variables. See <xref linkend="threads.rationale.events" />
|
||||
linkend="thread.glossary.race-condition">race conditions</link> than
|
||||
event variables. See <xref linkend="thread.rationale.events" />
|
||||
for analysis. Also see &cite.Hoare74; and &cite.SchmidtStalRohnertBuschmann;.
|
||||
</para>
|
||||
</answer>
|
||||
@@ -177,7 +181,7 @@ private:
|
||||
</question>
|
||||
<answer>
|
||||
<para>There's a valid need for thread termination, so at some point
|
||||
&Boost.Threads; probably will include it, but only after we can find a
|
||||
&Boost.Thread; probably will include it, but only after we can find a
|
||||
truly safe (and portable) mechanism for this concept.</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
@@ -206,5 +210,26 @@ private:
|
||||
condition variable.</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Why doesn't the thread's ctor take at least a void* to pass any
|
||||
information along with the function? All other threading libs support
|
||||
that and it makes Boost.Threads inferiour. </para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>There is no need, because Boost.Threads are superiour! First
|
||||
thing is that its ctor doesn't take a function but a functor. That
|
||||
means that you can pass an object with an overloaded operator() and
|
||||
include additional data as members in that object. Beware though that
|
||||
this object is copied, use boost::ref to prevent that. Secondly, even
|
||||
a boost::function<void (void)> can carry parameters, you only have to
|
||||
use boost::bind() to create it from any function and bind its
|
||||
parameters.</para>
|
||||
<para>That is also why Boost.Threads are superiour, because they
|
||||
don't require you to pass a type-unsafe void pointer. Rather, you can
|
||||
use the flexible Boost.Functions to create a thread entry out of
|
||||
anything that can be called.</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
</qandaset>
|
||||
</section>
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<glossary id="threads.glossary" last-revision="$Date$">
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<glossary id="thread.glossary" last-revision="$Date$">
|
||||
<title>Glossary</title>
|
||||
<para>Definitions are given in terms of the C++ Standard
|
||||
&cite.ISO98;. References to the standard are in the form [1.2.3/4], which
|
||||
@@ -12,9 +16,9 @@
|
||||
"/".</para>
|
||||
<para>Because the definitions are written in something akin to "standardese",
|
||||
they can be difficult to understand. The intent isn't to confuse, but rather
|
||||
to clarify the additional requirements &Boost.Threads; places on a C++
|
||||
to clarify the additional requirements &Boost.Thread; places on a C++
|
||||
implementation as defined by the C++ Standard.</para>
|
||||
<glossentry id="threads.glossary.thread">
|
||||
<glossentry id="thread.glossary.thread">
|
||||
<glossterm>Thread</glossterm>
|
||||
<glossdef>
|
||||
<para>Thread is short for "thread of execution". A thread of execution is
|
||||
@@ -50,13 +54,13 @@
|
||||
</itemizedlist>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="threads.glossary.thread-safe">
|
||||
<glossentry id="thread.glossary.thread-safe">
|
||||
<glossterm>Thread-safe</glossterm>
|
||||
<glossdef>
|
||||
<para>A program is thread-safe if it has no <link
|
||||
linkend="threads.glossary.race-condition">race conditions</link>, does
|
||||
not <link linkend="threads.glossary.deadlock">deadlock</link>, and has
|
||||
no <link linkend="threads.glossary.priority-failure">priority
|
||||
linkend="thread.glossary.race-condition">race conditions</link>, does
|
||||
not <link linkend="thread.glossary.deadlock">deadlock</link>, and has
|
||||
no <link linkend="thread.glossary.priority-failure">priority
|
||||
failures</link>.</para>
|
||||
<para>Note that thread-safety does not necessarily imply efficiency, and
|
||||
than while some thread-safety violations can be determined statically at
|
||||
@@ -64,7 +68,7 @@
|
||||
runtime.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="threads.glossary.thread-state">
|
||||
<glossentry id="thread.glossary.thread-state">
|
||||
<glossterm>Thread State</glossterm>
|
||||
<glossdef>
|
||||
<para>During the lifetime of a thread, it shall be in one of the following
|
||||
@@ -166,7 +170,7 @@
|
||||
above table.]</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="threads.glossary.race-condition">
|
||||
<glossentry id="thread.glossary.race-condition">
|
||||
<glossterm>Race Condition</glossterm>
|
||||
<glossdef>
|
||||
<para>A race condition is what occurs when multiple threads read from and write
|
||||
@@ -175,10 +179,10 @@
|
||||
pattern which isn't even a valid value for the data type. A race condition
|
||||
results in undefined behavior [1.3.12].</para>
|
||||
<para>Race conditions can be prevented by serializing memory access using
|
||||
the tools provided by &Boost.Threads;.</para>
|
||||
the tools provided by &Boost.Thread;.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="threads.glossary.deadlock">
|
||||
<glossentry id="thread.glossary.deadlock">
|
||||
<glossterm>Deadlock</glossterm>
|
||||
<glossdef>
|
||||
<para>Deadlock is an execution state where for some set of threads, each
|
||||
@@ -187,14 +191,14 @@
|
||||
become ready again.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="threads.glossary.starvation">
|
||||
<glossentry id="thread.glossary.starvation">
|
||||
<glossterm>Starvation</glossterm>
|
||||
<glossdef>
|
||||
<para>The condition in which a thread is not making sufficient progress in
|
||||
its work during a given time interval.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="threads.glossary.priority-failure">
|
||||
<glossentry id="thread.glossary.priority-failure">
|
||||
<glossterm>Priority Failure</glossterm>
|
||||
<glossdef>
|
||||
<para>A priority failure (such as priority inversion or infinite overtaking)
|
||||
@@ -202,10 +206,10 @@
|
||||
performed in time to be useful.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="threads.glossary.undefined-behavior">
|
||||
<glossentry id="thread.glossary.undefined-behavior">
|
||||
<glossterm>Undefined Behavior</glossterm>
|
||||
<glossdef>
|
||||
<para>The result of certain operations in &Boost.Threads; is undefined;
|
||||
<para>The result of certain operations in &Boost.Thread; is undefined;
|
||||
this means that those operations can invoke almost any behavior when
|
||||
they are executed.</para>
|
||||
|
||||
@@ -220,7 +224,7 @@
|
||||
programming error.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="threads.glossary.memory-visibility">
|
||||
<glossentry id="thread.glossary.memory-visibility">
|
||||
<glossterm>Memory Visibility</glossterm>
|
||||
<glossdef>
|
||||
<para>An address [1.7] shall always point to the same memory byte,
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<section id="threads.implementation_notes" last-revision="$Date$">
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<section id="thread.implementation_notes" last-revision="$Date$">
|
||||
<title>Implementation Notes</title>
|
||||
<section id="threads.implementation_notes.win32">
|
||||
<section id="thread.implementation_notes.win32">
|
||||
<title>Win32</title>
|
||||
<para>
|
||||
In the current Win32 implementation, creating a boost::thread object
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
<!-- Copyright (c) 2002-2003 Beman Dawes, William E. Kempf.
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=../../../doc/html/threads.html">
|
||||
<meta http-equiv="refresh" content="0; URL=../../../doc/html/thread.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to <a href="../../../doc/html/threads.html">../../../doc/html/threads.html</a>
|
||||
Automatic redirection failed, please go to <a href="../../../doc/html/thread.html">../../../doc/html/thread.html</a>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,35 +1,39 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<header name="boost/thread/mutex.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
<class name="mutex">
|
||||
<purpose>
|
||||
<para>The <classname>mutex</classname> class is a model of the
|
||||
<link linkend="threads.concepts.Mutex">Mutex</link> concept.</para>
|
||||
<link linkend="thread.concepts.Mutex">Mutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>mutex</classname> class is a model of the
|
||||
<link linkend="threads.concepts.Mutex">Mutex</link> concept.
|
||||
<link linkend="thread.concepts.Mutex">Mutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking mechanics.</para>
|
||||
|
||||
<para>For classes that model related mutex concepts, see
|
||||
<classname>try_mutex</classname> and <classname>timed_mutex</classname>.</para>
|
||||
|
||||
<para>For <link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
|
||||
<para>For <link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
|
||||
locking mechanics, see <classname>recursive_mutex</classname>,
|
||||
<classname>recursive_try_mutex</classname>, and <classname>recursive_timed_mutex</classname>.
|
||||
</para>
|
||||
|
||||
<para>The <classname>mutex</classname> class supplies the following typedef,
|
||||
which <link linkend="threads.concepts.lock-models">models</link>
|
||||
which <link linkend="thread.concepts.lock-models">models</link>
|
||||
the specified locking strategy:
|
||||
|
||||
<informaltable>
|
||||
@@ -43,7 +47,7 @@
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -51,7 +55,7 @@
|
||||
</para>
|
||||
|
||||
<para>The <classname>mutex</classname> class uses an
|
||||
<link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking strategy, so attempts to recursively lock a <classname>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>.
|
||||
@@ -61,10 +65,10 @@
|
||||
<code>NDEBUG</code> is not defined.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="threads.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Threads;, <classname>mutex</classname> leaves the
|
||||
<link linkend="threads.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
<link linkend="thread.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Thread;, <classname>mutex</classname> leaves the
|
||||
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
Programmers should make no assumptions about the order in which
|
||||
waiting threads acquire a lock.</para>
|
||||
</description>
|
||||
@@ -100,26 +104,26 @@
|
||||
<class name="try_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>try_mutex</classname> class is a model of the
|
||||
<link linkend="threads.concepts.TryMutex">TryMutex</link> concept.</para>
|
||||
<link linkend="thread.concepts.TryMutex">TryMutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>try_mutex</classname> class is a model of the
|
||||
<link linkend="threads.concepts.TryMutex">TryMutex</link> concept.
|
||||
<link linkend="thread.concepts.TryMutex">TryMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking mechanics.</para>
|
||||
|
||||
<para>For classes that model related mutex concepts, see
|
||||
<classname>mutex</classname> and <classname>timed_mutex</classname>.</para>
|
||||
|
||||
<para>For <link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
|
||||
<para>For <link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
|
||||
locking mechanics, see <classname>recursive_mutex</classname>,
|
||||
<classname>recursive_try_mutex</classname>, and <classname>recursive_timed_mutex</classname>.
|
||||
</para>
|
||||
|
||||
<para>The <classname>try_mutex</classname> class supplies the following typedefs,
|
||||
which <link linkend="threads.concepts.lock-models">model</link>
|
||||
which <link linkend="thread.concepts.lock-models">model</link>
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
@@ -133,11 +137,11 @@
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -145,7 +149,7 @@
|
||||
</para>
|
||||
|
||||
<para>The <classname>try_mutex</classname> class uses an
|
||||
<link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking strategy, so attempts to recursively lock a <classname>try_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>.
|
||||
@@ -155,10 +159,10 @@
|
||||
<code>NDEBUG</code> is not defined.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="threads.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Threads;, <classname>try_mutex</classname> leaves the
|
||||
<link linkend="threads.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
<link linkend="thread.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Thread;, <classname>try_mutex</classname> leaves the
|
||||
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
Programmers should make no assumptions about the order in which
|
||||
waiting threads acquire a lock.</para>
|
||||
</description>
|
||||
@@ -199,26 +203,26 @@
|
||||
<class name="timed_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>timed_mutex</classname> class is a model of the
|
||||
<link linkend="threads.concepts.TimedMutex">TimedMutex</link> concept.</para>
|
||||
<link linkend="thread.concepts.TimedMutex">TimedMutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>timed_mutex</classname> class is a model of the
|
||||
<link linkend="threads.concepts.TimedMutex">TimedMutex</link> concept.
|
||||
<link linkend="thread.concepts.TimedMutex">TimedMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking mechanics.</para>
|
||||
|
||||
<para>For classes that model related mutex concepts, see
|
||||
<classname>mutex</classname> and <classname>try_mutex</classname>.</para>
|
||||
|
||||
<para>For <link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
|
||||
<para>For <link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
|
||||
locking mechanics, see <classname>recursive_mutex</classname>,
|
||||
<classname>recursive_try_mutex</classname>, and <classname>recursive_timed_mutex</classname>.
|
||||
</para>
|
||||
|
||||
<para>The <classname>timed_mutex</classname> class supplies the following typedefs,
|
||||
which <link linkend="threads.concepts.lock-models">model</link>
|
||||
which <link linkend="thread.concepts.lock-models">model</link>
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
@@ -232,15 +236,15 @@
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -248,7 +252,7 @@
|
||||
</para>
|
||||
|
||||
<para>The <classname>timed_mutex</classname> class uses an
|
||||
<link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking strategy, so attempts to recursively lock a <classname>timed_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>.
|
||||
@@ -258,10 +262,10 @@
|
||||
<code>NDEBUG</code> is not defined.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="threads.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Threads;, <classname>timed_mutex</classname> leaves the
|
||||
<link linkend="threads.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
<link linkend="thread.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Thread;, <classname>timed_mutex</classname> leaves the
|
||||
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
Programmers should make no assumptions about the order in which
|
||||
waiting threads acquire a lock.</para>
|
||||
</description>
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<header name="boost/thread/once.hpp"
|
||||
last-revision="$Date$">
|
||||
<macro name="BOOST_ONCE_INIT">
|
||||
@@ -11,7 +15,7 @@
|
||||
<code>once_flag</code> type (statically initialized to
|
||||
<macroname>BOOST_ONCE_INIT</macroname>) can be used to run a
|
||||
routine exactly once. This can be used to initialize data in a
|
||||
<link linkend="threads.glossary.thread-safe">thread-safe</link>
|
||||
<link linkend="thread.glossary.thread-safe">thread-safe</link>
|
||||
manner.</purpose>
|
||||
|
||||
<description>The implementation-defined macro
|
||||
@@ -27,7 +31,7 @@
|
||||
<code>once_flag</code> type (statically initialized to
|
||||
<macroname>BOOST_ONCE_INIT</macroname>) can be used to run a
|
||||
routine exactly once. This can be used to initialize data in a
|
||||
<link linkend="threads.glossary.thread-safe">thread-safe</link>
|
||||
<link linkend="thread.glossary.thread-safe">thread-safe</link>
|
||||
manner.</purpose>
|
||||
|
||||
<description>The implementation-defined type <code>once_flag</code>
|
||||
@@ -45,7 +49,7 @@
|
||||
<code>once_flag</code> type (statically initialized to
|
||||
<macroname>BOOST_ONCE_INIT</macroname>) can be used to run a
|
||||
routine exactly once. This can be used to initialize data in a
|
||||
<link linkend="threads.glossary.thread-safe">thread-safe</link>
|
||||
<link linkend="thread.glossary.thread-safe">thread-safe</link>
|
||||
manner.</purpose>
|
||||
|
||||
<description>
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<section id="threads.overview" last-revision="$Date$">
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<section id="thread.overview" last-revision="$Date$">
|
||||
<title>Overview</title>
|
||||
<section id="threads.introduction">
|
||||
<section id="thread.introduction">
|
||||
<title>Introduction</title>
|
||||
<para>&Boost.Threads; allows C++ programs to execute as multiple,
|
||||
<para>&Boost.Thread; allows C++ programs to execute as multiple,
|
||||
asynchronous, independent threads-of-execution. Each thread has its own
|
||||
machine state including program instruction counter and registers. Programs
|
||||
which execute as multiple threads are called multithreaded programs to
|
||||
distinguish them from traditional single-threaded programs. The <link
|
||||
linkend="threads.glossary">glossary</link> gives a more complete description
|
||||
linkend="thread.glossary">glossary</link> gives a more complete description
|
||||
of the multithreading execution environment.</para>
|
||||
<para>Multithreading provides several advantages:
|
||||
<itemizedlist>
|
||||
@@ -44,15 +48,15 @@
|
||||
multithreaded programs are subject to additional errors:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><link linkend="threads.glossary.race-condition">Race
|
||||
<para><link linkend="thread.glossary.race-condition">Race
|
||||
conditions</link></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><link linkend="threads.glossary.deadlock">Deadlock</link>
|
||||
<para><link linkend="thread.glossary.deadlock">Deadlock</link>
|
||||
(sometimes called "deadly embrace")</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><link linkend="threads.glossary.priority-failure">Priority
|
||||
<para><link linkend="thread.glossary.priority-failure">Priority
|
||||
failures</link> (priority inversion, infinite overtaking, starvation,
|
||||
etc.)</para>
|
||||
</listitem>
|
||||
@@ -61,10 +65,10 @@
|
||||
errors. These aren't rare or exotic failures - they are virtually guaranteed
|
||||
to occur unless multithreaded code is designed to avoid them. Priority
|
||||
failures are somewhat less common, but are nonetheless serious.</para>
|
||||
<para>The <link linkend="threads.design">&Boost.Threads; design</link>
|
||||
<para>The <link linkend="thread.design">&Boost.Thread; design</link>
|
||||
attempts to minimize these errors, but they will still occur unless the
|
||||
programmer proactively designs to avoid them.</para>
|
||||
<note>Please also see <xref linkend="threads.implementation_notes"/>
|
||||
<note>Please also see <xref linkend="thread.implementation_notes"/>
|
||||
for additional, implementation-specific considerations.</note>
|
||||
</section>
|
||||
<section>
|
||||
@@ -119,11 +123,11 @@
|
||||
<title>Runtime libraries</title>
|
||||
<para>
|
||||
<emphasis role="bold">Warning:</emphasis> Multithreaded programs such as
|
||||
those using &Boost.Threads; must link to <link
|
||||
linkend="threads.glossary.thread-safe">thread-safe</link> versions of
|
||||
those using &Boost.Thread; must link to <link
|
||||
linkend="thread.glossary.thread-safe">thread-safe</link> versions of
|
||||
all runtime libraries used by the program, including the runtime library
|
||||
for the C++ Standard Library. Failure to do so will cause <link
|
||||
linkend="threads.glossary.race-condition">race conditions</link> to occur
|
||||
linkend="thread.glossary.race-condition">race conditions</link> to occur
|
||||
when multiple threads simultaneously execute runtime library functions for
|
||||
<code>new</code>, <code>delete</code>, or other language features which
|
||||
imply shared state.</para>
|
||||
@@ -169,15 +173,15 @@
|
||||
</section>
|
||||
</section>
|
||||
<section>
|
||||
<title>Common guarantees for all &Boost.Threads; components</title>
|
||||
<title>Common guarantees for all &Boost.Thread; components</title>
|
||||
<section>
|
||||
<title>Exceptions</title>
|
||||
<para>&Boost.Threads; destructors never
|
||||
<para>&Boost.Thread; destructors never
|
||||
throw exceptions. Unless otherwise specified, other
|
||||
&Boost.Threads; functions that do not have
|
||||
&Boost.Thread; functions that do not have
|
||||
an exception-specification may throw implementation-defined
|
||||
exceptions.</para>
|
||||
<para>In particular, &Boost.Threads;
|
||||
<para>In particular, &Boost.Thread;
|
||||
reports failure to allocate storage by throwing an exception of type
|
||||
<code>std::bad_alloc</code> or a class derived from
|
||||
<code>std::bad_alloc</code>, failure to obtain thread resources other than
|
||||
@@ -191,7 +195,7 @@
|
||||
</section>
|
||||
<section>
|
||||
<title>NonCopyable requirement</title>
|
||||
<para>&Boost.Threads; classes documented as
|
||||
<para>&Boost.Thread; classes documented as
|
||||
meeting the NonCopyable requirement disallow copy construction and copy
|
||||
assignment. For the sake of exposition, the synopsis of such classes show
|
||||
private derivation from <classname>boost::noncopyable</classname>. Users
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<section id="threads.rationale" last-revision="$Date$">
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<section id="thread.rationale" last-revision="$Date$">
|
||||
<title>Rationale</title>
|
||||
<para>This page explains the rationale behind various design decisions in the
|
||||
&Boost.Threads; library. Having the rationale documented here should explain
|
||||
&Boost.Thread; library. Having the rationale documented here should explain
|
||||
how we arrived at the current design as well as prevent future rehashing of
|
||||
discussions and thought processes that have already occurred. It can also give
|
||||
users a lot of insight into the design process required for this
|
||||
library.</para>
|
||||
<section id="threads.rationale.Boost.Threads">
|
||||
<title>Rationale for the Creation of &Boost.Threads;</title>
|
||||
<section id="thread.rationale.Boost.Thread">
|
||||
<title>Rationale for the Creation of &Boost.Thread;</title>
|
||||
<para>Processes often have a degree of "potential parallelism" and it can
|
||||
often be more intuitive to design systems with this in mind. Further, these
|
||||
parallel processes can result in more responsive programs. The benefits for
|
||||
@@ -33,24 +37,24 @@
|
||||
<para>What's truly needed is C++ language support for threads. However, the
|
||||
C++ standards committee needs existing practice or a good proposal as a
|
||||
starting point for adding this to the standard.</para>
|
||||
<para>The &Boost.Threads; library was developed to provide a C++ developer
|
||||
<para>The &Boost.Thread; library was developed to provide a C++ developer
|
||||
with a portable interface for writing multithreaded programs on numerous
|
||||
platforms. There's a hope that the library can be the basis for a more
|
||||
detailed proposal for the C++ standards committee to consider for inclusion
|
||||
in the next C++ standard.</para>
|
||||
</section>
|
||||
<section id="threads.rationale.primitives">
|
||||
<title>Rationale for the Low Level Primitives Supported in &Boost.Threads;</title>
|
||||
<para>The &Boost.Threads; library supplies a set of low level primitives for
|
||||
<section id="thread.rationale.primitives">
|
||||
<title>Rationale for the Low Level Primitives Supported in &Boost.Thread;</title>
|
||||
<para>The &Boost.Thread; library supplies a set of low level primitives for
|
||||
writing multithreaded programs, such as mutexes and condition variables. In
|
||||
fact, the first release of &Boost.Threads; supports only these low level
|
||||
fact, the first release of &Boost.Thread; supports only these low level
|
||||
primitives. However, computer science research has shown that use of these
|
||||
primitives is difficult since it's difficult to mathematically prove that a
|
||||
usage pattern is correct, meaning it doesn't result in race conditions or
|
||||
deadlocks. There are several algebras (such as CSP, CCS and Join calculus)
|
||||
that have been developed to help write provably correct parallel
|
||||
processes. In order to prove the correctness these processes must be coded
|
||||
using higher level abstractions. So why does &Boost.Threads; support the
|
||||
using higher level abstractions. So why does &Boost.Thread; support the
|
||||
lower level concepts?</para>
|
||||
<para>The reason is simple: the higher level concepts need to be implemented
|
||||
using at least some of the lower level concepts. So having portable lower
|
||||
@@ -64,11 +68,11 @@
|
||||
level concepts, supporting the lower level concepts provides
|
||||
greater accessibility.</para>
|
||||
</section>
|
||||
<section id="threads.rationale.locks">
|
||||
<section id="thread.rationale.locks">
|
||||
<title>Rationale for the Lock Design</title>
|
||||
<para>Programmers who are used to multithreaded programming issues will
|
||||
quickly note that the &Boost.Threads; design for mutex lock concepts is not
|
||||
<link linkend="threads.glossary.thread-safe">thread-safe</link> (this is
|
||||
quickly note that the &Boost.Thread; design for mutex lock concepts is not
|
||||
<link linkend="thread.glossary.thread-safe">thread-safe</link> (this is
|
||||
clearly documented as well). At first this may seem like a serious design
|
||||
flaw. Why have a multithreading primitive that's not thread-safe
|
||||
itself?</para>
|
||||
@@ -91,17 +95,17 @@
|
||||
since checking the state can occur only by a call after construction, we'd
|
||||
have a race condition if the lock object were shared between threads.</para>
|
||||
<para>So, to avoid the overhead of synchronizing access to the state
|
||||
information and to avoid the race condition, the &Boost.Threads; library
|
||||
information and to avoid the race condition, the &Boost.Thread; library
|
||||
simply does nothing to make lock objects thread-safe. Instead, sharing a
|
||||
lock object between threads results in undefined behavior. Since the only
|
||||
proper usage of lock objects is within block scope this isn't a problem, and
|
||||
so long as the lock object is properly used there's no danger of any
|
||||
multithreading issues.</para>
|
||||
</section>
|
||||
<section id="threads.rationale.non-copyable">
|
||||
<section id="thread.rationale.non-copyable">
|
||||
<title>Rationale for NonCopyable Thread Type</title>
|
||||
<para>Programmers who are used to C libraries for multithreaded programming
|
||||
are likely to wonder why &Boost.Threads; uses a noncopyable design for
|
||||
are likely to wonder why &Boost.Thread; uses a noncopyable design for
|
||||
<classname>boost::thread</classname>. After all, the C thread types are
|
||||
copyable, and you often have a need for copying them within user
|
||||
code. However, careful comparison of C designs to C++ designs shows a flaw
|
||||
@@ -137,7 +141,7 @@
|
||||
appear to bear them out. To illustrate the analysis we'll first provide
|
||||
pseudo-code illustrating the six typical usage patterns of a thread
|
||||
object.</para>
|
||||
<section id="threads.rationale.non-copyable.simple">
|
||||
<section id="thread.rationale.non-copyable.simple">
|
||||
<title>1. Use case: Simple creation of a thread.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -146,7 +150,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="threads.rationale.non-copyable.joined">
|
||||
<section id="thread.rationale.non-copyable.joined">
|
||||
<title>2. Use case: Creation of a thread that's later joined.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -156,7 +160,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="threads.rationale.non-copyable.loop">
|
||||
<section id="thread.rationale.non-copyable.loop">
|
||||
<title>3. Use case: Simple creation of several threads in a loop.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -166,7 +170,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="threads.rationale.non-copyable.loop-join">
|
||||
<section id="thread.rationale.non-copyable.loop-join">
|
||||
<title>4. Use case: Creation of several threads in a loop which are later joined.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -178,7 +182,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="threads.rationale.non-copyable.pass">
|
||||
<section id="thread.rationale.non-copyable.pass">
|
||||
<title>5. Use case: Creation of a thread whose ownership is passed to another object/method.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -188,7 +192,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="threads.rationale.non-copyable.shared">
|
||||
<section id="thread.rationale.non-copyable.shared">
|
||||
<title>6. Use case: Creation of a thread whose ownership is shared between multiple
|
||||
objects.</title>
|
||||
<programlisting>
|
||||
@@ -221,7 +225,7 @@
|
||||
use a concept for any of the usage patterns there would be a good argument
|
||||
for choosing the other design. So we'll code all six usage patterns using
|
||||
both designs.</para>
|
||||
<section id="threads.rationale_comparison.non-copyable.simple">
|
||||
<section id="thread.rationale_comparison.non-copyable.simple">
|
||||
<title>1. Comparison: simple creation of a thread.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -234,7 +238,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="threads.rationale_comparison.non-copyable.joined">
|
||||
<section id="thread.rationale_comparison.non-copyable.joined">
|
||||
<title>2. Comparison: creation of a thread that's later joined.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -249,7 +253,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="threads.rationale_comparison.non-copyable.loop">
|
||||
<section id="thread.rationale_comparison.non-copyable.loop">
|
||||
<title>3. Comparison: simple creation of several threads in a loop.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -264,7 +268,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="threads.rationale_comparison.non-copyable.loop-join">
|
||||
<section id="thread.rationale_comparison.non-copyable.loop-join">
|
||||
<title>4. Comparison: creation of several threads in a loop which are later joined.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -285,7 +289,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="threads.rationale_comparison.non-copyable.pass">
|
||||
<section id="thread.rationale_comparison.non-copyable.pass">
|
||||
<title>5. Comparison: creation of a thread whose ownership is passed to another object/method.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -300,7 +304,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="threads.rationale_comparison.non-copyable.shared">
|
||||
<section id="thread.rationale_comparison.non-copyable.shared">
|
||||
<title>6. Comparison: creation of a thread whose ownership is shared
|
||||
between multiple objects.</title>
|
||||
<programlisting>
|
||||
@@ -321,18 +325,18 @@
|
||||
<para>This shows the usage patterns being nearly identical in complexity for
|
||||
both designs. The only actual added complexity occurs because of the use of
|
||||
operator new in
|
||||
<link linkend="threads.rationale_comparison.non-copyable.loop-join">(4)</link>,
|
||||
<link linkend="threads.rationale_comparison.non-copyable.pass">(5)</link>, and
|
||||
<link linkend="threads.rationale_comparison.non-copyable.shared">(6)</link>;
|
||||
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>,
|
||||
<link linkend="thread.rationale_comparison.non-copyable.pass">(5)</link>, and
|
||||
<link linkend="thread.rationale_comparison.non-copyable.shared">(6)</link>;
|
||||
and the use of std::auto_ptr and boost::shared_ptr in
|
||||
<link linkend="threads.rationale_comparison.non-copyable.loop-join">(4)</link> and
|
||||
<link linkend="threads.rationale_comparison.non-copyable.shared">(6)</link>
|
||||
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link> and
|
||||
<link linkend="thread.rationale_comparison.non-copyable.shared">(6)</link>
|
||||
respectively. However, that's not really
|
||||
much added complexity, and C++ programmers are used to using these idioms
|
||||
anyway. Some may dislike the presence of operator new in user code, but
|
||||
this can be eliminated by proper design of higher level concepts, such as
|
||||
the boost::thread_group class that simplifies example
|
||||
<link linkend="threads.rationale_comparison.non-copyable.loop-join">(4)</link>
|
||||
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>
|
||||
down to:</para>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -347,49 +351,49 @@
|
||||
design.</para>
|
||||
<para>So what about performance? Looking at the above code examples,
|
||||
we can analyze the theoretical impact to performance that both designs
|
||||
have. For <link linkend="threads.rationale_comparison.non-copyable.simple">(1)</link>
|
||||
have. For <link linkend="thread.rationale_comparison.non-copyable.simple">(1)</link>
|
||||
we can see that platforms that don't have a ref-counted native
|
||||
thread type (POSIX, for instance) will be impacted by a thread_ref
|
||||
design. Even if the native thread type is ref-counted there may be an impact
|
||||
if more state information has to be maintained for concepts foreign to the
|
||||
native API, such as clean up stacks for Win32 implementations.
|
||||
For <link linkend="threads.rationale_comparison.non-copyable.joined">(2)</link>
|
||||
and <link linkend="threads.rationale_comparison.non-copyable.loop">(3)</link>
|
||||
For <link linkend="thread.rationale_comparison.non-copyable.joined">(2)</link>
|
||||
and <link linkend="thread.rationale_comparison.non-copyable.loop">(3)</link>
|
||||
the performance impact will be identical to
|
||||
<link linkend="threads.rationale_comparison.non-copyable.simple">(1)</link>.
|
||||
For <link linkend="threads.rationale_comparison.non-copyable.loop-join">(4)</link>
|
||||
<link linkend="thread.rationale_comparison.non-copyable.simple">(1)</link>.
|
||||
For <link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>
|
||||
things get a little more interesting and we find that theoretically at least
|
||||
the thread_ref may perform faster since the thread design requires dynamic
|
||||
memory allocation/deallocation. However, in practice there may be dynamic
|
||||
allocation for the thread_ref design as well, it will just be hidden from
|
||||
the user. As long as the implementation has to do dynamic allocations the
|
||||
thread_ref loses again because of the reference management. For
|
||||
<link linkend="threads.rationale_comparison.non-copyable.pass">(5)</link> we see
|
||||
<link linkend="thread.rationale_comparison.non-copyable.pass">(5)</link> we see
|
||||
the same impact as we do for
|
||||
<link linkend="threads.rationale_comparison.non-copyable.loop-join">(4)</link>.
|
||||
For <link linkend="threads.rationale_comparison.non-copyable.shared">(6)</link>
|
||||
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>.
|
||||
For <link linkend="thread.rationale_comparison.non-copyable.shared">(6)</link>
|
||||
we still have a possible impact to
|
||||
the thread design because of dynamic allocation but thread_ref no longer
|
||||
suffers because of its reference management, and in fact, theoretically at
|
||||
least, the thread_ref may do a better job of managing the references. All of
|
||||
this indicates that thread wins for
|
||||
<link linkend="threads.rationale_comparison.non-copyable.simple">(1)</link>,
|
||||
<link linkend="threads.rationale_comparison.non-copyable.joined">(2)</link> and
|
||||
<link linkend="threads.rationale_comparison.non-copyable.loop">(3)</link>; with
|
||||
<link linkend="threads.rationale_comparison.non-copyable.loop-join">(4)</link>
|
||||
and <link linkend="threads.rationale_comparison.non-copyable.pass">(5)</link> the
|
||||
<link linkend="thread.rationale_comparison.non-copyable.simple">(1)</link>,
|
||||
<link linkend="thread.rationale_comparison.non-copyable.joined">(2)</link> and
|
||||
<link linkend="thread.rationale_comparison.non-copyable.loop">(3)</link>; with
|
||||
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>
|
||||
and <link linkend="thread.rationale_comparison.non-copyable.pass">(5)</link> the
|
||||
winner depending on the implementation and the platform but with the thread design
|
||||
probably having a better chance; and with
|
||||
<link linkend="threads.rationale_comparison.non-copyable.shared">(6)</link>
|
||||
<link linkend="thread.rationale_comparison.non-copyable.shared">(6)</link>
|
||||
it will again depend on the
|
||||
implementation and platform but this time we favor thread_ref
|
||||
slightly. Given all of this it's a narrow margin, but the thread design
|
||||
prevails.</para>
|
||||
<para>Given this analysis, and the fact that noncopyable objects for system
|
||||
resources are the normal designs that C++ programmers are used to dealing
|
||||
with, the &Boost.Threads; library has gone with a noncopyable design.</para>
|
||||
with, the &Boost.Thread; library has gone with a noncopyable design.</para>
|
||||
</section>
|
||||
<section id="threads.rationale.events">
|
||||
<section id="thread.rationale.events">
|
||||
<title>Rationale for not providing <emphasis>Event Variables</emphasis></title>
|
||||
<para><emphasis>Event variables</emphasis> are simply far too
|
||||
error-prone. <classname>boost::condition</classname> variables are a much safer
|
||||
@@ -416,13 +420,13 @@
|
||||
experiences caused them to be very careful in their use of event
|
||||
variables. Overt problems can be avoided, for example, by teaming the event
|
||||
variable with a mutex, but that may just convert a <link
|
||||
linkend="threads.glossary.race-condition">race condition</link> into another
|
||||
linkend="thread.glossary.race-condition">race condition</link> into another
|
||||
problem, such as excessive resource use. One of the most distressing aspects
|
||||
of the experience reports is the claim that many defects are latent. That
|
||||
is, the programs appear to work correctly, but contain hidden timing
|
||||
dependencies which will cause them to fail when environmental factors or
|
||||
usage patterns change, altering relative thread timings.</para>
|
||||
<para>The decision to exclude event variables from &Boost.Threads; has been
|
||||
<para>The decision to exclude event variables from &Boost.Thread; has been
|
||||
surprising to some Windows programmers. They have written programs which
|
||||
work using event variables, and wonder what the problem is. It seems similar
|
||||
to the "goto considered harmful" controversy of 30 years ago. It isn't that
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<header name="boost/thread/read_write_mutex.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
@@ -16,13 +20,13 @@
|
||||
|
||||
<purpose>
|
||||
<para>Specifies the
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
<link linkend="thread.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
|
||||
<para>The only clock type supported by &Boost.Thread; is
|
||||
<code>TIME_UTC</code>. The epoch for <code>TIME_UTC</code>
|
||||
is 1970-01-01 00:00:00.</para>
|
||||
</description>
|
||||
@@ -32,21 +36,21 @@
|
||||
<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>
|
||||
<link linkend="thread.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.
|
||||
<link linkend="thread.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>
|
||||
<link linkend="thread.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>
|
||||
which <link linkend="thread.concepts.read-write-lock-models">model</link>
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
@@ -60,15 +64,15 @@
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_read_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_read_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -76,7 +80,7 @@
|
||||
</para>
|
||||
|
||||
<para>The <classname>read_write_mutex</classname> class uses an
|
||||
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
<link linkend="thread.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>.
|
||||
@@ -86,20 +90,20 @@
|
||||
<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>
|
||||
<link linkend="thread.concepts.read-write-mutex-models">read/write mutex models</link>
|
||||
in &Boost.Thread;, <classname>read_write_mutex</classname> has two types of
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies">scheduling policies</link>, an
|
||||
<link linkend="thread.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>
|
||||
<link linkend="thread.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>
|
||||
<link linkend="thread.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>.
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
|
||||
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>.
|
||||
</para>
|
||||
|
||||
<note>Self-deadlock is virtually guaranteed if a thread tries to
|
||||
@@ -155,21 +159,21 @@
|
||||
<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>
|
||||
<link linkend="thread.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.
|
||||
<link linkend="thread.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>
|
||||
<link linkend="thread.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>
|
||||
which <link linkend="thread.concepts.read-write-lock-models">model</link>
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
@@ -183,27 +187,27 @@
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_read_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_read_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_read_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_read_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -211,7 +215,7 @@
|
||||
</para>
|
||||
|
||||
<para>The <classname>try_read_write_mutex</classname> class uses an
|
||||
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
<link linkend="thread.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>.
|
||||
@@ -221,20 +225,20 @@
|
||||
<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>
|
||||
<link linkend="thread.concepts.read-write-mutex-models">read/write mutex models</link>
|
||||
in &Boost.Thread;, <classname>try_read_write_mutex</classname> has two types of
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies">scheduling policies</link>, an
|
||||
<link linkend="thread.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>
|
||||
<link linkend="thread.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>
|
||||
<link linkend="thread.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>.
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
|
||||
<link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
</para>
|
||||
|
||||
<note>Self-deadlock is virtually guaranteed if a thread tries to
|
||||
@@ -297,21 +301,21 @@
|
||||
<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>
|
||||
<link linkend="thread.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.
|
||||
<link linkend="thread.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>
|
||||
<link linkend="thread.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>
|
||||
which <link linkend="thread.concepts.read-write-lock-models">model</link>
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
@@ -325,39 +329,39 @@
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_read_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_read_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_read_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTimedReadWriteLock">ScopedTimedReadWriteLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTimedReadWriteLock">ScopedTimedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_read_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_read_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_read_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -365,7 +369,7 @@
|
||||
</para>
|
||||
|
||||
<para>The <classname>timed_read_write_mutex</classname> class uses an
|
||||
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
<link linkend="thread.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>.
|
||||
@@ -375,20 +379,20 @@
|
||||
<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>
|
||||
<link linkend="thread.concepts.read-write-mutex-models">read/write mutex models</link>
|
||||
in &Boost.Thread;, <classname>timed_read_write_mutex</classname> has two types of
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies">scheduling policies</link>, an
|
||||
<link linkend="thread.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>
|
||||
<link linkend="thread.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>
|
||||
<link linkend="thread.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>.
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
|
||||
<link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
</para>
|
||||
|
||||
<note>Self-deadlock is virtually guaranteed if a thread tries to
|
||||
|
||||
@@ -1,29 +1,33 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<header name="boost/thread/recursive_mutex.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
<class name="recursive_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>recursive_mutex</classname> class is a model of the
|
||||
<link linkend="threads.concepts.Mutex">Mutex</link> concept.</para>
|
||||
<link linkend="thread.concepts.Mutex">Mutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>recursive_mutex</classname> class is a model of the
|
||||
<link linkend="threads.concepts.Mutex">Mutex</link> concept.
|
||||
<link linkend="thread.concepts.Mutex">Mutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
|
||||
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
|
||||
locking mechanics.</para>
|
||||
|
||||
<para>For classes that model related mutex concepts, see
|
||||
<classname>recursive_try_mutex</classname> and <classname>recursive_timed_mutex</classname>.</para>
|
||||
|
||||
<para>For <link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
<para>For <link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking mechanics, see <classname>mutex</classname>,
|
||||
<classname>try_mutex</classname>, and <classname>timed_mutex</classname>.
|
||||
</para>
|
||||
@@ -43,7 +47,7 @@
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -51,7 +55,7 @@
|
||||
</para>
|
||||
|
||||
<para>The <classname>recursive_mutex</classname> class uses a
|
||||
<link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
|
||||
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
|
||||
locking strategy, so attempts to recursively lock a
|
||||
<classname>recursive_mutex</classname> object
|
||||
succeed and an internal "lock count" is maintained.
|
||||
@@ -60,10 +64,10 @@
|
||||
<emphasis role="bold">undefined behavior</emphasis>.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="threads.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Threads;, <classname>recursive_mutex</classname> leaves the
|
||||
<link linkend="threads.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
<link linkend="thread.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Thread;, <classname>recursive_mutex</classname> leaves the
|
||||
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
Programmers should make no assumptions about the order in which
|
||||
waiting threads acquire a lock.</para>
|
||||
</description>
|
||||
@@ -99,20 +103,20 @@
|
||||
<class name="recursive_try_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>recursive_try_mutex</classname> class is a model of the
|
||||
<link linkend="threads.concepts.TryMutex">TryMutex</link> concept.</para>
|
||||
<link linkend="thread.concepts.TryMutex">TryMutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>recursive_try_mutex</classname> class is a model of the
|
||||
<link linkend="threads.concepts.TryMutex">TryMutex</link> concept.
|
||||
<link linkend="thread.concepts.TryMutex">TryMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
|
||||
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
|
||||
locking mechanics.</para>
|
||||
|
||||
<para>For classes that model related mutex concepts, see
|
||||
<classname>recursive_mutex</classname> and <classname>recursive_timed_mutex</classname>.</para>
|
||||
|
||||
<para>For <link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
<para>For <link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking mechanics, see <classname>mutex</classname>,
|
||||
<classname>try_mutex</classname>, and <classname>timed_mutex</classname>.
|
||||
</para>
|
||||
@@ -132,11 +136,11 @@
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -144,7 +148,7 @@
|
||||
</para>
|
||||
|
||||
<para>The <classname>recursive_try_mutex</classname> class uses a
|
||||
<link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
|
||||
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
|
||||
locking strategy, so attempts to recursively lock a
|
||||
<classname>recursive_try_mutex</classname> object
|
||||
succeed and an internal "lock count" is maintained.
|
||||
@@ -153,10 +157,10 @@
|
||||
<emphasis role="bold">undefined behavior</emphasis>.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="threads.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Threads;, <classname>recursive_try_mutex</classname> leaves the
|
||||
<link linkend="threads.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
<link linkend="thread.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Thread;, <classname>recursive_try_mutex</classname> leaves the
|
||||
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
Programmers should make no assumptions about the order in which
|
||||
waiting threads acquire a lock.</para>
|
||||
</description>
|
||||
@@ -197,20 +201,20 @@
|
||||
<class name="recursive_timed_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>recursive_timed_mutex</classname> class is a model of the
|
||||
<link linkend="threads.concepts.TimedMutex">TimedMutex</link> concept.</para>
|
||||
<link linkend="thread.concepts.TimedMutex">TimedMutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>recursive_timed_mutex</classname> class is a model of the
|
||||
<link linkend="threads.concepts.TimedMutex">TimedMutex</link> concept.
|
||||
<link linkend="thread.concepts.TimedMutex">TimedMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
|
||||
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
|
||||
locking mechanics.</para>
|
||||
|
||||
<para>For classes that model related mutex concepts, see
|
||||
<classname>recursive_mutex</classname> and <classname>recursive_try_mutex</classname>.</para>
|
||||
|
||||
<para>For <link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
<para>For <link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking mechanics, see <classname>mutex</classname>,
|
||||
<classname>try_mutex</classname>, and <classname>timed_mutex</classname>.
|
||||
</para>
|
||||
@@ -230,15 +234,15 @@
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -246,7 +250,7 @@
|
||||
</para>
|
||||
|
||||
<para>The <classname>recursive_timed_mutex</classname> class uses a
|
||||
<link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
|
||||
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
|
||||
locking strategy, so attempts to recursively lock a
|
||||
<classname>recursive_timed_mutex</classname> object
|
||||
succeed and an internal "lock count" is maintained.
|
||||
@@ -255,10 +259,10 @@
|
||||
<emphasis role="bold">undefined behavior</emphasis>.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="threads.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Threads;, <classname>recursive_timed_mutex</classname> leaves the
|
||||
<link linkend="threads.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
<link linkend="thread.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Thread;, <classname>recursive_timed_mutex</classname> leaves the
|
||||
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
Programmers should make no assumptions about the order in which
|
||||
waiting threads acquire a lock.</para>
|
||||
</description>
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<library-reference id="threads.reference"
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<library-reference id="thread.reference"
|
||||
last-revision="$Date$"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<xi:include href="barrier-ref.xml"/>
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<section id="threads.release_notes" last-revision="$Date$">
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<section id="thread.release_notes" last-revision="$Date$">
|
||||
<title>Release Notes</title>
|
||||
<section id="threads.release_notes.boost_1_32_0">
|
||||
<section id="thread.release_notes.boost_1_32_0">
|
||||
<title>Boost 1.32.0</title>
|
||||
|
||||
<section id="threads.release_notes.boost_1_32_0.change_log.documentation">
|
||||
<section id="thread.release_notes.boost_1_32_0.change_log.documentation">
|
||||
<title>Documentation converted to BoostBook</title>
|
||||
|
||||
<para>The documentation was converted to BoostBook format,
|
||||
@@ -20,24 +24,24 @@
|
||||
please report them!</para>
|
||||
</section>
|
||||
|
||||
<section id="threads.release_notes.boost_1_32_0.change_log.static_link">
|
||||
<section id="thread.release_notes.boost_1_32_0.change_log.static_link">
|
||||
<title>Statically-link build option added</title>
|
||||
|
||||
<para>The option to link &Boost.Threads; as a static
|
||||
<para>The option to link &Boost.Thread; as a static
|
||||
library has been added (with some limitations on Win32 platforms).
|
||||
This feature was originally removed from an earlier version
|
||||
of Boost because <classname>boost::thread_specific_ptr</classname>
|
||||
required that &Boost.Threads; be dynamically linked in order
|
||||
required that &Boost.Thread; be dynamically linked in order
|
||||
for its cleanup functionality to work on Win32 platforms.
|
||||
Because this limitation never applied to non-Win32 platforms,
|
||||
because significant progress has been made in removing
|
||||
the limitation on Win32 platforms (many thanks to
|
||||
Aaron LaFramboise and Roland Scwarz!), and because the lack
|
||||
of static linking is one of the most common complaints of
|
||||
&Boost.Threads; users, this decision was reversed.</para>
|
||||
&Boost.Thread; users, this decision was reversed.</para>
|
||||
|
||||
<para>On non-Win32 platforms:
|
||||
To choose the dynamically linked version of &Boost.Threads;
|
||||
To choose the dynamically linked version of &Boost.Thread;
|
||||
using Boost's auto-linking feature, #define BOOST_THREAD_USE_DLL;
|
||||
to choose the statically linked version,
|
||||
#define BOOST_THREAD_USE_LIB.
|
||||
@@ -63,9 +67,9 @@
|
||||
because it has not yet been possible to implement automatic
|
||||
tss cleanup in the statically linked version for compilers
|
||||
other than VC++, although it is hoped that this will be
|
||||
possible in a future version of &Boost.Threads;.
|
||||
possible in a future version of &Boost.Thread;.
|
||||
|
||||
Note for advanced users: &Boost.Threads; provides several "hook"
|
||||
Note for advanced users: &Boost.Thread; provides several "hook"
|
||||
functions to allow users to experiment with the statically
|
||||
linked version on Win32 with compilers other than VC++.
|
||||
These functions are on_process_enter(), on_process_exit(),
|
||||
@@ -74,13 +78,13 @@
|
||||
information.</para>
|
||||
</section>
|
||||
|
||||
<section id="threads.release_notes.boost_1_32_0.change_log.barrier">
|
||||
<section id="thread.release_notes.boost_1_32_0.change_log.barrier">
|
||||
<title>Barrier functionality added</title>
|
||||
|
||||
<para>A new class, <classname>boost::barrier</classname>, was added.</para>
|
||||
</section>
|
||||
|
||||
<section id="threads.release_notes.boost_1_32_0.change_log.read_write_mutex">
|
||||
<section id="thread.release_notes.boost_1_32_0.change_log.read_write_mutex">
|
||||
<title>Read/write mutex functionality added</title>
|
||||
|
||||
<para>New classes,
|
||||
@@ -91,13 +95,13 @@
|
||||
|
||||
<note>Since the read/write mutex and related classes are new,
|
||||
both interface and implementation are liable to change
|
||||
in future releases of &Boost.Threads;.
|
||||
in future releases of &Boost.Thread;.
|
||||
The lock concepts and lock promotion in particular are
|
||||
still under discussion and very likely to change.</note>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="threads.release_notes.boost_1_32_0.change_log.thread_specific_ptr">
|
||||
<section id="thread.release_notes.boost_1_32_0.change_log.thread_specific_ptr">
|
||||
<title>Thread-specific pointer functionality changed</title>
|
||||
|
||||
<para>The <classname>boost::thread_specific_ptr</classname>
|
||||
@@ -124,7 +128,7 @@
|
||||
is called.</para>
|
||||
</section>
|
||||
|
||||
<section id="threads.release_notes.boost_1_32_0.change_log.mutex">
|
||||
<section id="thread.release_notes.boost_1_32_0.change_log.mutex">
|
||||
<title>Mutex implementation changed for Win32</title>
|
||||
|
||||
<para>On Win32, <classname>boost::mutex</classname>,
|
||||
@@ -135,10 +139,10 @@
|
||||
<classname>boost::recursive_timed_mutex</classname> use a Win32 mutex.</para>
|
||||
</section>
|
||||
|
||||
<section id="threads.release_notes.boost_1_32_0.change_log.wince">
|
||||
<section id="thread.release_notes.boost_1_32_0.change_log.wince">
|
||||
<title>Windows CE support improved</title>
|
||||
|
||||
<para>Minor changes were made to make Boost.Threads work on Windows CE.</para>
|
||||
<para>Minor changes were made to make Boost.Thread work on Windows CE.</para>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<header name="boost/thread/thread.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
@@ -11,15 +15,15 @@
|
||||
<purpose>
|
||||
<para>The <classname>thread</classname> class represents threads of
|
||||
execution, and provides the functionality to create and manage
|
||||
threads within the &Boost.Threads; library. See
|
||||
<xref linkend="threads.glossary"/> for a precise description of
|
||||
<link linkend="threads.glossary.thread">thread of execution</link>,
|
||||
threads within the &Boost.Thread; library. See
|
||||
<xref linkend="thread.glossary"/> for a precise description of
|
||||
<link linkend="thread.glossary.thread">thread of execution</link>,
|
||||
and for definitions of threading-related terms and of thread states such as
|
||||
<link linkend="threads.glossary.thread-state">blocked</link>.</para>
|
||||
<link linkend="thread.glossary.thread-state">blocked</link>.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>A <link linkend="threads.glossary.thread">thread of execution</link>
|
||||
<para>A <link linkend="thread.glossary.thread">thread of execution</link>
|
||||
has an initial function. For the program's initial thread, the initial
|
||||
function is <code>main()</code>. For other threads, the initial
|
||||
function is <code>operator()</code> of the function object passed to
|
||||
@@ -36,7 +40,7 @@
|
||||
"joinable" or "non-joinable".</para>
|
||||
|
||||
<para>Except as described below, the policy used by an implementation
|
||||
of &Boost.Threads; to schedule transitions between thread states is
|
||||
of &Boost.Thread; to schedule transitions between thread states is
|
||||
unspecified.</para>
|
||||
|
||||
<para><note>Just as the lifetime of a file may be different from the
|
||||
@@ -149,7 +153,7 @@
|
||||
<notes>If <code>*this == thread()</code> the result is
|
||||
implementation-defined. If the implementation doesn't
|
||||
detect this the result will be
|
||||
<link linkend="threads.glossary.deadlock">deadlock</link>.
|
||||
<link linkend="thread.glossary.deadlock">deadlock</link>.
|
||||
</notes>
|
||||
</method>
|
||||
</method-group>
|
||||
@@ -170,7 +174,7 @@
|
||||
<type>void</type>
|
||||
|
||||
<effects>The current thread of execution is placed in the
|
||||
<link linkend="threads.glossary.thread-state">ready</link>
|
||||
<link linkend="thread.glossary.thread-state">ready</link>
|
||||
state.</effects>
|
||||
|
||||
<notes>
|
||||
@@ -229,7 +233,7 @@
|
||||
<type>void</type>
|
||||
|
||||
<parameter name="thrd">
|
||||
<paramtype><classname>thread</classname>* thrd</paramtype>
|
||||
<paramtype><classname>thread</classname>*</paramtype>
|
||||
</parameter>
|
||||
|
||||
<effects>Adds <code>thrd</code> to the
|
||||
@@ -243,7 +247,7 @@
|
||||
<type>void</type>
|
||||
|
||||
<parameter name="thrd">
|
||||
<paramtype><classname>thread</classname>* thrd</paramtype>
|
||||
<paramtype><classname>thread</classname>*</paramtype>
|
||||
</parameter>
|
||||
|
||||
<effects>Removes <code>thread</code> from <code>*this</code>'s
|
||||
@@ -260,7 +264,20 @@
|
||||
<effects>Calls <code>join()</code> on each of the managed
|
||||
<classname>thread</classname> objects.</effects>
|
||||
</method>
|
||||
</method-group>
|
||||
</method-group>
|
||||
|
||||
<method-group name="capacity">
|
||||
|
||||
<method name="size" cv="const">
|
||||
<type>int</type>
|
||||
|
||||
<returns>the number of <classname>thread</classname>
|
||||
objects in the group
|
||||
</returns>
|
||||
|
||||
</method>
|
||||
|
||||
</method-group>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<library name="Threads" dirname="thread" id="threads"
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<library name="Thread" dirname="thread" id="thread"
|
||||
last-revision="$Date$"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<libraryinfo>
|
||||
@@ -20,19 +24,14 @@ xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<holder>William E. Kempf</holder>
|
||||
</copyright>
|
||||
<legalnotice>
|
||||
<para>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.</para>
|
||||
<para>Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)</para>
|
||||
</legalnotice>
|
||||
<librarypurpose>Portable C++ multi-threading</librarypurpose>
|
||||
<librarycategory name="category:concurrent" />
|
||||
<title>Boost.Threads</title>
|
||||
<title>Boost.Thread</title>
|
||||
</libraryinfo>
|
||||
<title>&Boost.Threads;</title>
|
||||
<title>Boost.Thread</title>
|
||||
<xi:include href="overview.xml"/>
|
||||
<xi:include href="design.xml"/>
|
||||
<xi:include href="concepts.xml"/>
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<header name="boost/thread/tss.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
@@ -17,7 +21,7 @@
|
||||
<para>Thread specific storage is data associated with
|
||||
individual threads and is often used to make operations
|
||||
that rely on global data
|
||||
<link linkend="threads.glossary.thread-safe">thread-safe</link>.
|
||||
<link linkend="thread.glossary.thread-safe">thread-safe</link>.
|
||||
</para>
|
||||
|
||||
<para>Template <classname>thread_specific_ptr</classname>
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
<?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;
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
<header name="boost/thread/xtime.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
@@ -16,7 +20,7 @@
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The only clock type supported by &Boost.Threads; is
|
||||
<para>The only clock type supported by &Boost.Thread; is
|
||||
<code>TIME_UTC</code>. The epoch for <code>TIME_UTC</code>
|
||||
is 1970-01-01 00:00:00.</para>
|
||||
</description>
|
||||
@@ -33,9 +37,9 @@
|
||||
<description>
|
||||
<simpara>The <classname>xtime</classname> type is used to represent a point on
|
||||
some time scale or a duration in time. This type may be proposed for the C standard by
|
||||
Markus Kuhn. &Boost.Threads; provides only a very minimal implementation of this
|
||||
Markus Kuhn. &Boost.Thread; provides only a very minimal implementation of this
|
||||
proposal; it is expected that a full implementation (or some other time
|
||||
library) will be provided in Boost as a separate library, at which time &Boost.Threads;
|
||||
library) will be provided in Boost as a separate library, at which time &Boost.Thread;
|
||||
will deprecate its own implementation.</simpara>
|
||||
|
||||
<simpara><emphasis role="bold">Note</emphasis> that the resolution is
|
||||
|
||||
@@ -1,54 +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.
|
||||
#
|
||||
# Boost.Threads example Jamfile
|
||||
#
|
||||
# Additional configuration variables used:
|
||||
# 1. PTW32 may be used on Win32 platforms to specify that the pthreads-win32
|
||||
# library should be used instead of "native" threads. This feature is
|
||||
# mostly used for testing and it's generally recommended you use the
|
||||
# native threading libraries instead. PTW32 should be set to be a list
|
||||
# of two strings, the first specifying the installation path of the
|
||||
# pthreads-win32 library and the second specifying which library
|
||||
# variant to link against (see the pthreads-win32 documentation).
|
||||
# Example: jam -sPTW32="c:\pthreads-win32 pthreadVCE.lib"
|
||||
|
||||
# Declare the location of this subproject relative to the root.
|
||||
subproject libs/thread/example ;
|
||||
|
||||
# Include threads.jam for Boost.Threads global build information.
|
||||
# This greatly simplifies the Jam code needed to configure the build
|
||||
# for the various Win32 build types.
|
||||
import ../build/threads ;
|
||||
|
||||
{
|
||||
template example
|
||||
## sources ##
|
||||
: <template>thread_base
|
||||
<dll>../build/boost_thread
|
||||
## requirements ##
|
||||
:
|
||||
## default build ##
|
||||
:
|
||||
;
|
||||
|
||||
exe monitor : <template>example monitor.cpp ;
|
||||
exe starvephil : <template>example starvephil.cpp ;
|
||||
exe tennis : <template>example tennis.cpp ;
|
||||
exe condition : <template>example condition.cpp ;
|
||||
exe mutex : <template>example mutex.cpp ;
|
||||
exe once : <template>example once.cpp ;
|
||||
exe recursive_mutex : <template>example recursive_mutex.cpp ;
|
||||
exe thread : <template>example thread.cpp ;
|
||||
exe thread_group : <template>example thread_group.cpp ;
|
||||
exe tss : <template>example tss.cpp ;
|
||||
exe xtime : <template>example xtime.cpp ;
|
||||
}
|
||||
@@ -1,5 +1,23 @@
|
||||
# Copyright (C) 2001-2003
|
||||
# William E. Kempf
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
exe starvephil
|
||||
: starvephil.cpp ../build/boost_thread ../../test/build/unit_test_framework
|
||||
project boost/thread/example
|
||||
: requirements <library>../build//boost_thread <threading>multi
|
||||
;
|
||||
|
||||
|
||||
exe monitor : monitor.cpp ;
|
||||
exe starvephil : starvephil.cpp ;
|
||||
exe tennis : tennis.cpp ;
|
||||
exe condition : condition.cpp ;
|
||||
exe mutex : mutex.cpp ;
|
||||
exe once : once.cpp ;
|
||||
exe recursive_mutex : recursive_mutex.cpp ;
|
||||
exe thread : thread.cpp ;
|
||||
exe thread_group : thread_group.cpp ;
|
||||
exe tss : tss.cpp ;
|
||||
exe xtime : xtime.cpp ;
|
||||
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/once.hpp>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <iostream>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/tss.hpp>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
|
||||
19
include/boost/thread.hpp
Normal file
19
include/boost/thread.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_THREAD_WEK01082003_HPP)
|
||||
#define BOOST_THREAD_WEK01082003_HPP
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/once.hpp>
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
#include <boost/thread/tss.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
|
||||
#endif
|
||||
44
include/boost/thread/barrier.hpp
Normal file
44
include/boost/thread/barrier.hpp
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright (C) 2002-2003
|
||||
// David Moore, William E. Kempf
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_BARRIER_JDM030602_HPP
|
||||
#define BOOST_BARRIER_JDM030602_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
class BOOST_THREAD_DECL barrier
|
||||
{
|
||||
public:
|
||||
barrier(unsigned int count);
|
||||
~barrier();
|
||||
|
||||
bool wait();
|
||||
|
||||
private:
|
||||
mutex m_mutex;
|
||||
// disable warnings about non dll import
|
||||
// see: http://www.boost.org/more/separate_compilation.html#dlls
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4251 4231 4660 4275)
|
||||
#endif
|
||||
condition m_cond;
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
unsigned int m_threshold;
|
||||
unsigned int m_count;
|
||||
unsigned int m_generation;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
200
include/boost/thread/condition.hpp
Normal file
200
include/boost/thread/condition.hpp
Normal file
@@ -0,0 +1,200 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_CONDITION_WEK070601_HPP
|
||||
#define BOOST_CONDITION_WEK070601_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/detail/lock.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
# include "scoped_critical_region.hpp"
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct xtime;
|
||||
// disable warnings about non dll import
|
||||
// see: http://www.boost.org/more/separate_compilation.html#dlls
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4251 4231 4660 4275)
|
||||
#endif
|
||||
namespace detail {
|
||||
|
||||
class BOOST_THREAD_DECL condition_impl : private noncopyable
|
||||
{
|
||||
friend class condition;
|
||||
|
||||
public:
|
||||
condition_impl();
|
||||
~condition_impl();
|
||||
|
||||
void notify_one();
|
||||
void notify_all();
|
||||
|
||||
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
void enter_wait();
|
||||
void do_wait();
|
||||
bool do_timed_wait(const xtime& xt);
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
void do_wait(pthread_mutex_t* pmutex);
|
||||
bool do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex);
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
void* m_gate;
|
||||
void* m_queue;
|
||||
void* m_mutex;
|
||||
unsigned m_gone; // # threads that timed out and never made it to m_queue
|
||||
unsigned long m_blocked; // # threads blocked on the condition
|
||||
unsigned m_waiting; // # threads no longer waiting for the condition but
|
||||
// still waiting to be removed from m_queue
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_cond_t m_condition;
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
MPSemaphoreID m_gate;
|
||||
MPSemaphoreID m_queue;
|
||||
threads::mac::detail::scoped_critical_region m_mutex;
|
||||
threads::mac::detail::scoped_critical_region m_mutex_mutex;
|
||||
unsigned m_gone; // # threads that timed out and never made it to m_queue
|
||||
unsigned long m_blocked; // # threads blocked on the condition
|
||||
unsigned m_waiting; // # threads no longer waiting for the condition but
|
||||
// still waiting to be removed from m_queue
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class condition : private noncopyable
|
||||
{
|
||||
public:
|
||||
condition() { }
|
||||
~condition() { }
|
||||
|
||||
void notify_one() { m_impl.notify_one(); }
|
||||
void notify_all() { m_impl.notify_all(); }
|
||||
|
||||
template <typename L>
|
||||
void wait(L& lock)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
do_wait(lock.m_mutex);
|
||||
}
|
||||
|
||||
template <typename L, typename Pr>
|
||||
void wait(L& lock, Pr pred)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
while (!pred())
|
||||
do_wait(lock.m_mutex);
|
||||
}
|
||||
|
||||
template <typename L>
|
||||
bool timed_wait(L& lock, const xtime& xt)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
return do_timed_wait(lock.m_mutex, xt);
|
||||
}
|
||||
|
||||
template <typename L, typename Pr>
|
||||
bool timed_wait(L& lock, const xtime& xt, Pr pred)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
while (!pred())
|
||||
{
|
||||
if (!do_timed_wait(lock.m_mutex, xt))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
detail::condition_impl m_impl;
|
||||
|
||||
template <typename M>
|
||||
void do_wait(M& mutex)
|
||||
{
|
||||
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
m_impl.enter_wait();
|
||||
#endif
|
||||
|
||||
typedef detail::thread::lock_ops<M>
|
||||
#if defined(__HP_aCC) && __HP_aCC <= 33900 && !defined(BOOST_STRICT_CONFIG)
|
||||
# define lock_ops lock_ops_ // HP confuses lock_ops witht the template
|
||||
#endif
|
||||
lock_ops;
|
||||
|
||||
typename lock_ops::lock_state state;
|
||||
lock_ops::unlock(mutex, state);
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
m_impl.do_wait(state.pmutex);
|
||||
#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
m_impl.do_wait();
|
||||
#endif
|
||||
|
||||
lock_ops::lock(mutex, state);
|
||||
#undef lock_ops
|
||||
}
|
||||
|
||||
template <typename M>
|
||||
bool do_timed_wait(M& mutex, const xtime& xt)
|
||||
{
|
||||
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
m_impl.enter_wait();
|
||||
#endif
|
||||
|
||||
typedef detail::thread::lock_ops<M>
|
||||
#if defined(__HP_aCC) && __HP_aCC <= 33900 && !defined(BOOST_STRICT_CONFIG)
|
||||
# define lock_ops lock_ops_ // HP confuses lock_ops witht the template
|
||||
#endif
|
||||
lock_ops;
|
||||
|
||||
typename lock_ops::lock_state state;
|
||||
lock_ops::unlock(mutex, state);
|
||||
|
||||
bool ret = false;
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
ret = m_impl.do_timed_wait(xt, state.pmutex);
|
||||
#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
ret = m_impl.do_timed_wait(xt);
|
||||
#endif
|
||||
|
||||
lock_ops::lock(mutex, state);
|
||||
#undef lock_ops
|
||||
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
} // namespace boost
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
|
||||
// 23 May 01 WEKEMPF Removed "duration" timed_waits, as they are too
|
||||
// difficult to use with spurious wakeups.
|
||||
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
|
||||
|
||||
#endif // BOOST_CONDITION_WEK070601_HPP
|
||||
95
include/boost/thread/detail/config.hpp
Normal file
95
include/boost/thread/detail/config.hpp
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_THREAD_CONFIG_WEK01032003_HPP
|
||||
#define BOOST_THREAD_CONFIG_WEK01032003_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
|
||||
# pragma warn -8008 // Condition always true/false
|
||||
# pragma warn -8080 // Identifier declared but never used
|
||||
# pragma warn -8057 // Parameter never used
|
||||
# pragma warn -8066 // Unreachable code
|
||||
#endif
|
||||
|
||||
// insist on threading support being available:
|
||||
#include <boost/config/requires_threads.hpp>
|
||||
|
||||
// compatibility with the rest of Boost's auto-linking code:
|
||||
#if defined(BOOST_THREAD_DYN_DLL) || defined(BOOST_ALL_DYN_LINK)
|
||||
# undef BOOST_THREAD_USE_LIB
|
||||
# define BOOST_THREAD_USE_DLL
|
||||
#endif
|
||||
|
||||
#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 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
|
||||
# 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
|
||||
#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:
|
||||
//
|
||||
#if defined(BOOST_THREAD_LIB_NAME)
|
||||
# define BOOST_LIB_NAME BOOST_THREAD_LIB_NAME
|
||||
#else
|
||||
# define BOOST_LIB_NAME boost_thread
|
||||
#endif
|
||||
//
|
||||
// If we're importing code from a dll, then tell auto_link.hpp about it:
|
||||
//
|
||||
// And include the header that does the work:
|
||||
//
|
||||
#include <boost/config/auto_link.hpp>
|
||||
#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.
|
||||
39
include/boost/thread/detail/force_cast.hpp
Normal file
39
include/boost/thread/detail/force_cast.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// Mac Murrett
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
#ifndef BOOST_FORCE_CAST_MJM012402_HPP
|
||||
#define BOOST_FORCE_CAST_MJM012402_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
namespace thread {
|
||||
|
||||
// force_cast will convert anything to anything.
|
||||
|
||||
// general case
|
||||
template<class Return_Type, class Argument_Type>
|
||||
inline Return_Type &force_cast(Argument_Type &rSrc)
|
||||
{
|
||||
return(*reinterpret_cast<Return_Type *>(&rSrc));
|
||||
}
|
||||
|
||||
// specialization for const
|
||||
template<class Return_Type, class Argument_Type>
|
||||
inline const Return_Type &force_cast(const Argument_Type &rSrc)
|
||||
{
|
||||
return(*reinterpret_cast<const Return_Type *>(&rSrc));
|
||||
}
|
||||
|
||||
} // namespace thread
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_FORCE_CAST_MJM012402_HPP
|
||||
209
include/boost/thread/detail/lock.hpp
Normal file
209
include/boost/thread/detail/lock.hpp
Normal file
@@ -0,0 +1,209 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_XLOCK_WEK070601_HPP
|
||||
#define BOOST_XLOCK_WEK070601_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
class condition;
|
||||
struct xtime;
|
||||
|
||||
namespace detail { namespace thread {
|
||||
|
||||
template <typename Mutex>
|
||||
class lock_ops : private noncopyable
|
||||
{
|
||||
private:
|
||||
lock_ops() { }
|
||||
|
||||
public:
|
||||
typedef typename Mutex::cv_state lock_state;
|
||||
|
||||
static void lock(Mutex& m)
|
||||
{
|
||||
m.do_lock();
|
||||
}
|
||||
static bool trylock(Mutex& m)
|
||||
{
|
||||
return m.do_trylock();
|
||||
}
|
||||
static bool timedlock(Mutex& m, const xtime& xt)
|
||||
{
|
||||
return m.do_timedlock(xt);
|
||||
}
|
||||
static void unlock(Mutex& m)
|
||||
{
|
||||
m.do_unlock();
|
||||
}
|
||||
static void lock(Mutex& m, lock_state& state)
|
||||
{
|
||||
m.do_lock(state);
|
||||
}
|
||||
static void unlock(Mutex& m, lock_state& state)
|
||||
{
|
||||
m.do_unlock(state);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Mutex>
|
||||
class scoped_lock : private noncopyable
|
||||
{
|
||||
public:
|
||||
typedef Mutex mutex_type;
|
||||
|
||||
explicit scoped_lock(Mutex& mx, bool initially_locked=true)
|
||||
: m_mutex(mx), m_locked(false)
|
||||
{
|
||||
if (initially_locked) lock();
|
||||
}
|
||||
~scoped_lock()
|
||||
{
|
||||
if (m_locked) unlock();
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if (m_locked) throw lock_error();
|
||||
lock_ops<Mutex>::lock(m_mutex);
|
||||
m_locked = true;
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if (!m_locked) throw lock_error();
|
||||
lock_ops<Mutex>::unlock(m_mutex);
|
||||
m_locked = false;
|
||||
}
|
||||
|
||||
bool locked() const { return m_locked; }
|
||||
operator const void*() const { return m_locked ? this : 0; }
|
||||
|
||||
private:
|
||||
friend class boost::condition;
|
||||
|
||||
Mutex& m_mutex;
|
||||
bool m_locked;
|
||||
};
|
||||
|
||||
template <typename TryMutex>
|
||||
class scoped_try_lock : private noncopyable
|
||||
{
|
||||
public:
|
||||
typedef TryMutex mutex_type;
|
||||
|
||||
explicit scoped_try_lock(TryMutex& mx)
|
||||
: m_mutex(mx), m_locked(false)
|
||||
{
|
||||
try_lock();
|
||||
}
|
||||
scoped_try_lock(TryMutex& mx, bool initially_locked)
|
||||
: m_mutex(mx), m_locked(false)
|
||||
{
|
||||
if (initially_locked) lock();
|
||||
}
|
||||
~scoped_try_lock()
|
||||
{
|
||||
if (m_locked) unlock();
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if (m_locked) throw lock_error();
|
||||
lock_ops<TryMutex>::lock(m_mutex);
|
||||
m_locked = true;
|
||||
}
|
||||
bool try_lock()
|
||||
{
|
||||
if (m_locked) throw lock_error();
|
||||
return (m_locked = lock_ops<TryMutex>::trylock(m_mutex));
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if (!m_locked) throw lock_error();
|
||||
lock_ops<TryMutex>::unlock(m_mutex);
|
||||
m_locked = false;
|
||||
}
|
||||
|
||||
bool locked() const { return m_locked; }
|
||||
operator const void*() const { return m_locked ? this : 0; }
|
||||
|
||||
private:
|
||||
friend class boost::condition;
|
||||
|
||||
TryMutex& m_mutex;
|
||||
bool m_locked;
|
||||
};
|
||||
|
||||
template <typename TimedMutex>
|
||||
class scoped_timed_lock : private noncopyable
|
||||
{
|
||||
public:
|
||||
typedef TimedMutex mutex_type;
|
||||
|
||||
scoped_timed_lock(TimedMutex& mx, const xtime& xt)
|
||||
: m_mutex(mx), m_locked(false)
|
||||
{
|
||||
timed_lock(xt);
|
||||
}
|
||||
scoped_timed_lock(TimedMutex& mx, bool initially_locked)
|
||||
: m_mutex(mx), m_locked(false)
|
||||
{
|
||||
if (initially_locked) lock();
|
||||
}
|
||||
~scoped_timed_lock()
|
||||
{
|
||||
if (m_locked) unlock();
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if (m_locked) throw lock_error();
|
||||
lock_ops<TimedMutex>::lock(m_mutex);
|
||||
m_locked = true;
|
||||
}
|
||||
bool try_lock()
|
||||
{
|
||||
if (m_locked) throw lock_error();
|
||||
return (m_locked = lock_ops<TimedMutex>::trylock(m_mutex));
|
||||
}
|
||||
bool timed_lock(const xtime& xt)
|
||||
{
|
||||
if (m_locked) throw lock_error();
|
||||
return (m_locked = lock_ops<TimedMutex>::timedlock(m_mutex, xt));
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if (!m_locked) throw lock_error();
|
||||
lock_ops<TimedMutex>::unlock(m_mutex);
|
||||
m_locked = false;
|
||||
}
|
||||
|
||||
bool locked() const { return m_locked; }
|
||||
operator const void*() const { return m_locked ? this : 0; }
|
||||
|
||||
private:
|
||||
friend class boost::condition;
|
||||
|
||||
TimedMutex& m_mutex;
|
||||
bool m_locked;
|
||||
};
|
||||
|
||||
} // namespace thread
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_XLOCK_WEK070601_HPP
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
|
||||
// 30 Jul 01 WEKEMPF Moved lock types into boost::detail::thread. Renamed
|
||||
// some types. Added locked() methods.
|
||||
1106
include/boost/thread/detail/read_write_lock.hpp
Normal file
1106
include/boost/thread/detail/read_write_lock.hpp
Normal file
File diff suppressed because it is too large
Load Diff
59
include/boost/thread/detail/singleton.hpp
Normal file
59
include/boost/thread/detail/singleton.hpp
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// Mac Murrett
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
#ifndef BOOST_SINGLETON_MJM012402_HPP
|
||||
#define BOOST_SINGLETON_MJM012402_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
namespace thread {
|
||||
|
||||
// class singleton has the same goal as all singletons: create one instance of
|
||||
// a class on demand, then dish it out as requested.
|
||||
|
||||
template <class T>
|
||||
class singleton : private T
|
||||
{
|
||||
private:
|
||||
singleton();
|
||||
~singleton();
|
||||
|
||||
public:
|
||||
static T &instance();
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
inline singleton<T>::singleton()
|
||||
{
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline singleton<T>::~singleton()
|
||||
{
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
template <class T>
|
||||
/*static*/ T &singleton<T>::instance()
|
||||
{
|
||||
// function-local static to force this to work correctly at static
|
||||
// initialization time.
|
||||
static singleton<T> s_oT;
|
||||
return(s_oT);
|
||||
}
|
||||
|
||||
} // namespace thread
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_SINGLETON_MJM012402_HPP
|
||||
78
include/boost/thread/detail/tss_hooks.hpp
Normal file
78
include/boost/thread/detail/tss_hooks.hpp
Normal file
@@ -0,0 +1,78 @@
|
||||
// (C) Copyright Michael Glassford 2004.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_TLS_HOOKS_HPP)
|
||||
#define BOOST_TLS_HOOKS_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
|
||||
typedef void (__cdecl *thread_exit_handler)(void);
|
||||
|
||||
extern "C" BOOST_THREAD_DECL int at_thread_exit(
|
||||
thread_exit_handler exit_handler
|
||||
);
|
||||
//Add a function to the list of functions that will
|
||||
//be called when a thread is about to exit.
|
||||
//Currently only implemented for Win32, but should
|
||||
//later be implemented for all platforms.
|
||||
//Used by Win32 implementation of Boost.Threads
|
||||
//tss to perform cleanup.
|
||||
//Like the C runtime library atexit() function,
|
||||
//which it mimics, at_thread_exit() returns
|
||||
//zero if successful and a nonzero
|
||||
//value if an error occurs.
|
||||
|
||||
#endif //defined(BOOST_HAS_WINTHREADS)
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_process_enter(void);
|
||||
//Function to be called when the exe or dll
|
||||
//that uses Boost.Threads first starts
|
||||
//or is first loaded.
|
||||
//Should be called only before the first call to
|
||||
//on_thread_enter().
|
||||
//Called automatically by Boost.Threads when
|
||||
//a method for doing so has been discovered.
|
||||
//May be omitted; may be called multiple times.
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_process_exit(void);
|
||||
//Function to be called when the exe or dll
|
||||
//that uses Boost.Threads first starts
|
||||
//or is first loaded.
|
||||
//Should be called only after the last call to
|
||||
//on_exit_thread().
|
||||
//Called automatically by Boost.Threads when
|
||||
//a method for doing so has been discovered.
|
||||
//Must not be omitted; may be called multiple times.
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_thread_enter(void);
|
||||
//Function to be called just after a thread starts
|
||||
//in an exe or dll that uses Boost.Threads.
|
||||
//Must be called in the context of the thread
|
||||
//that is starting.
|
||||
//Called automatically by Boost.Threads when
|
||||
//a method for doing so has been discovered.
|
||||
//May be omitted; may be called multiple times.
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_thread_exit(void);
|
||||
//Function to be called just be fore a thread ends
|
||||
//in an exe or dll that uses Boost.Threads.
|
||||
//Must be called in the context of the thread
|
||||
//that is ending.
|
||||
//Called automatically by Boost.Threads when
|
||||
//a method for doing so has been discovered.
|
||||
//Must not be omitted; may be called multiple times.
|
||||
|
||||
extern "C" void tss_cleanup_implemented(void);
|
||||
//Dummy function used both to detect whether tss cleanup
|
||||
//cleanup has been implemented and to force
|
||||
//it to be linked into the Boost.Threads library.
|
||||
|
||||
#endif //defined(BOOST_HAS_WINTHREADS)
|
||||
|
||||
#endif //!defined(BOOST_TLS_HOOKS_HPP)
|
||||
94
include/boost/thread/exceptions.hpp
Normal file
94
include/boost/thread/exceptions.hpp
Normal file
@@ -0,0 +1,94 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_THREAD_EXCEPTIONS_PDM070801_H
|
||||
#define BOOST_THREAD_EXCEPTIONS_PDM070801_H
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
// pdm: Sorry, but this class is used all over the place & I end up
|
||||
// with recursive headers if I don't separate it
|
||||
// wek: Not sure why recursive headers would cause compilation problems
|
||||
// given the include guards, but regardless it makes sense to
|
||||
// seperate this out any way.
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace boost {
|
||||
|
||||
class BOOST_THREAD_DECL thread_exception : public std::exception
|
||||
{
|
||||
protected:
|
||||
thread_exception();
|
||||
thread_exception(int sys_err_code);
|
||||
|
||||
public:
|
||||
~thread_exception() throw();
|
||||
|
||||
int native_error() const;
|
||||
|
||||
private:
|
||||
int m_sys_err;
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL lock_error : public thread_exception
|
||||
{
|
||||
public:
|
||||
lock_error();
|
||||
lock_error(int sys_err_code);
|
||||
~lock_error() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL thread_resource_error : public thread_exception
|
||||
{
|
||||
public:
|
||||
thread_resource_error();
|
||||
thread_resource_error(int sys_err_code);
|
||||
~thread_resource_error() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL unsupported_thread_option : public thread_exception
|
||||
{
|
||||
public:
|
||||
unsupported_thread_option();
|
||||
unsupported_thread_option(int sys_err_code);
|
||||
~unsupported_thread_option() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL invalid_thread_argument : public thread_exception
|
||||
{
|
||||
public:
|
||||
invalid_thread_argument();
|
||||
invalid_thread_argument(int sys_err_code);
|
||||
~invalid_thread_argument() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL thread_permission_error : public thread_exception
|
||||
{
|
||||
public:
|
||||
thread_permission_error();
|
||||
thread_permission_error(int sys_err_code);
|
||||
~thread_permission_error() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_THREAD_CONFIG_PDM070801_H
|
||||
|
||||
// Change log:
|
||||
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
|
||||
|
||||
169
include/boost/thread/mutex.hpp
Normal file
169
include/boost/thread/mutex.hpp
Normal file
@@ -0,0 +1,169 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MUTEX_WEK070601_HPP
|
||||
#define BOOST_MUTEX_WEK070601_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/detail/lock.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_MPTASKS)
|
||||
# include "scoped_critical_region.hpp"
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct xtime;
|
||||
// disable warnings about non dll import
|
||||
// see: http://www.boost.org/more/separate_compilation.html#dlls
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4251 4231 4660 4275)
|
||||
#endif
|
||||
class BOOST_THREAD_DECL mutex
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::lock_ops<mutex>;
|
||||
|
||||
typedef detail::thread::scoped_lock<mutex> scoped_lock;
|
||||
|
||||
mutex();
|
||||
~mutex();
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
typedef void* cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
struct cv_state
|
||||
{
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
void* m_mutex;
|
||||
bool m_critical_section;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
threads::mac::detail::scoped_critical_region m_mutex;
|
||||
threads::mac::detail::scoped_critical_region m_mutex_mutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL try_mutex
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::lock_ops<try_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_lock<try_mutex> scoped_lock;
|
||||
typedef detail::thread::scoped_try_lock<try_mutex> scoped_try_lock;
|
||||
|
||||
try_mutex();
|
||||
~try_mutex();
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
typedef void* cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
struct cv_state
|
||||
{
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
void* m_mutex;
|
||||
bool m_critical_section;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
threads::mac::detail::scoped_critical_region m_mutex;
|
||||
threads::mac::detail::scoped_critical_region m_mutex_mutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL timed_mutex
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::lock_ops<timed_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_lock<timed_mutex> scoped_lock;
|
||||
typedef detail::thread::scoped_try_lock<timed_mutex> scoped_try_lock;
|
||||
typedef detail::thread::scoped_timed_lock<timed_mutex> scoped_timed_lock;
|
||||
|
||||
timed_mutex();
|
||||
~timed_mutex();
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
typedef void* cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
struct cv_state
|
||||
{
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
bool do_timedlock(const xtime& xt);
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
void* m_mutex;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
pthread_cond_t m_condition;
|
||||
bool m_locked;
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
threads::mac::detail::scoped_critical_region m_mutex;
|
||||
threads::mac::detail::scoped_critical_region m_mutex_mutex;
|
||||
#endif
|
||||
};
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
} // namespace boost
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 22 May 01 WEKEMPF Modified to use xtime for time outs. Factored out
|
||||
// to three classes, mutex, try_mutex and timed_mutex.
|
||||
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
|
||||
|
||||
#endif // BOOST_MUTEX_WEK070601_HPP
|
||||
37
include/boost/thread/once.hpp
Normal file
37
include/boost/thread/once.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_ONCE_WEK080101_HPP
|
||||
#define BOOST_ONCE_WEK080101_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
|
||||
typedef pthread_once_t once_flag;
|
||||
#define BOOST_ONCE_INIT PTHREAD_ONCE_INIT
|
||||
|
||||
#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
|
||||
typedef long once_flag;
|
||||
#define BOOST_ONCE_INIT 0
|
||||
|
||||
#endif
|
||||
|
||||
void BOOST_THREAD_DECL call_once(void (*func)(), once_flag& flag);
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// Change Log:
|
||||
// 1 Aug 01 WEKEMPF Initial version.
|
||||
|
||||
#endif // BOOST_ONCE_WEK080101_HPP
|
||||
285
include/boost/thread/read_write_mutex.hpp
Normal file
285
include/boost/thread/read_write_mutex.hpp
Normal file
@@ -0,0 +1,285 @@
|
||||
// Copyright (C) 2002-2003
|
||||
// David Moore, William E. Kempf, Michael Glassford
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// 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/detail/workaround.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 {
|
||||
// disable warnings about non dll import
|
||||
// see: http://www.boost.org/more/separate_compilation.html#dlls
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4251 4231 4660 4275)
|
||||
#endif
|
||||
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 one 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);
|
||||
#if !BOOST_WORKAROUND(__BORLANDC__,<= 0x564)
|
||||
~read_write_mutex_impl();
|
||||
#endif
|
||||
|
||||
Mutex m_prot;
|
||||
|
||||
const read_write_scheduling_policy::read_write_scheduling_policy_enum m_sp;
|
||||
int m_state; //-1 = write lock; 0 = unlocked; >0 = read locked
|
||||
|
||||
boost::condition m_waiting_writers;
|
||||
boost::condition m_waiting_readers;
|
||||
boost::condition m_waiting_promotion;
|
||||
int m_num_waiting_writers;
|
||||
int m_num_waiting_readers;
|
||||
bool m_state_waiting_promotion;
|
||||
|
||||
int m_num_waking_writers;
|
||||
int m_num_waking_readers;
|
||||
int m_num_max_waking_writers; //Debug only
|
||||
int m_num_max_waking_readers; //Debug only
|
||||
|
||||
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:
|
||||
|
||||
bool do_demote_to_read_lock_impl();
|
||||
|
||||
enum scheduling_reason
|
||||
{
|
||||
scheduling_reason_unlock,
|
||||
scheduling_reason_timeout,
|
||||
scheduling_reason_demote
|
||||
};
|
||||
|
||||
void do_scheduling_impl(const scheduling_reason reason);
|
||||
bool do_wake_one_reader(void);
|
||||
bool do_wake_all_readers(void);
|
||||
bool do_wake_writer(void);
|
||||
bool waker_exists(void);
|
||||
};
|
||||
|
||||
} // 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);
|
||||
~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);
|
||||
~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);
|
||||
~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;
|
||||
};
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
} // 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.
|
||||
184
include/boost/thread/recursive_mutex.hpp
Normal file
184
include/boost/thread/recursive_mutex.hpp
Normal file
@@ -0,0 +1,184 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_RECURSIVE_MUTEX_WEK070601_HPP
|
||||
#define BOOST_RECURSIVE_MUTEX_WEK070601_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/detail/lock.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_MPTASKS)
|
||||
# include "scoped_critical_region.hpp"
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct xtime;
|
||||
// disable warnings about non dll import
|
||||
// see: http://www.boost.org/more/separate_compilation.html#dlls
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4251 4231 4660 4275)
|
||||
#endif
|
||||
class BOOST_THREAD_DECL recursive_mutex
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::lock_ops<recursive_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_lock<recursive_mutex> scoped_lock;
|
||||
|
||||
recursive_mutex();
|
||||
~recursive_mutex();
|
||||
|
||||
private:
|
||||
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
typedef std::size_t cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
long count;
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
void* m_mutex;
|
||||
bool m_critical_section;
|
||||
unsigned long m_count;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
unsigned m_count;
|
||||
# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
|
||||
pthread_cond_t m_unlocked;
|
||||
pthread_t m_thread_id;
|
||||
bool m_valid_id;
|
||||
# endif
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
threads::mac::detail::scoped_critical_region m_mutex;
|
||||
threads::mac::detail::scoped_critical_region m_mutex_mutex;
|
||||
std::size_t m_count;
|
||||
#endif
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL recursive_try_mutex
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::lock_ops<recursive_try_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_lock<recursive_try_mutex> scoped_lock;
|
||||
typedef detail::thread::scoped_try_lock<
|
||||
recursive_try_mutex> scoped_try_lock;
|
||||
|
||||
recursive_try_mutex();
|
||||
~recursive_try_mutex();
|
||||
|
||||
private:
|
||||
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
typedef std::size_t cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
long count;
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
void* m_mutex;
|
||||
bool m_critical_section;
|
||||
unsigned long m_count;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
unsigned m_count;
|
||||
# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
|
||||
pthread_cond_t m_unlocked;
|
||||
pthread_t m_thread_id;
|
||||
bool m_valid_id;
|
||||
# endif
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
threads::mac::detail::scoped_critical_region m_mutex;
|
||||
threads::mac::detail::scoped_critical_region m_mutex_mutex;
|
||||
std::size_t m_count;
|
||||
#endif
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL recursive_timed_mutex
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::lock_ops<recursive_timed_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_lock<recursive_timed_mutex> scoped_lock;
|
||||
typedef detail::thread::scoped_try_lock<
|
||||
recursive_timed_mutex> scoped_try_lock;
|
||||
typedef detail::thread::scoped_timed_lock<
|
||||
recursive_timed_mutex> scoped_timed_lock;
|
||||
|
||||
recursive_timed_mutex();
|
||||
~recursive_timed_mutex();
|
||||
|
||||
private:
|
||||
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
typedef std::size_t cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
long count;
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
bool do_timedlock(const xtime& xt);
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
void* m_mutex;
|
||||
unsigned long m_count;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
pthread_cond_t m_unlocked;
|
||||
pthread_t m_thread_id;
|
||||
bool m_valid_id;
|
||||
unsigned m_count;
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
threads::mac::detail::scoped_critical_region m_mutex;
|
||||
threads::mac::detail::scoped_critical_region m_mutex_mutex;
|
||||
std::size_t m_count;
|
||||
#endif
|
||||
};
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_RECURSIVE_MUTEX_WEK070601_HPP
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 1 Jun 01 WEKEMPF Modified to use xtime for time outs. Factored out
|
||||
// to three classes, mutex, try_mutex and timed_mutex.
|
||||
// 11 Jun 01 WEKEMPF Modified to use PTHREAD_MUTEX_RECURSIVE if available.
|
||||
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
|
||||
89
include/boost/thread/thread.hpp
Normal file
89
include/boost/thread/thread.hpp
Normal file
@@ -0,0 +1,89 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_THREAD_WEK070601_HPP
|
||||
#define BOOST_THREAD_WEK070601_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
# include <boost/thread/condition.hpp>
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
# include <Multiprocessing.h>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct xtime;
|
||||
// disable warnings about non dll import
|
||||
// see: http://www.boost.org/more/separate_compilation.html#dlls
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4251 4231 4660 4275)
|
||||
#endif
|
||||
class BOOST_THREAD_DECL thread : private noncopyable
|
||||
{
|
||||
public:
|
||||
thread();
|
||||
explicit thread(const function0<void>& threadfunc);
|
||||
~thread();
|
||||
|
||||
bool operator==(const thread& other) const;
|
||||
bool operator!=(const thread& other) const;
|
||||
|
||||
void join();
|
||||
|
||||
static void sleep(const xtime& xt);
|
||||
static void yield();
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
void* m_thread;
|
||||
unsigned int m_id;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
private:
|
||||
pthread_t m_thread;
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
MPQueueID m_pJoinQueueID;
|
||||
MPTaskID m_pTaskID;
|
||||
#endif
|
||||
bool m_joinable;
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL thread_group : private noncopyable
|
||||
{
|
||||
public:
|
||||
thread_group();
|
||||
~thread_group();
|
||||
|
||||
thread* create_thread(const function0<void>& threadfunc);
|
||||
void add_thread(thread* thrd);
|
||||
void remove_thread(thread* thrd);
|
||||
void join_all();
|
||||
int size() const;
|
||||
|
||||
private:
|
||||
std::list<thread*> m_threads;
|
||||
mutex m_mutex;
|
||||
};
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
} // namespace boost
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 1 Jun 01 WEKEMPF Added boost::thread initial implementation.
|
||||
// 3 Jul 01 WEKEMPF Redesigned boost::thread to be noncopyable.
|
||||
|
||||
#endif // BOOST_THREAD_WEK070601_HPP
|
||||
127
include/boost/thread/tss.hpp
Normal file
127
include/boost/thread/tss.hpp
Normal file
@@ -0,0 +1,127 @@
|
||||
// Copyright (C) 2001-2003 William E. Kempf
|
||||
// Copyright (C) 2006 Roland Schwarz
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_TSS_WEK070601_HPP
|
||||
#define BOOST_TSS_WEK070601_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
# include <Multiprocessing.h>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
// disable warnings about non dll import
|
||||
// see: http://www.boost.org/more/separate_compilation.html#dlls
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4251 4231 4660 4275)
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
class BOOST_THREAD_DECL tss : private noncopyable
|
||||
{
|
||||
public:
|
||||
tss(boost::function1<void, void*>* pcleanup) {
|
||||
if (pcleanup == 0) throw boost::thread_resource_error();
|
||||
try
|
||||
{
|
||||
init(pcleanup);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
delete pcleanup;
|
||||
throw boost::thread_resource_error();
|
||||
}
|
||||
}
|
||||
~tss();
|
||||
void* get() const;
|
||||
void set(void* value);
|
||||
void cleanup(void* p);
|
||||
|
||||
private:
|
||||
unsigned int m_slot; //This is a "pseudo-slot", not a native slot
|
||||
|
||||
void init(boost::function1<void, void*>* pcleanup);
|
||||
};
|
||||
|
||||
#if defined(BOOST_HAS_MPTASKS)
|
||||
void thread_cleanup();
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
struct tss_adapter
|
||||
{
|
||||
template <typename F>
|
||||
tss_adapter(const F& cleanup) : m_cleanup(cleanup) { }
|
||||
void operator()(void* p) { m_cleanup(static_cast<T*>(p)); }
|
||||
boost::function1<void, T*> m_cleanup;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T>
|
||||
class thread_specific_ptr : private noncopyable
|
||||
{
|
||||
public:
|
||||
thread_specific_ptr()
|
||||
: m_tss(new boost::function1<void, void*>(
|
||||
boost::detail::tss_adapter<T>(
|
||||
&thread_specific_ptr<T>::cleanup)))
|
||||
{
|
||||
}
|
||||
thread_specific_ptr(void (*clean)(T*))
|
||||
: m_tss(new boost::function1<void, void*>(
|
||||
boost::detail::tss_adapter<T>(clean)))
|
||||
{
|
||||
}
|
||||
~thread_specific_ptr() { reset(); }
|
||||
|
||||
T* get() const { return static_cast<T*>(m_tss.get()); }
|
||||
T* operator->() const { return get(); }
|
||||
T& operator*() const { return *get(); }
|
||||
T* release() { T* temp = get(); if (temp) m_tss.set(0); return temp; }
|
||||
void reset(T* p=0)
|
||||
{
|
||||
T* cur = get();
|
||||
if (cur == p) return;
|
||||
m_tss.set(p);
|
||||
if (cur) m_tss.cleanup(cur);
|
||||
}
|
||||
|
||||
private:
|
||||
static void cleanup(T* p) { delete p; }
|
||||
detail::tss m_tss;
|
||||
};
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif //BOOST_TSS_WEK070601_HPP
|
||||
|
||||
// Change Log:
|
||||
// 6 Jun 01
|
||||
// WEKEMPF Initial version.
|
||||
// 30 May 02 WEKEMPF
|
||||
// Added interface to set specific cleanup handlers.
|
||||
// Removed TLS slot limits from most implementations.
|
||||
// 22 Mar 04 GlassfordM for WEKEMPF
|
||||
// Fixed: thread_specific_ptr::reset() doesn't check error returned
|
||||
// by tss::set(); tss::set() now throws if it fails.
|
||||
// Fixed: calling thread_specific_ptr::reset() or
|
||||
// thread_specific_ptr::release() causes double-delete: once on
|
||||
// reset()/release() and once on ~thread_specific_ptr().
|
||||
54
include/boost/thread/xtime.hpp
Normal file
54
include/boost/thread/xtime.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_XTIME_WEK070601_HPP
|
||||
#define BOOST_XTIME_WEK070601_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
enum xtime_clock_types
|
||||
{
|
||||
TIME_UTC=1
|
||||
// TIME_TAI,
|
||||
// TIME_MONOTONIC,
|
||||
// TIME_PROCESS,
|
||||
// TIME_THREAD,
|
||||
// TIME_LOCAL,
|
||||
// TIME_SYNC,
|
||||
// TIME_RESOLUTION
|
||||
};
|
||||
|
||||
struct xtime
|
||||
{
|
||||
#if defined(BOOST_NO_INT64_T)
|
||||
typedef int_fast32_t xtime_sec_t; //INT_FAST32_MIN <= sec <= INT_FAST32_MAX
|
||||
#else
|
||||
typedef int_fast64_t xtime_sec_t; //INT_FAST64_MIN <= sec <= INT_FAST64_MAX
|
||||
#endif
|
||||
|
||||
typedef int_fast32_t xtime_nsec_t; //0 <= xtime.nsec < NANOSECONDS_PER_SECOND
|
||||
|
||||
xtime_sec_t sec;
|
||||
xtime_nsec_t nsec;
|
||||
};
|
||||
|
||||
int BOOST_THREAD_DECL xtime_get(struct xtime* xtp, int clock_type);
|
||||
|
||||
inline int xtime_cmp(const xtime& xt1, const xtime& xt2)
|
||||
{
|
||||
if (xt1.sec == xt2.sec)
|
||||
return (int)(xt1.nsec - xt2.nsec);
|
||||
else
|
||||
return (xt1.sec > xt2.sec) ? 1 : -1;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif //BOOST_XTIME_WEK070601_HPP
|
||||
@@ -1,3 +1,8 @@
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf.
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=doc/index.html">
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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. 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/barrier.hpp>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
@@ -15,57 +10,6 @@
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
# ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std { using ::strerror; }
|
||||
# endif
|
||||
|
||||
// BOOST_POSIX or BOOST_WINDOWS specify which API to use.
|
||||
# if !defined( BOOST_WINDOWS ) && !defined( BOOST_POSIX )
|
||||
# if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)
|
||||
# define BOOST_WINDOWS
|
||||
# else
|
||||
# define BOOST_POSIX
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined( BOOST_WINDOWS )
|
||||
# include "windows.h"
|
||||
# else
|
||||
# include <errno.h> // for POSIX error codes
|
||||
# endif
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
std::string system_message(int sys_err_code)
|
||||
{
|
||||
std::string str;
|
||||
# ifdef BOOST_WINDOWS
|
||||
LPVOID lpMsgBuf;
|
||||
::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
sys_err_code,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPSTR)&lpMsgBuf,
|
||||
0,
|
||||
NULL);
|
||||
str += static_cast<LPCSTR>(lpMsgBuf);
|
||||
::LocalFree(lpMsgBuf); // free the buffer
|
||||
while (str.size() && (str[str.size()-1] == '\n' ||
|
||||
str[str.size()-1] == '\r'))
|
||||
{
|
||||
str.erase(str.size()-1);
|
||||
}
|
||||
# else
|
||||
str += std::strerror(errno);
|
||||
# endif
|
||||
return str;
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
namespace boost {
|
||||
|
||||
thread_exception::thread_exception()
|
||||
@@ -87,13 +31,6 @@ int thread_exception::native_error() const
|
||||
return m_sys_err;
|
||||
}
|
||||
|
||||
const char* thread_exception::message() const
|
||||
{
|
||||
if (m_sys_err != 0)
|
||||
return system_message(m_sys_err).c_str();
|
||||
return what();
|
||||
}
|
||||
|
||||
lock_error::lock_error()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
// boostinspect:nounnamed
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -28,7 +24,7 @@ void init_TryEnterCriticalSection()
|
||||
version_info.dwMajorVersion >= 4)
|
||||
{
|
||||
if (HMODULE kernel_module = GetModuleHandle(TEXT("KERNEL32.DLL")))
|
||||
g_TryEnterCriticalSection = reinterpret_cast<TryEnterCriticalSection_type>(GetProcAddress(kernel_module, "TryEnterCriticalSection"));
|
||||
g_TryEnterCriticalSection = reinterpret_cast<TryEnterCriticalSection_type>(GetProcAddress(kernel_module, TEXT("TryEnterCriticalSection")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,8 +62,10 @@ inline void* new_critical_section()
|
||||
inline void* new_mutex(const char* name)
|
||||
{
|
||||
#if defined(BOOST_NO_ANSI_APIS)
|
||||
USES_CONVERSION;
|
||||
HANDLE mutex = CreateMutexW(0, 0, A2CW(name));
|
||||
int num_wide_chars = (strlen(name) + 1);
|
||||
LPWSTR wide_name = (LPWSTR)_alloca( num_wide_chars * 2 );
|
||||
::MultiByteToWideChar(CP_ACP, 0, name, -1, wide_name, num_wide_chars);
|
||||
HANDLE mutex = CreateMutexW(0, 0, wide_name);
|
||||
#else
|
||||
HANDLE mutex = CreateMutexA(0, 0, name);
|
||||
#endif
|
||||
|
||||
28
src/once.cpp
28
src/once.cpp
@@ -1,22 +1,25 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#include <boost/thread/once.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
# if BOOST_WORKAROUND(__BORLANDC__,<= 0x551)
|
||||
using std::size_t;
|
||||
# endif
|
||||
# include <windows.h>
|
||||
# include "mutex.inl"
|
||||
# if defined(BOOST_NO_STRINGSTREAM)
|
||||
# include <strstream>
|
||||
|
||||
@@ -112,7 +115,11 @@ inline LONG ice_wrapper(LPVOID (__stdcall *ice)(LPVOID*, LPVOID, LPVOID),
|
||||
// according to the above function type wrappers.
|
||||
inline LONG compare_exchange(volatile LPLONG dest, LONG exch, LONG cmp)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
return InterlockedCompareExchange(dest, exch, cmp);
|
||||
#else
|
||||
return ice_wrapper(&InterlockedCompareExchange, dest, exch, cmp);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -132,12 +139,7 @@ void call_once(void (*func)(), once_flag& flag)
|
||||
<< &flag
|
||||
<< std::ends;
|
||||
unfreezer unfreeze(strm);
|
||||
# if defined (BOOST_NO_ANSI_APIS)
|
||||
USES_CONVERSION;
|
||||
HANDLE mutex = CreateMutexW(NULL, FALSE, A2CW(strm.str()));
|
||||
# else
|
||||
HANDLE mutex = CreateMutexA(NULL, FALSE, strm.str());
|
||||
# endif
|
||||
HANDLE mutex=new_mutex(strm.str());
|
||||
#else
|
||||
# if defined (BOOST_NO_ANSI_APIS)
|
||||
std::wostringstream strm;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
@@ -519,7 +514,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)
|
||||
{
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
@@ -94,6 +89,18 @@ public:
|
||||
bool m_started;
|
||||
};
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
|
||||
struct on_thread_exit_guard
|
||||
{
|
||||
~on_thread_exit_guard()
|
||||
{
|
||||
on_thread_exit();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
extern "C" {
|
||||
@@ -105,22 +112,25 @@ extern "C" {
|
||||
static OSStatus thread_proxy(void* param)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
// try
|
||||
{
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
|
||||
on_thread_exit_guard guard;
|
||||
|
||||
#endif
|
||||
|
||||
thread_param* p = static_cast<thread_param*>(param);
|
||||
boost::function0<void> threadfunc = p->m_threadfunc;
|
||||
p->started();
|
||||
threadfunc();
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
on_thread_exit();
|
||||
#endif
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
on_thread_exit();
|
||||
#endif
|
||||
}
|
||||
// catch (...)
|
||||
// {
|
||||
//#if defined(BOOST_HAS_WINTHREADS)
|
||||
// on_thread_exit();
|
||||
//#endif
|
||||
// }
|
||||
#if defined(BOOST_HAS_MPTASKS)
|
||||
::boost::detail::thread_cleanup();
|
||||
#endif
|
||||
@@ -220,6 +230,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 +378,9 @@ void thread_group::join_all()
|
||||
}
|
||||
}
|
||||
|
||||
int thread_group::size() const
|
||||
{
|
||||
return m_threads.size();
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
// boostinspect:nounnamed
|
||||
|
||||
namespace {
|
||||
const int MILLISECONDS_PER_SECOND = 1000;
|
||||
@@ -27,7 +23,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 +35,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 +71,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;
|
||||
@@ -106,17 +102,22 @@ inline void to_duration(boost::xtime xt, int& milliseconds)
|
||||
}
|
||||
}
|
||||
|
||||
inline void to_microduration(const boost::xtime& xt, int& microseconds)
|
||||
inline void to_microduration(boost::xtime xt, int& microseconds)
|
||||
{
|
||||
boost::xtime cur;
|
||||
int res = 0;
|
||||
res = boost::xtime_get(&cur, boost::TIME_UTC);
|
||||
assert(res == boost::TIME_UTC);
|
||||
|
||||
if (boost::xtime_get(&cur, boost::TIME_UTC) <= 0)
|
||||
if (boost::xtime_cmp(xt, cur) <= 0)
|
||||
microseconds = 0;
|
||||
else
|
||||
{
|
||||
if (cur.nsec > xt.nsec)
|
||||
{
|
||||
xt.nsec += NANOSECONDS_PER_SECOND;
|
||||
--xt.sec;
|
||||
}
|
||||
microseconds = (int)((xt.sec - cur.sec) * MICROSECONDS_PER_SECOND) +
|
||||
(((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MICROSECOND/2)) /
|
||||
NANOSECONDS_PER_MICROSECOND);
|
||||
|
||||
139
src/tss.cpp
139
src/tss.cpp
@@ -1,13 +1,8 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// Copyright (C) 2001-2003 William E. Kempf
|
||||
// Copyright (C) 2006 Roland Schwarz
|
||||
//
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
@@ -30,62 +25,98 @@
|
||||
namespace {
|
||||
|
||||
typedef std::vector<void*> tss_slots;
|
||||
typedef std::vector<boost::function1<void, void*>*> tss_data_cleanup_handlers_type;
|
||||
|
||||
struct tss_data_t
|
||||
{
|
||||
boost::mutex mutex;
|
||||
std::vector<boost::function1<void, void*>*> cleanup_handlers;
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
DWORD native_key;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_key_t native_key;
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
TaskStorageIndex native_key;
|
||||
#endif
|
||||
};
|
||||
|
||||
tss_data_t* tss_data = 0;
|
||||
boost::once_flag tss_data_once = BOOST_ONCE_INIT;
|
||||
boost::mutex* tss_data_mutex = 0;
|
||||
tss_data_cleanup_handlers_type* tss_data_cleanup_handlers = 0;
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
DWORD tss_data_native_key;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_key_t tss_data_native_key;
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
TaskStorageIndex tss_data_native_key;
|
||||
#endif
|
||||
int tss_data_use = 0;
|
||||
|
||||
void tss_data_inc_use(boost::mutex::scoped_lock& lk)
|
||||
{
|
||||
++tss_data_use;
|
||||
}
|
||||
|
||||
void tss_data_dec_use(boost::mutex::scoped_lock& lk)
|
||||
{
|
||||
if (0 == --tss_data_use)
|
||||
{
|
||||
tss_data_cleanup_handlers_type::size_type i;
|
||||
for (i = 0; i < tss_data_cleanup_handlers->size(); ++i)
|
||||
{
|
||||
delete (*tss_data_cleanup_handlers)[i];
|
||||
}
|
||||
delete tss_data_cleanup_handlers;
|
||||
tss_data_cleanup_handlers = 0;
|
||||
lk.unlock();
|
||||
delete tss_data_mutex;
|
||||
tss_data_mutex = 0;
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
TlsFree(tss_data_native_key);
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_key_delete(tss_data_native_key);
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
// Don't know what to put here.
|
||||
// But MPTASKS isn't currently maintained anyways...
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void cleanup_slots(void* p)
|
||||
{
|
||||
tss_slots* slots = static_cast<tss_slots*>(p);
|
||||
boost::mutex::scoped_lock lock(*tss_data_mutex);
|
||||
for (tss_slots::size_type i = 0; i < slots->size(); ++i)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(tss_data->mutex);
|
||||
(*tss_data->cleanup_handlers[i])((*slots)[i]);
|
||||
(*(*tss_data_cleanup_handlers)[i])((*slots)[i]);
|
||||
(*slots)[i] = 0;
|
||||
}
|
||||
tss_data_dec_use(lock);
|
||||
delete slots;
|
||||
}
|
||||
|
||||
void init_tss_data()
|
||||
{
|
||||
std::auto_ptr<tss_data_t> temp(new tss_data_t);
|
||||
std::auto_ptr<tss_data_cleanup_handlers_type> temp(new tss_data_cleanup_handlers_type);
|
||||
|
||||
std::auto_ptr<boost::mutex> temp_mutex(new boost::mutex);
|
||||
if (temp_mutex.get() == 0)
|
||||
throw boost::thread_resource_error();
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
//Force the cleanup implementation library to be linked in
|
||||
tss_cleanup_implemented();
|
||||
|
||||
//Allocate tls slot
|
||||
temp->native_key = TlsAlloc();
|
||||
if (temp->native_key == 0xFFFFFFFF)
|
||||
tss_data_native_key = TlsAlloc();
|
||||
if (tss_data_native_key == 0xFFFFFFFF)
|
||||
return;
|
||||
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
int res = pthread_key_create(&temp->native_key, &cleanup_slots);
|
||||
int res = pthread_key_create(&tss_data_native_key, &cleanup_slots);
|
||||
if (res != 0)
|
||||
return;
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
OSStatus status = MPAllocateTaskStorageIndex(&temp->native_key);
|
||||
OSStatus status = MPAllocateTaskStorageIndex(&tss_data_native_key);
|
||||
if (status != noErr)
|
||||
return;
|
||||
#endif
|
||||
|
||||
// Intentional memory "leak"
|
||||
// This is the only way to ensure the mutex in the global data
|
||||
// structure is available when cleanup handlers are run, since the
|
||||
// execution order of cleanup handlers is unspecified on any platform
|
||||
// with regards to C++ destructor ordering rules.
|
||||
tss_data = temp.release();
|
||||
// The life time of cleanup handlers and mutex is beeing
|
||||
// managed by a reference counting technique.
|
||||
// This avoids a memory leak by releasing the global data
|
||||
// after last use only, since the execution order of cleanup
|
||||
// handlers is unspecified on any platform with regards to
|
||||
// C++ destructor ordering rules.
|
||||
tss_data_cleanup_handlers = temp.release();
|
||||
tss_data_mutex = temp_mutex.release();
|
||||
}
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
@@ -105,13 +136,13 @@ tss_slots* get_slots(bool alloc)
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
slots = static_cast<tss_slots*>(
|
||||
TlsGetValue(tss_data->native_key));
|
||||
TlsGetValue(tss_data_native_key));
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
slots = static_cast<tss_slots*>(
|
||||
pthread_getspecific(tss_data->native_key));
|
||||
pthread_getspecific(tss_data_native_key));
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
slots = static_cast<tss_slots*>(
|
||||
MPGetTaskStorageValue(tss_data->native_key));
|
||||
MPGetTaskStorageValue(tss_data_native_key));
|
||||
#endif
|
||||
|
||||
if (slots == 0 && alloc)
|
||||
@@ -121,16 +152,19 @@ tss_slots* get_slots(bool alloc)
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
if (at_thread_exit(&tss_thread_exit) == -1)
|
||||
return 0;
|
||||
if (!TlsSetValue(tss_data->native_key, temp.get()))
|
||||
if (!TlsSetValue(tss_data_native_key, temp.get()))
|
||||
return 0;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
if (pthread_setspecific(tss_data->native_key, temp.get()) != 0)
|
||||
if (pthread_setspecific(tss_data_native_key, temp.get()) != 0)
|
||||
return 0;
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
if (MPSetTaskStorageValue(tss_data->native_key, temp.get()) != noErr)
|
||||
if (MPSetTaskStorageValue(tss_data_native_key, temp.get()) != noErr)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock lock(*tss_data_mutex);
|
||||
tss_data_inc_use(lock);
|
||||
}
|
||||
slots = temp.release();
|
||||
}
|
||||
|
||||
@@ -145,13 +179,14 @@ namespace detail {
|
||||
void tss::init(boost::function1<void, void*>* pcleanup)
|
||||
{
|
||||
boost::call_once(&init_tss_data, tss_data_once);
|
||||
if (tss_data == 0)
|
||||
if (tss_data_cleanup_handlers == 0)
|
||||
throw thread_resource_error();
|
||||
boost::mutex::scoped_lock lock(tss_data->mutex);
|
||||
boost::mutex::scoped_lock lock(*tss_data_mutex);
|
||||
try
|
||||
{
|
||||
tss_data->cleanup_handlers.push_back(pcleanup);
|
||||
m_slot = tss_data->cleanup_handlers.size() - 1;
|
||||
tss_data_cleanup_handlers->push_back(pcleanup);
|
||||
m_slot = tss_data_cleanup_handlers->size() - 1;
|
||||
tss_data_inc_use(lock);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@@ -159,6 +194,12 @@ void tss::init(boost::function1<void, void*>* pcleanup)
|
||||
}
|
||||
}
|
||||
|
||||
tss::~tss()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(*tss_data_mutex);
|
||||
tss_data_dec_use(lock);
|
||||
}
|
||||
|
||||
void* tss::get() const
|
||||
{
|
||||
tss_slots* slots = get_slots(false);
|
||||
@@ -196,8 +237,8 @@ void tss::set(void* value)
|
||||
|
||||
void tss::cleanup(void* value)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(tss_data->mutex);
|
||||
(*tss_data->cleanup_handlers[m_slot])(value);
|
||||
boost::mutex::scoped_lock lock(*tss_data_mutex);
|
||||
(*(*tss_data_cleanup_handlers)[m_slot])(value);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
#if defined(__BORLANDC__)
|
||||
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
#elif defined(_WIN32_WCE)
|
||||
extern "C" BOOL WINAPI DllMain(HANDLE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
#else
|
||||
extern "C" BOOL WINAPI DllMain(HINSTANCE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/)
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
// (C) Copyright Michael Glassford 2004.
|
||||
// Copyright (c) 2006 Peter Dimov
|
||||
// Copyright (c) 2006 Anthony Williams
|
||||
//
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -7,178 +10,152 @@
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
|
||||
#include <boost/thread/detail/tss_hooks.hpp>
|
||||
#include <boost/thread/detail/tss_hooks.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/once.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/thread/once.hpp>
|
||||
|
||||
#include <list>
|
||||
#include <list>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
namespace
|
||||
namespace
|
||||
{
|
||||
|
||||
typedef std::list<thread_exit_handler> thread_exit_handlers;
|
||||
|
||||
const DWORD invalid_tls_key = TLS_OUT_OF_INDEXES;
|
||||
DWORD tls_key = invalid_tls_key;
|
||||
|
||||
boost::once_flag once_init_tls_key = BOOST_ONCE_INIT;
|
||||
|
||||
void init_tls_key()
|
||||
{
|
||||
tls_key = TlsAlloc();
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
extern "C" BOOST_THREAD_DECL int at_thread_exit( thread_exit_handler exit_handler )
|
||||
{
|
||||
boost::call_once( init_tls_key, once_init_tls_key );
|
||||
|
||||
if( tls_key == invalid_tls_key )
|
||||
{
|
||||
typedef std::list<thread_exit_handler> thread_exit_handlers;
|
||||
|
||||
boost::once_flag once_init_threadmon_mutex = BOOST_ONCE_INIT;
|
||||
boost::mutex* threadmon_mutex;
|
||||
void init_threadmon_mutex(void)
|
||||
{
|
||||
threadmon_mutex = new boost::mutex;
|
||||
if (!threadmon_mutex)
|
||||
throw boost::thread_resource_error();
|
||||
}
|
||||
|
||||
const DWORD invalid_tls_key = TLS_OUT_OF_INDEXES;
|
||||
DWORD tls_key = invalid_tls_key;
|
||||
|
||||
unsigned long attached_thread_count = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
Calls to DllMain() and tls_callback() are serialized by the OS;
|
||||
however, calls to at_thread_exit are not, so it must be protected
|
||||
by a mutex. Since we already need a mutex for at_thread_exit(),
|
||||
and since there is no guarantee that on_process_enter(),
|
||||
on_process_exit(), on_thread_enter(), and on_thread_exit()
|
||||
will be called only from DllMain() or tls_callback(), it makes
|
||||
sense to protect those, too.
|
||||
*/
|
||||
// Get the exit handlers list for the current thread from tls.
|
||||
|
||||
extern "C" BOOST_THREAD_DECL int at_thread_exit(
|
||||
thread_exit_handler exit_handler
|
||||
)
|
||||
thread_exit_handlers* exit_handlers =
|
||||
static_cast< thread_exit_handlers* >( TlsGetValue( tls_key ) );
|
||||
|
||||
if( exit_handlers == 0 )
|
||||
{
|
||||
boost::call_once(init_threadmon_mutex, once_init_threadmon_mutex);
|
||||
boost::mutex::scoped_lock lock(*threadmon_mutex);
|
||||
|
||||
//Allocate a tls slot if necessary.
|
||||
|
||||
if (tls_key == invalid_tls_key)
|
||||
tls_key = TlsAlloc();
|
||||
|
||||
if (tls_key == invalid_tls_key)
|
||||
return -1;
|
||||
|
||||
//Get the exit handlers list for the current thread from tls.
|
||||
|
||||
thread_exit_handlers* exit_handlers =
|
||||
static_cast<thread_exit_handlers*>(TlsGetValue(tls_key));
|
||||
|
||||
if (!exit_handlers)
|
||||
{
|
||||
//No exit handlers list was created yet.
|
||||
|
||||
try
|
||||
{
|
||||
//Attempt to create a new exit handlers list.
|
||||
|
||||
exit_handlers = new thread_exit_handlers;
|
||||
if (!exit_handlers)
|
||||
return -1;
|
||||
|
||||
//Attempt to store the list pointer in tls.
|
||||
|
||||
if (TlsSetValue(tls_key, exit_handlers))
|
||||
++attached_thread_count;
|
||||
else
|
||||
{
|
||||
delete exit_handlers;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
//Like the C runtime library atexit() function,
|
||||
//functions should be called in the reverse of
|
||||
//the order they are added, so push them on the
|
||||
//front of the list.
|
||||
// No exit handlers list was created yet.
|
||||
|
||||
try
|
||||
{
|
||||
exit_handlers->push_front(exit_handler);
|
||||
// Attempt to create a new exit handlers list.
|
||||
|
||||
exit_handlers = new thread_exit_handlers;
|
||||
|
||||
if( exit_handlers == 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Attempt to store the list pointer in tls.
|
||||
|
||||
if( !TlsSetValue( tls_key, exit_handlers ) )
|
||||
{
|
||||
delete exit_handlers;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
catch( ... )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Like the atexit() function, a result of zero
|
||||
//indicates success.
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_process_enter(void)
|
||||
{
|
||||
boost::call_once(init_threadmon_mutex, once_init_threadmon_mutex);
|
||||
boost::mutex::scoped_lock lock(*threadmon_mutex);
|
||||
// Like the C runtime library atexit() function,
|
||||
// functions should be called in the reverse of
|
||||
// the order they are added, so push them on the
|
||||
// front of the list.
|
||||
|
||||
BOOST_ASSERT(attached_thread_count == 0);
|
||||
try
|
||||
{
|
||||
exit_handlers->push_front( exit_handler );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_process_exit(void)
|
||||
// Like the atexit() function, a result of zero
|
||||
// indicates success.
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_process_enter()
|
||||
{
|
||||
}
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_process_exit()
|
||||
{
|
||||
if( tls_key != invalid_tls_key )
|
||||
{
|
||||
boost::call_once(init_threadmon_mutex, once_init_threadmon_mutex);
|
||||
boost::mutex::scoped_lock lock(*threadmon_mutex);
|
||||
TlsFree(tls_key);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_ASSERT(attached_thread_count == 0);
|
||||
extern "C" BOOST_THREAD_DECL void on_thread_enter()
|
||||
{
|
||||
}
|
||||
|
||||
//Free the tls slot if one was allocated.
|
||||
extern "C" BOOST_THREAD_DECL void on_thread_exit()
|
||||
{
|
||||
// Initializing tls_key here ensures its proper visibility
|
||||
boost::call_once( init_tls_key, once_init_tls_key );
|
||||
|
||||
if (tls_key != invalid_tls_key)
|
||||
// Get the exit handlers list for the current thread from tls.
|
||||
|
||||
if( tls_key == invalid_tls_key )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
thread_exit_handlers* exit_handlers =
|
||||
static_cast< thread_exit_handlers* >( TlsGetValue( tls_key ) );
|
||||
|
||||
// If a handlers list was found, invoke its handlers.
|
||||
|
||||
if( exit_handlers != 0 )
|
||||
{
|
||||
// Call each handler and remove it from the list
|
||||
|
||||
while( !exit_handlers->empty() )
|
||||
{
|
||||
TlsFree(tls_key);
|
||||
tls_key = invalid_tls_key;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_thread_enter(void)
|
||||
{
|
||||
//boost::call_once(init_threadmon_mutex, once_init_threadmon_mutex);
|
||||
//boost::mutex::scoped_lock lock(*threadmon_mutex);
|
||||
}
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_thread_exit(void)
|
||||
{
|
||||
boost::call_once(init_threadmon_mutex, once_init_threadmon_mutex);
|
||||
boost::mutex::scoped_lock lock(*threadmon_mutex);
|
||||
|
||||
//Get the exit handlers list for the current thread from tls.
|
||||
|
||||
if (tls_key == invalid_tls_key)
|
||||
return;
|
||||
|
||||
thread_exit_handlers* exit_handlers =
|
||||
static_cast<thread_exit_handlers*>(TlsGetValue(tls_key));
|
||||
|
||||
//If a handlers list was found, use it.
|
||||
|
||||
if (exit_handlers && TlsSetValue(tls_key, 0))
|
||||
{
|
||||
BOOST_ASSERT(attached_thread_count > 0);
|
||||
--attached_thread_count;
|
||||
|
||||
lock.unlock();
|
||||
|
||||
//Call each handler and remove it from the list
|
||||
|
||||
while (!exit_handlers->empty())
|
||||
if( thread_exit_handler exit_handler = *exit_handlers->begin() )
|
||||
{
|
||||
if (thread_exit_handler exit_handler = *exit_handlers->begin())
|
||||
(*exit_handler)();
|
||||
exit_handlers->pop_front();
|
||||
(*exit_handler)();
|
||||
}
|
||||
|
||||
exit_handlers->pop_front();
|
||||
}
|
||||
|
||||
// If TlsSetValue fails, we can't delete the list,
|
||||
// since a second call to on_thread_exit will try
|
||||
// to access it.
|
||||
|
||||
if( TlsSetValue( tls_key, 0 ) )
|
||||
{
|
||||
delete exit_handlers;
|
||||
exit_handlers = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif //defined(BOOST_HAS_WINTHREADS)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
//Definitions required by implementation
|
||||
|
||||
#if (_MSC_VER < 1310) // 1310 == VC++ 7.1
|
||||
#if (_MSC_VER < 1300) // 1300 == VC++ 7.0
|
||||
typedef void (__cdecl *_PVFV)(void);
|
||||
#define INIRETSUCCESS
|
||||
#define PVAPI void
|
||||
@@ -48,7 +48,7 @@
|
||||
//The .CRT$Xxx information is taken from Codeguru:
|
||||
//http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/
|
||||
|
||||
#if (_MSC_VER >= 1310) // 1310 == VC++ 7.1
|
||||
#if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
|
||||
# pragma data_seg(push, old_seg)
|
||||
#endif
|
||||
//Callback to run tls glue code first.
|
||||
@@ -78,7 +78,7 @@
|
||||
#pragma data_seg(".CRT$XTU")
|
||||
static _PVFV p_process_term = on_process_term;
|
||||
#pragma data_seg()
|
||||
#if (_MSC_VER >= 1310) // 1310 == VC++ 7.1
|
||||
#if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
|
||||
# pragma data_seg(pop, old_seg)
|
||||
#endif
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
|
||||
DWORD volatile dw = _tls_used;
|
||||
|
||||
#if (_MSC_VER < 1310) // 1310 == VC++ 7.1
|
||||
#if (_MSC_VER < 1300) // 1300 == VC++ 7.0
|
||||
_TLSCB* pfbegin = __xl_a;
|
||||
_TLSCB* pfend = __xl_z;
|
||||
_TLSCB* pfdst = pfbegin;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
@@ -27,6 +22,8 @@
|
||||
# include <boost/thread/detail/force_cast.hpp>
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace boost {
|
||||
|
||||
#ifdef BOOST_HAS_MPTASKS
|
||||
@@ -111,13 +108,23 @@ int xtime_get(struct xtime* xtp, int clock_type)
|
||||
return clock_type;
|
||||
#elif defined(BOOST_HAS_GETTIMEOFDAY)
|
||||
struct timeval tv;
|
||||
# ifndef NDEBUG
|
||||
int res =
|
||||
#endif
|
||||
gettimeofday(&tv, 0);
|
||||
assert(0 == res);
|
||||
assert(tv.tv_sec >= 0);
|
||||
assert(tv.tv_usec >= 0);
|
||||
xtp->sec = tv.tv_sec;
|
||||
xtp->nsec = tv.tv_usec * 1000;
|
||||
return clock_type;
|
||||
#elif defined(BOOST_HAS_CLOCK_GETTIME)
|
||||
timespec ts;
|
||||
# ifndef NDEBUG
|
||||
int res =
|
||||
# endif
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
assert(0 == res);
|
||||
xtp->sec = ts.tv_sec;
|
||||
xtp->nsec = ts.tv_nsec;
|
||||
return clock_type;
|
||||
|
||||
83
test/Jamfile
83
test/Jamfile
@@ -1,83 +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.
|
||||
#
|
||||
# Boost.Threads test Jamfile
|
||||
#
|
||||
# Additional configuration variables used:
|
||||
# See threads.jam.
|
||||
|
||||
# Declare the location of this subproject relative to the root.
|
||||
subproject libs/thread/test ;
|
||||
|
||||
# Include threads.jam for Boost.Threads global build information.
|
||||
# This greatly simplifies the Jam code needed to configure the build
|
||||
# for the various Win32 build types.
|
||||
import ../build/threads ;
|
||||
|
||||
# bring in rules for testing
|
||||
import testing ;
|
||||
|
||||
{
|
||||
template boost_thread_test_lib
|
||||
: ## sources ##
|
||||
<template>thread_base
|
||||
../src/tss_null.cpp
|
||||
<lib>../build/boost_thread
|
||||
<lib>../../test/build/boost_unit_test_framework
|
||||
#<lib>../../test/build/boost_test_exec_monitor
|
||||
: ## requirements ##
|
||||
<sysinclude>$(BOOST_ROOT) #:should be unnecessary (because already included in thread_base)
|
||||
<define>BOOST_ALL_NO_LIB=1
|
||||
<define>BOOST_THREAD_USE_LIB=1
|
||||
<define>BOOST_THREAD_TEST=1
|
||||
<runtime-link>static
|
||||
<threading>multi
|
||||
: ## default build ##
|
||||
;
|
||||
|
||||
template boost_thread_test_dll
|
||||
: ## sources ##
|
||||
<template>thread_base
|
||||
../src/tss_null.cpp
|
||||
<dll>../build/boost_thread
|
||||
<lib>../../test/build/boost_unit_test_framework
|
||||
#<lib>../../test/build/boost_test_exec_monitor
|
||||
: ## requirements ##
|
||||
<sysinclude>$(BOOST_ROOT) #:should be unnecessary (because already included in thread_base)
|
||||
<define>BOOST_ALL_NO_LIB=1
|
||||
<define>BOOST_THREAD_USE_DLL=1
|
||||
<define>BOOST_THREAD_TEST=1
|
||||
<runtime-link>dynamic
|
||||
<threading>multi
|
||||
: ## default build ##
|
||||
;
|
||||
|
||||
test-suite "threads"
|
||||
:
|
||||
[ run test_thread.cpp <template>boost_thread_test_dll ]
|
||||
[ run test_mutex.cpp <template>boost_thread_test_dll ]
|
||||
[ run test_condition.cpp <template>boost_thread_test_dll ]
|
||||
[ run test_tss.cpp <template>boost_thread_test_dll ]
|
||||
[ 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 ]
|
||||
[ run test_condition.cpp <template>boost_thread_test_lib : : : : test_condition_lib ]
|
||||
[ run test_tss.cpp <template>boost_thread_test_lib : : : : test_tss_lib ]
|
||||
[ 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 ]
|
||||
;
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
# (C) Copyright William E. Kempf 2001. Permission to copy, use, modify, sell
|
||||
# and distribute this software is granted provided this copyright notice
|
||||
# appears in all copies. This software is provided "as is" without express or
|
||||
# implied warranty, and with no claim as to its suitability for any purpose.
|
||||
# (C) Copyright William E. Kempf 2001.
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# Boost.Threads test Jamfile
|
||||
#
|
||||
@@ -19,18 +18,28 @@
|
||||
import testing ;
|
||||
|
||||
project
|
||||
: requirements <library>../build//boost_thread
|
||||
<library>../../test/build//boost_unit_test_framework
|
||||
: requirements <library>/boost/test//boost_unit_test_framework/<link>static
|
||||
<threading>multi
|
||||
;
|
||||
|
||||
rule thread-run ( sources )
|
||||
{
|
||||
return
|
||||
[ run $(sources) ../build//boost_thread ]
|
||||
[ run $(sources) ../src/tss_null.cpp ../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 ]
|
||||
[ thread-run test_read_write_mutex.cpp ]
|
||||
;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
@@ -48,7 +43,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*[])
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
@@ -17,7 +12,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,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
@@ -17,314 +14,767 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#define TS_CHECK(pred) \
|
||||
do { if (!(pred)) BOOST_ERROR (#pred); } while (0)
|
||||
#define TS_CHECK_MSG(pred, msg) \
|
||||
do { if (!(pred)) BOOST_ERROR (msg); } while (0)
|
||||
|
||||
namespace {
|
||||
|
||||
int shared_val = 0;
|
||||
|
||||
boost::xtime xsecs(int secs)
|
||||
{
|
||||
//Create an xtime that is secs seconds from now
|
||||
boost::xtime ret;
|
||||
BOOST_TEST(boost::TIME_UTC == boost::xtime_get(&ret, boost::TIME_UTC));
|
||||
TS_CHECK (boost::TIME_UTC == boost::xtime_get(&ret, boost::TIME_UTC));
|
||||
ret.sec += secs;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define MESSAGE "w1=" << w1.value_ << ", w2=" << w2.value_ << ", r1=" << r1.value_ << ", r2=" << r2.value_
|
||||
|
||||
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); }
|
||||
|
||||
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;
|
||||
|
||||
void (*func_)(void*, RW&);
|
||||
void* param1_;
|
||||
RW& param2_;
|
||||
};
|
||||
|
||||
const int k_data_init = -1;
|
||||
|
||||
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;
|
||||
data(
|
||||
int id,
|
||||
RW& m,
|
||||
int wait_for_lock_secs,
|
||||
int sleep_with_lock_secs,
|
||||
bool demote_after_write = false
|
||||
)
|
||||
: id_(id)
|
||||
, wait_for_lock_secs_(wait_for_lock_secs)
|
||||
, sleep_with_lock_secs_(sleep_with_lock_secs)
|
||||
, test_promotion_and_demotion_(demote_after_write)
|
||||
, value_(k_data_init)
|
||||
, rw_(m)
|
||||
{}
|
||||
|
||||
RW& m_rw; // Reader/Writer mutex
|
||||
int id_;
|
||||
int wait_for_lock_secs_;
|
||||
int sleep_with_lock_secs_;
|
||||
bool test_promotion_and_demotion_;
|
||||
int value_;
|
||||
|
||||
RW& rw_;
|
||||
};
|
||||
|
||||
// plain_writer excercises the "infinite" lock for each
|
||||
// read_write_mutex type.
|
||||
|
||||
template<typename RW>
|
||||
void plain_writer(void *arg,RW &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())
|
||||
try
|
||||
{
|
||||
data<RW>* pdata = (data<RW>*) arg;
|
||||
TS_CHECK_MSG(pdata->wait_for_lock_secs_ == 0, "pdata->wait_for_lock_secs_: " << pdata->wait_for_lock_secs_);
|
||||
|
||||
boost::thread::sleep(xsecs(3));
|
||||
shared_val += 10;
|
||||
typename RW::scoped_read_write_lock l(
|
||||
rw,
|
||||
pdata->test_promotion_and_demotion_
|
||||
? boost::read_write_lock_state::read_locked
|
||||
: boost::read_write_lock_state::write_locked
|
||||
);
|
||||
|
||||
pdata->m_value = shared_val;
|
||||
bool succeeded = true;
|
||||
|
||||
if (pdata->test_promotion_and_demotion_)
|
||||
{
|
||||
try
|
||||
{
|
||||
l.promote();
|
||||
}
|
||||
catch(const boost::lock_error&)
|
||||
{
|
||||
succeeded = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (succeeded)
|
||||
{
|
||||
if (pdata->sleep_with_lock_secs_ > 0)
|
||||
boost::thread::sleep(xsecs(pdata->sleep_with_lock_secs_));
|
||||
|
||||
shared_val += 10;
|
||||
|
||||
if (pdata->test_promotion_and_demotion_)
|
||||
l.demote();
|
||||
|
||||
pdata->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())
|
||||
catch(...)
|
||||
{
|
||||
pdata->m_value = shared_val;
|
||||
TS_CHECK_MSG(false, "plain_writer() exception!");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename RW>
|
||||
void timed_writer(void *arg,RW &rw)
|
||||
void plain_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_write_lock(xt))
|
||||
try
|
||||
{
|
||||
boost::thread::sleep(xsecs(3));
|
||||
shared_val += 10;
|
||||
data<RW>* pdata = (data<RW>*)arg;
|
||||
TS_CHECK(!pdata->test_promotion_and_demotion_);
|
||||
TS_CHECK_MSG(pdata->wait_for_lock_secs_ == 0, "pdata->wait_for_lock_secs_: " << pdata->wait_for_lock_secs_);
|
||||
|
||||
pdata->m_value = shared_val;
|
||||
typename RW::scoped_read_write_lock l(rw, boost::read_write_lock_state::read_locked);
|
||||
|
||||
if (pdata->sleep_with_lock_secs_ > 0)
|
||||
boost::thread::sleep(xsecs(pdata->sleep_with_lock_secs_));
|
||||
|
||||
pdata->value_ = shared_val;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
TS_CHECK_MSG(false, "plain_reader() exception!");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename RW>
|
||||
void timed_reader(void *arg,RW &rw)
|
||||
void try_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_read_lock(xt))
|
||||
try
|
||||
{
|
||||
pdata->m_value = shared_val;
|
||||
data<RW>* pdata = (data<RW>*) arg;
|
||||
TS_CHECK_MSG(pdata->wait_for_lock_secs_ == 0, "pdata->wait_for_lock_secs_: " << pdata->wait_for_lock_secs_);
|
||||
|
||||
typename RW::scoped_try_read_write_lock l(rw, boost::read_write_lock_state::unlocked);
|
||||
|
||||
bool succeeded = false;
|
||||
|
||||
if (pdata->test_promotion_and_demotion_)
|
||||
succeeded = l.try_read_lock() && l.try_promote();
|
||||
else
|
||||
succeeded = l.try_write_lock();
|
||||
|
||||
if (succeeded)
|
||||
{
|
||||
if (pdata->sleep_with_lock_secs_ > 0)
|
||||
boost::thread::sleep(xsecs(pdata->sleep_with_lock_secs_));
|
||||
|
||||
shared_val += 10;
|
||||
|
||||
if (pdata->test_promotion_and_demotion_)
|
||||
l.demote();
|
||||
|
||||
pdata->value_ = shared_val;
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
TS_CHECK_MSG(false, "try_writer() exception!");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename RW>
|
||||
void dump_times(const char *prefix,data<RW> *pdata)
|
||||
void try_reader(void*arg, RW& rw)
|
||||
{
|
||||
std::cout << " " << prefix << pdata->m_id <<
|
||||
" In:" << pdata->m_start.LowPart <<
|
||||
" Holding:" << pdata->m_holding.LowPart <<
|
||||
" Out: " << pdata->m_end.LowPart << std::endl;
|
||||
try
|
||||
{
|
||||
data<RW>* pdata = (data<RW>*)arg;
|
||||
TS_CHECK(!pdata->test_promotion_and_demotion_);
|
||||
TS_CHECK_MSG(pdata->wait_for_lock_secs_ == 0, "pdata->wait_for_lock_secs_: " << pdata->wait_for_lock_secs_);
|
||||
|
||||
typename RW::scoped_try_read_write_lock l(rw, boost::read_write_lock_state::unlocked);
|
||||
|
||||
if (l.try_read_lock())
|
||||
{
|
||||
if (pdata->sleep_with_lock_secs_ > 0)
|
||||
boost::thread::sleep(xsecs(pdata->sleep_with_lock_secs_));
|
||||
|
||||
pdata->value_ = shared_val;
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
TS_CHECK_MSG(false, "try_reader() exception!");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename RW>
|
||||
void test_plain_read_write_mutex(RW &rw)
|
||||
void timed_writer(void* arg, RW& rw)
|
||||
{
|
||||
try
|
||||
{
|
||||
data<RW>* pdata = (data<RW>*)arg;
|
||||
|
||||
typename RW::scoped_timed_read_write_lock l(rw, boost::read_write_lock_state::unlocked);
|
||||
|
||||
bool succeeded = false;
|
||||
|
||||
boost::xtime xt = xsecs(pdata->wait_for_lock_secs_);
|
||||
if (pdata->test_promotion_and_demotion_)
|
||||
succeeded = l.timed_read_lock(xt) && l.timed_promote(xt);
|
||||
else
|
||||
succeeded = l.timed_write_lock(xt);
|
||||
|
||||
if (succeeded)
|
||||
{
|
||||
if (pdata->sleep_with_lock_secs_ > 0)
|
||||
boost::thread::sleep(xsecs(pdata->sleep_with_lock_secs_));
|
||||
|
||||
shared_val += 10;
|
||||
|
||||
if (pdata->test_promotion_and_demotion_)
|
||||
l.demote();
|
||||
|
||||
pdata->value_ = shared_val;
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
TS_CHECK_MSG(false, "timed_writer() exception!");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename RW>
|
||||
void timed_reader(void* arg, RW& rw)
|
||||
{
|
||||
try
|
||||
{
|
||||
data<RW>* pdata = (data<RW>*)arg;
|
||||
TS_CHECK(!pdata->test_promotion_and_demotion_);
|
||||
|
||||
typename RW::scoped_timed_read_write_lock l(rw,boost::read_write_lock_state::unlocked);
|
||||
|
||||
boost::xtime xt = xsecs(pdata->wait_for_lock_secs_);
|
||||
if (l.timed_read_lock(xt))
|
||||
{
|
||||
if (pdata->sleep_with_lock_secs_ > 0)
|
||||
boost::thread::sleep(xsecs(pdata->sleep_with_lock_secs_));
|
||||
|
||||
pdata->value_ = shared_val;
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
TS_CHECK_MSG(false, "timed_reader() exception!");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename RW>
|
||||
void clear_data(data<RW>& data1, data<RW>& data2, data<RW>& data3, data<RW>& data4)
|
||||
{
|
||||
shared_val = 0;
|
||||
data<RW> r1(1,rw);
|
||||
data<RW> r2(2,rw);
|
||||
data<RW> w1(1,rw);
|
||||
data<RW> w2(2,rw);
|
||||
data1.value_ = k_data_init;
|
||||
data2.value_ = k_data_init;
|
||||
data3.value_ = k_data_init;
|
||||
data4.value_ = k_data_init;
|
||||
}
|
||||
|
||||
// Writer one launches, holds the lock for 3 seconds.
|
||||
boost::thread tw1(thread_adapter<RW>(plain_writer,&w1,rw));
|
||||
bool shared_test_writelocked = false;
|
||||
bool shared_test_readlocked = false;
|
||||
bool shared_test_unlocked = false;
|
||||
|
||||
// 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)
|
||||
template<typename RW>
|
||||
void run_try_tests(void* arg, RW& rw)
|
||||
{
|
||||
try
|
||||
{
|
||||
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);
|
||||
TS_CHECK(shared_test_writelocked || shared_test_readlocked || shared_test_unlocked);
|
||||
|
||||
typename RW::scoped_try_read_write_lock l(rw, boost::read_write_lock_state::unlocked);
|
||||
|
||||
if (shared_test_writelocked)
|
||||
{
|
||||
//Verify that write lock blocks other write locks
|
||||
TS_CHECK(!l.try_write_lock());
|
||||
|
||||
//Verify that write lock blocks read locks
|
||||
TS_CHECK(!l.try_read_lock());
|
||||
}
|
||||
else if (shared_test_readlocked)
|
||||
{
|
||||
//Verify that read lock blocks write locks
|
||||
TS_CHECK(!l.try_write_lock());
|
||||
|
||||
//Verify that read lock does not block other read locks
|
||||
TS_CHECK(l.try_read_lock());
|
||||
|
||||
//Verify that read lock blocks promotion
|
||||
TS_CHECK(!l.try_promote());
|
||||
}
|
||||
else if (shared_test_unlocked)
|
||||
{
|
||||
//Verify that unlocked does not blocks write locks
|
||||
TS_CHECK(l.try_write_lock());
|
||||
|
||||
//Verify that unlocked does not block demotion
|
||||
TS_CHECK(l.try_demote());
|
||||
|
||||
l.unlock();
|
||||
|
||||
//Verify that unlocked does not block read locks
|
||||
TS_CHECK(l.try_read_lock());
|
||||
|
||||
//Verify that unlocked does not block promotion
|
||||
TS_CHECK(l.try_promote());
|
||||
|
||||
l.unlock();
|
||||
}
|
||||
}
|
||||
else if (rw.policy() == boost::read_write_scheduling_policy::reader_priority)
|
||||
catch(...)
|
||||
{
|
||||
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));
|
||||
TS_CHECK_MSG(false, "run_try_tests() exception!");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename RW>
|
||||
void test_try_read_write_mutex(RW &rw)
|
||||
void test_plain_read_write_mutex(RW& rw, bool test_promotion_and_demotion)
|
||||
{
|
||||
data<RW> r1(1,rw);
|
||||
data<RW> w1(2,rw);
|
||||
data<RW> w2(3,rw);
|
||||
//Verify that a write lock prevents both readers and writers from obtaining a lock
|
||||
{
|
||||
shared_val = 0;
|
||||
data<RW> r1(1, rw, 0, 0);
|
||||
data<RW> r2(2, rw, 0, 0);
|
||||
data<RW> w1(3, rw, 0, 0);
|
||||
data<RW> w2(4, rw, 0, 0);
|
||||
|
||||
// We start with some specialized tests for "try" behavior
|
||||
//Write-lock the mutex and queue up other readers and writers
|
||||
|
||||
shared_val = 0;
|
||||
typename RW::scoped_read_write_lock l(rw, boost::read_write_lock_state::write_locked);
|
||||
|
||||
// Writer one launches, holds the lock for 3 seconds.
|
||||
boost::thread tr1(thread_adapter<RW>(plain_reader, &r1, rw));
|
||||
boost::thread tr2(thread_adapter<RW>(plain_reader, &r2, rw));
|
||||
boost::thread tw1(thread_adapter<RW>(plain_writer, &w1, rw));
|
||||
boost::thread tw2(thread_adapter<RW>(plain_writer, &w2, rw));
|
||||
|
||||
boost::thread tw1(thread_adapter<RW>(try_writer,&w1,rw));
|
||||
boost::thread::sleep(xsecs(1));
|
||||
|
||||
// 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));
|
||||
//At this point, neither queued readers nor queued writers should have obtained access
|
||||
|
||||
// Writer two launches in the same timeframe.
|
||||
boost::thread tw2(thread_adapter<RW>(try_writer,&w2,rw));
|
||||
TS_CHECK_MSG(w1.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(w2.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(r2.value_ == k_data_init, MESSAGE);
|
||||
|
||||
tw2.join();
|
||||
tr1.join();
|
||||
tw1.join();
|
||||
if (test_promotion_and_demotion)
|
||||
{
|
||||
l.demote();
|
||||
boost::thread::sleep(xsecs(1));
|
||||
//:boost::thread tr3(thread_adapter<RW>(plain_reader, &r3, rw));
|
||||
|
||||
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
|
||||
if (rw.policy() == boost::read_write_scheduling_policy::writer_priority)
|
||||
{
|
||||
//Expected result:
|
||||
//Since writers have priority, demotion doesn't release any readers.
|
||||
TS_CHECK_MSG(w1.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(w2.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(r2.value_ == k_data_init, MESSAGE);
|
||||
}
|
||||
else if (rw.policy() == boost::read_write_scheduling_policy::reader_priority)
|
||||
{
|
||||
//Expected result:
|
||||
//Since readers have priority, demotion releases all readers.
|
||||
TS_CHECK_MSG(w1.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(w2.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ == 0, MESSAGE);
|
||||
TS_CHECK_MSG(r2.value_ == 0, MESSAGE);
|
||||
}
|
||||
else if (rw.policy() == boost::read_write_scheduling_policy::alternating_many_reads)
|
||||
{
|
||||
//Expected result:
|
||||
//Since readers can be released many at a time, demotion releases all queued readers.
|
||||
TS_CHECK_MSG(w1.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(w2.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ == 0, MESSAGE);
|
||||
TS_CHECK_MSG(r2.value_ == 0, MESSAGE);
|
||||
//:TS_CHECK_MSG(r3.value_ == k_data_init, MESSAGE);
|
||||
}
|
||||
else if (rw.policy() == boost::read_write_scheduling_policy::alternating_single_read)
|
||||
{
|
||||
//Expected result:
|
||||
//Since readers can be released only one at a time, demotion releases one queued reader.
|
||||
TS_CHECK_MSG(w1.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(w2.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ == k_data_init || r1.value_ == 0, MESSAGE);
|
||||
TS_CHECK_MSG(r2.value_ == k_data_init || r2.value_ == 0, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ != r2.value_, MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
l.unlock();
|
||||
|
||||
// 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);
|
||||
tr2.join();
|
||||
tr1.join();
|
||||
tw2.join();
|
||||
tw1.join();
|
||||
|
||||
if (rw.policy() == boost::read_write_scheduling_policy::writer_priority)
|
||||
{
|
||||
if (!test_promotion_and_demotion)
|
||||
{
|
||||
//Expected result:
|
||||
//1) either w1 or w2 obtains and releases the lock
|
||||
//2) the other of w1 and w2 obtains and releases the lock
|
||||
//3) r1 and r2 obtain and release the lock "simultaneously"
|
||||
TS_CHECK_MSG(w1.value_ == 10 || w1.value_ == 20, MESSAGE);
|
||||
TS_CHECK_MSG(w2.value_ == 10 || w2.value_ == 20, MESSAGE);
|
||||
TS_CHECK_MSG(w1.value_ != w2.value_, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ == 20, MESSAGE);
|
||||
TS_CHECK_MSG(r2.value_ == 20, MESSAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Expected result:
|
||||
//The same, except that either w1 or w2 (but not both) may
|
||||
//fail to promote to a write lock,
|
||||
//and r1, r2, or both may "sneak in" ahead of w1 and/or w2
|
||||
//by obtaining a read lock before w1 or w2 can promote
|
||||
//their initial read lock to a write lock.
|
||||
TS_CHECK_MSG(w1.value_ == k_data_init || w1.value_ == 10 || w1.value_ == 20, MESSAGE);
|
||||
TS_CHECK_MSG(w2.value_ == k_data_init || w2.value_ == 10 || w2.value_ == 20, MESSAGE);
|
||||
TS_CHECK_MSG(w1.value_ != w2.value_, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ == k_data_init || r1.value_ == 10 || r1.value_ == 20, MESSAGE);
|
||||
TS_CHECK_MSG(r2.value_ == k_data_init || r2.value_ == 10 || r2.value_ == 20, MESSAGE);
|
||||
}
|
||||
}
|
||||
else if (rw.policy() == boost::read_write_scheduling_policy::reader_priority)
|
||||
{
|
||||
if (!test_promotion_and_demotion)
|
||||
{
|
||||
//Expected result:
|
||||
//1) r1 and r2 obtain and release the lock "simultaneously"
|
||||
//2) either w1 or w2 obtains and releases the lock
|
||||
//3) the other of w1 and w2 obtains and releases the lock
|
||||
TS_CHECK_MSG(w1.value_ == 10 || w1.value_ == 20, MESSAGE);
|
||||
TS_CHECK_MSG(w2.value_ == 10 || w2.value_ == 20, MESSAGE);
|
||||
TS_CHECK_MSG(w1.value_ != w2.value_, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ == 0, MESSAGE);
|
||||
TS_CHECK_MSG(r2.value_ == 0, MESSAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Expected result:
|
||||
//The same, except that either w1 or w2 (but not both) may
|
||||
//fail to promote to a write lock.
|
||||
TS_CHECK_MSG(w1.value_ == k_data_init || w1.value_ == 10 || w1.value_ == 20, MESSAGE);
|
||||
TS_CHECK_MSG(w2.value_ == k_data_init || w2.value_ == 10 || w2.value_ == 20, MESSAGE);
|
||||
TS_CHECK_MSG(w1.value_ != w2.value_, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ == 0, MESSAGE);
|
||||
TS_CHECK_MSG(r2.value_ == 0, MESSAGE);
|
||||
}
|
||||
}
|
||||
else if (rw.policy() == boost::read_write_scheduling_policy::alternating_many_reads)
|
||||
{
|
||||
if (!test_promotion_and_demotion)
|
||||
{
|
||||
//Expected result:
|
||||
//1) r1 and r2 obtain and release the lock "simultaneously"
|
||||
//2) either w1 or w2 obtains and releases the lock
|
||||
//3) the other of w1 and w2 obtains and releases the lock
|
||||
TS_CHECK_MSG(w1.value_ == 10 || w1.value_ == 20, MESSAGE);
|
||||
TS_CHECK_MSG(w2.value_ == 10 || w2.value_ == 20, MESSAGE);
|
||||
TS_CHECK_MSG(w1.value_ != w2.value_, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ == 0, MESSAGE);
|
||||
TS_CHECK_MSG(r2.value_ == 0, MESSAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Expected result:
|
||||
//The same, except that either w1 or w2 (but not both) may
|
||||
//fail to promote to a write lock.
|
||||
TS_CHECK_MSG(w1.value_ == k_data_init || w1.value_ == 10 || w1.value_ == 20, MESSAGE);
|
||||
TS_CHECK_MSG(w2.value_ == k_data_init || w2.value_ == 10 || w2.value_ == 20, MESSAGE);
|
||||
TS_CHECK_MSG(w1.value_ != w2.value_, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ == 0, MESSAGE);
|
||||
TS_CHECK_MSG(r2.value_ == 0, MESSAGE);
|
||||
}
|
||||
}
|
||||
else if (rw.policy() == boost::read_write_scheduling_policy::alternating_single_read)
|
||||
{
|
||||
if (!test_promotion_and_demotion)
|
||||
{
|
||||
//Expected result:
|
||||
//1) either r1 or r2 obtains and releases the lock
|
||||
//2) either w1 or w2 obtains and releases the lock
|
||||
//3) the other of r1 and r2 obtains and releases the lock
|
||||
//4) the other of w1 and w2 obtains and release the lock
|
||||
TS_CHECK_MSG(w1.value_ == 10 || w1.value_ == 20, MESSAGE);
|
||||
TS_CHECK_MSG(w2.value_ == 10 || w2.value_ == 20, MESSAGE);
|
||||
TS_CHECK_MSG(w1.value_ != w2.value_, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ == 0 || r1.value_ == 10, MESSAGE);
|
||||
TS_CHECK_MSG(r2.value_ == 0 || r2.value_ == 10, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ != r2.value_, MESSAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Expected result:
|
||||
//Since w1 and w2 start as read locks, r1, r2, w1, and w2
|
||||
//obtain read locks "simultaneously". Each of w1 and w2,
|
||||
//after it obtain a read lock, attempts to promote to a
|
||||
//write lock; this attempt fails if the other has
|
||||
//already done so and currently holds the write lock;
|
||||
//otherwise it will succeed as soon as any other
|
||||
//read locks have been released.
|
||||
//In other words, any ordering is possible, and either
|
||||
//w1 or w2 (but not both) may fail to obtain the lock
|
||||
//altogether.
|
||||
TS_CHECK_MSG(w1.value_ == k_data_init || w1.value_ == 10 || w1.value_ == 20, MESSAGE);
|
||||
TS_CHECK_MSG(w2.value_ == k_data_init || w2.value_ == 10 || w2.value_ == 20, MESSAGE);
|
||||
TS_CHECK_MSG(w1.value_ != w2.value_, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ == 0 || r1.value_ == 10 || r1.value_ == 20, MESSAGE);
|
||||
TS_CHECK_MSG(r2.value_ == 0 || r2.value_ == 10 || r2.value_ == 20, MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Verify that a read lock prevents readers but not writers from obtaining a lock
|
||||
{
|
||||
shared_val = 0;
|
||||
data<RW> r1(1, rw, 0, 0);
|
||||
data<RW> r2(2, rw, 0, 0);
|
||||
data<RW> w1(3, rw, 0, 0);
|
||||
data<RW> w2(4, rw, 0, 0);
|
||||
|
||||
//Read-lock the mutex and queue up other readers and writers
|
||||
|
||||
typename RW::scoped_read_write_lock l(rw, boost::read_write_lock_state::read_locked);
|
||||
|
||||
boost::thread tr1(thread_adapter<RW>(plain_reader, &r1, rw));
|
||||
boost::thread tr2(thread_adapter<RW>(plain_reader, &r2, rw));
|
||||
|
||||
boost::thread::sleep(xsecs(1));
|
||||
|
||||
boost::thread tw1(thread_adapter<RW>(plain_writer, &w1, rw));
|
||||
boost::thread tw2(thread_adapter<RW>(plain_writer, &w2, rw));
|
||||
|
||||
boost::thread::sleep(xsecs(1));
|
||||
|
||||
//Expected result: all readers passed through before the writers entered
|
||||
TS_CHECK_MSG(w1.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(w2.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ == 0, MESSAGE);
|
||||
TS_CHECK_MSG(r2.value_ == 0, MESSAGE);
|
||||
|
||||
if (test_promotion_and_demotion)
|
||||
{
|
||||
l.promote();
|
||||
}
|
||||
|
||||
l.unlock();
|
||||
|
||||
tr2.join();
|
||||
tr1.join();
|
||||
tw2.join();
|
||||
tw1.join();
|
||||
}
|
||||
|
||||
//Verify that a read lock prevents readers but not writers from obtaining a lock
|
||||
{
|
||||
shared_val = 0;
|
||||
data<RW> r1(1, rw, 0, 0);
|
||||
data<RW> r2(2, rw, 0, 0);
|
||||
data<RW> w1(3, rw, 0, 0);
|
||||
data<RW> w2(4, rw, 0, 0);
|
||||
|
||||
//Read-lock the mutex and queue up other readers and writers
|
||||
|
||||
typename RW::scoped_read_write_lock l(rw, boost::read_write_lock_state::read_locked);
|
||||
|
||||
boost::thread tw1(thread_adapter<RW>(plain_writer, &w1, rw));
|
||||
boost::thread tw2(thread_adapter<RW>(plain_writer, &w2, rw));
|
||||
|
||||
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));
|
||||
|
||||
boost::thread::sleep(xsecs(1));
|
||||
|
||||
if (rw.policy() == boost::read_write_scheduling_policy::writer_priority)
|
||||
{
|
||||
//Expected result:
|
||||
//Writers have priority, so no readers have been released
|
||||
TS_CHECK_MSG(w1.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(w2.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(r2.value_ == k_data_init, MESSAGE);
|
||||
}
|
||||
else if (rw.policy() == boost::read_write_scheduling_policy::reader_priority)
|
||||
{
|
||||
//Expected result:
|
||||
//Readers have priority, so all readers have been released
|
||||
TS_CHECK_MSG(w1.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(w2.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ == 0, MESSAGE);
|
||||
TS_CHECK_MSG(r2.value_ == 0, MESSAGE);
|
||||
}
|
||||
else if (rw.policy() == boost::read_write_scheduling_policy::alternating_many_reads)
|
||||
{
|
||||
//Expected result:
|
||||
//It's the writers' turn, so no readers have been released
|
||||
TS_CHECK_MSG(w1.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(w2.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(r2.value_ == k_data_init, MESSAGE);
|
||||
}
|
||||
else if (rw.policy() == boost::read_write_scheduling_policy::alternating_single_read)
|
||||
{
|
||||
//Expected result:
|
||||
//It's the writers' turn, so no readers have been released
|
||||
TS_CHECK_MSG(w1.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(w2.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(r1.value_ == k_data_init, MESSAGE);
|
||||
TS_CHECK_MSG(r2.value_ == k_data_init, MESSAGE);
|
||||
}
|
||||
|
||||
if (test_promotion_and_demotion)
|
||||
{
|
||||
l.promote();
|
||||
}
|
||||
|
||||
l.unlock();
|
||||
|
||||
tr2.join();
|
||||
tr1.join();
|
||||
tw2.join();
|
||||
tw1.join();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename RW>
|
||||
void test_timed_read_write_mutex(RW &rw)
|
||||
void test_try_read_write_mutex(RW& rw, bool test_promotion_and_demotion)
|
||||
{
|
||||
data<RW> r1(1,rw,1);
|
||||
data<RW> r2(2,rw,3);
|
||||
data<RW> w1(3,rw,3);
|
||||
data<RW> w2(4,rw,1);
|
||||
//Repeat the plain tests with the try lock.
|
||||
//This is important to verify that try locks are proper
|
||||
//read_write_mutexes as well.
|
||||
|
||||
// We begin with some specialized tests for "timed" behavior
|
||||
test_plain_read_write_mutex(rw, test_promotion_and_demotion);
|
||||
|
||||
shared_val = 0;
|
||||
//Verify try_* operations with write-locked mutex
|
||||
{
|
||||
typename RW::scoped_try_read_write_lock l(rw, boost::read_write_lock_state::write_locked);
|
||||
|
||||
// Writer one will hold the lock for 3 seconds.
|
||||
boost::thread tw1(thread_adapter<RW>(timed_writer,&w1,rw));
|
||||
shared_test_writelocked = true;
|
||||
shared_test_readlocked = false;
|
||||
shared_test_unlocked = false;
|
||||
|
||||
boost::thread test_thread(thread_adapter<RW>(run_try_tests, NULL, rw));
|
||||
test_thread.join();
|
||||
}
|
||||
|
||||
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));
|
||||
//Verify try_* operations with read-locked mutex
|
||||
{
|
||||
typename RW::scoped_try_read_write_lock l(rw, boost::read_write_lock_state::read_locked);
|
||||
|
||||
shared_test_writelocked = false;
|
||||
shared_test_readlocked = true;
|
||||
shared_test_unlocked = false;
|
||||
|
||||
boost::thread test_thread(thread_adapter<RW>(run_try_tests, NULL, rw));
|
||||
test_thread.join();
|
||||
}
|
||||
|
||||
// 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.
|
||||
//Verify try_* operations with unlocked mutex
|
||||
{
|
||||
shared_test_writelocked = false;
|
||||
shared_test_readlocked = false;
|
||||
shared_test_unlocked = true;
|
||||
|
||||
boost::thread test_thread(thread_adapter<RW>(run_try_tests, NULL, rw));
|
||||
test_thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
boost::thread tr1(thread_adapter<RW>(timed_reader,&r1,rw));
|
||||
boost::thread tr2(thread_adapter<RW>(timed_reader,&r2,rw));
|
||||
template<typename RW>
|
||||
void test_timed_read_write_mutex(RW& rw, bool test_promotion_and_demotion)
|
||||
{
|
||||
//Repeat 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, test_promotion_and_demotion);
|
||||
|
||||
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);
|
||||
//:More tests here
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void test_read_write_mutex()
|
||||
void do_test_read_write_mutex(bool test_promotion_and_demotion)
|
||||
{
|
||||
int i;
|
||||
for(i = (int) boost::read_write_scheduling_policy::writer_priority;
|
||||
//Run every test for each scheduling policy
|
||||
|
||||
for(int 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
|
||||
<< (test_promotion_and_demotion ? " with promotion & demotion" : " without promotion & demotion")
|
||||
<< "\n";
|
||||
std::cout.flush();
|
||||
|
||||
std::cout << "plain test, sp=" << i << "\n";
|
||||
test_plain_read_write_mutex(plain_rw);
|
||||
{
|
||||
boost::read_write_mutex plain_rw(static_cast<boost::read_write_scheduling_policy::read_write_scheduling_policy_enum>(i));
|
||||
test_plain_read_write_mutex(plain_rw, test_promotion_and_demotion);
|
||||
}
|
||||
|
||||
std::cout << "try test, sp=" << i << "\n";
|
||||
test_try_read_write_mutex(try_rw);
|
||||
std::cout << "try test, sp=" << i
|
||||
<< (test_promotion_and_demotion ? " with promotion & demotion" : " without promotion & demotion")
|
||||
<< "\n";
|
||||
std::cout.flush();
|
||||
|
||||
std::cout << "timed test, sp=" << i << "\n";
|
||||
test_timed_read_write_mutex(timed_rw);
|
||||
{
|
||||
boost::try_read_write_mutex try_rw(static_cast<boost::read_write_scheduling_policy::read_write_scheduling_policy_enum>(i));
|
||||
test_try_read_write_mutex(try_rw, test_promotion_and_demotion);
|
||||
}
|
||||
|
||||
std::cout << "timed test, sp=" << i
|
||||
<< (test_promotion_and_demotion ? " with promotion & demotion" : " without promotion & demotion")
|
||||
<< "\n";
|
||||
std::cout.flush();
|
||||
|
||||
{
|
||||
boost::timed_read_write_mutex timed_rw(static_cast<boost::read_write_scheduling_policy::read_write_scheduling_policy_enum>(i));
|
||||
test_timed_read_write_mutex(timed_rw, test_promotion_and_demotion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test_read_write_mutex()
|
||||
{
|
||||
do_test_read_write_mutex(false);
|
||||
do_test_read_write_mutex(true);
|
||||
}
|
||||
|
||||
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
boost::unit_test_framework::test_suite* test =
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
@@ -29,9 +24,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 +36,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()
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
@@ -149,7 +144,12 @@ void do_test_tss()
|
||||
<< "\n";
|
||||
std::cout.flush();
|
||||
|
||||
BOOST_CHECK_EQUAL(tss_instances, 0);
|
||||
// The following is not really an error. TSS cleanup support still is available
|
||||
// for threads, launched via the boost API. Also this usually will be triggered
|
||||
// only when bound to the static version of the thread lib.
|
||||
// 2006-10-15 Roland Schwarz
|
||||
//BOOST_CHECK_EQUAL(tss_instances, 0);
|
||||
BOOST_CHECK_MESSAGE(tss_instances ==0, "Support of automatic tss cleanup for native threading API not available");
|
||||
BOOST_CHECK_EQUAL(tss_total, 5);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(UTIL_INL_WEK01242003)
|
||||
#define UTIL_INL_WEK01242003
|
||||
@@ -30,8 +25,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 +135,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 +148,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
|
||||
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
# 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.
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# Boost.Threads tutorial Jamfile
|
||||
#
|
||||
@@ -21,34 +16,19 @@
|
||||
# variant to link against (see the pthreads-win32 documentation).
|
||||
# Example: jam -sPTW32="c:\pthreads-win32 pthreadVCE.lib"
|
||||
|
||||
# Declare the location of this subproject relative to the root.
|
||||
|
||||
subproject libs/thread/tutorial ;
|
||||
|
||||
# Include threads.jam for Boost.Threads global build information.
|
||||
# This greatly simplifies the Jam code needed to configure the build
|
||||
# for the various Win32 build types.
|
||||
import ../build/threads ;
|
||||
|
||||
{
|
||||
template tutorial
|
||||
## sources ##
|
||||
: <template>thread_base
|
||||
<dll>../build/boost_thread
|
||||
## requirements ##
|
||||
:
|
||||
## default build ##
|
||||
:
|
||||
project
|
||||
: requirements <library>/boost/thread//boost_thread
|
||||
<threading>multi
|
||||
;
|
||||
|
||||
exe helloworld : <template>tutorial helloworld.cpp ;
|
||||
exe helloworld2 : <template>tutorial helloworld2.cpp ;
|
||||
exe helloworld3 : <template>tutorial helloworld3.cpp ;
|
||||
exe helloworld4 : <template>tutorial helloworld4.cpp ;
|
||||
exe factorial : <template>tutorial factorial.cpp ;
|
||||
exe factorial2 : <template>tutorial factorial2.cpp ;
|
||||
exe factorial3 : <template>tutorial factorial3.cpp ;
|
||||
exe counter : <template>tutorial counter.cpp ;
|
||||
exe bounded_buffer : <template>tutorial bounded_buffer.cpp ;
|
||||
exe once : <template>tutorial once.cpp ;
|
||||
}
|
||||
exe helloworld : helloworld.cpp ;
|
||||
exe helloworld2 : helloworld2.cpp ;
|
||||
exe helloworld3 : helloworld3.cpp ;
|
||||
exe helloworld4 : helloworld4.cpp ;
|
||||
exe factorial : factorial.cpp ;
|
||||
exe factorial2 : factorial2.cpp ;
|
||||
exe factorial3 : factorial3.cpp ;
|
||||
exe counter : counter.cpp ;
|
||||
exe bounded_buffer : bounded_buffer.cpp ;
|
||||
exe once : once.cpp ;
|
||||
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/condition.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <iostream>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <iostream>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <iostream>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <iostream>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/once.hpp>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// 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.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/tss.hpp>
|
||||
|
||||
Reference in New Issue
Block a user