mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 21:52:07 +00:00
Compare commits
317 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 | ||
|
|
113b974bb7 | ||
|
|
c747a6ff4e | ||
|
|
107d11cfd5 | ||
|
|
a4d2cd94b9 | ||
|
|
3d9fb84fc9 | ||
|
|
e500bc075e | ||
|
|
25e8fa0e11 | ||
|
|
5f27fb2607 | ||
|
|
d977cedb78 | ||
|
|
454b58cdf0 | ||
|
|
82a632b0f9 | ||
|
|
43cbe3f1f8 | ||
|
|
d027cec8a6 | ||
|
|
e53c2c52ee | ||
|
|
5ff0ecc12d | ||
|
|
9c1f421ccb | ||
|
|
66850bc057 | ||
|
|
33da34b4bf | ||
|
|
792cd49310 | ||
|
|
37fdb5e2b0 | ||
|
|
88cd251db7 | ||
|
|
4038d18fc8 | ||
|
|
59bf92a183 | ||
|
|
57879155d2 | ||
|
|
96d43cebc0 | ||
|
|
8e13857b29 | ||
|
|
8c6e454697 | ||
|
|
4c7c7df89b | ||
|
|
515e6d8635 | ||
|
|
bbd941e2df | ||
|
|
3edba1bf19 | ||
|
|
4ad99d8242 | ||
|
|
c0aeaecc14 | ||
|
|
792be9e687 | ||
|
|
fd65337f43 | ||
|
|
9de9726e6f | ||
|
|
522037ca4a | ||
|
|
8fc3d1f718 | ||
|
|
cebaf27ee8 | ||
|
|
b62503f274 | ||
|
|
af50c640ab | ||
|
|
b5c5fbe0f5 | ||
|
|
b88ae8105e | ||
|
|
9ad04bb65e | ||
|
|
13bbaab1c4 | ||
|
|
09ca8d1728 | ||
|
|
9797a93d86 | ||
|
|
d29dae72de | ||
|
|
59fba2bff6 | ||
|
|
0350d4c501 | ||
|
|
d3e4a90e70 | ||
|
|
8ebb19fd18 | ||
|
|
02ddc33e6c | ||
|
|
410e8efeba | ||
|
|
e9f8e0bad9 | ||
|
|
f69e0313dc | ||
|
|
baa9b396d9 | ||
|
|
a82b0c516d | ||
|
|
43e2192aa2 | ||
|
|
4cd6453cac | ||
|
|
921d4c24c2 | ||
|
|
4fc7653b12 | ||
|
|
9d0e39a7c2 | ||
|
|
7aa979cf5b | ||
|
|
0aa50614d7 | ||
|
|
6f402c7362 | ||
|
|
2bf43a124d | ||
|
|
3573c53eda | ||
|
|
4546ec4ef7 | ||
|
|
2f7337aaf6 | ||
|
|
046698bcc2 | ||
|
|
06d7bf21d5 | ||
|
|
e7b9ccdf10 | ||
|
|
1e15b043a0 | ||
|
|
6c5f3d76e2 | ||
|
|
8679d6f6af | ||
|
|
f1c7d0f354 | ||
|
|
261e413500 | ||
|
|
094e41d7a7 | ||
|
|
e20299c8ee | ||
|
|
f8962b7ad2 | ||
|
|
c34f829c3e | ||
|
|
46264e4a4a | ||
|
|
096df68ea6 | ||
|
|
35f2055a1e | ||
|
|
e1353eefb3 | ||
|
|
4911a532bf | ||
|
|
96362e03aa | ||
|
|
049b4e09fe | ||
|
|
828c0e28af | ||
|
|
15a638edc0 | ||
|
|
fc8f1b1075 | ||
|
|
318a8e38c9 | ||
|
|
f0dbb02a9f | ||
|
|
649b777b76 | ||
|
|
6fad43670a | ||
|
|
e24b16229e | ||
|
|
21b4b81810 | ||
|
|
1096b1e28e | ||
|
|
03458fedef | ||
|
|
c1a2004344 | ||
|
|
2adb13a209 | ||
|
|
dba194ddb9 | ||
|
|
8179f041e6 | ||
|
|
a13c7a4d84 | ||
|
|
bbf92bb971 | ||
|
|
b33f413635 | ||
|
|
58ffb2bc16 | ||
|
|
0ed112631c | ||
|
|
9cfe8e9422 | ||
|
|
7d3fe72970 | ||
|
|
ac422138fa | ||
|
|
bf8746454a | ||
|
|
b61aa5b4ba | ||
|
|
c2bcd08168 | ||
|
|
48593b8868 | ||
|
|
83d4dc1831 | ||
|
|
0696f3cc41 | ||
|
|
515590495a | ||
|
|
7221bca909 | ||
|
|
ed64a8cd12 | ||
|
|
cbd30d22ff | ||
|
|
0c74dbd436 | ||
|
|
49356cc931 | ||
|
|
ceee6e8b17 | ||
|
|
61ab2754d2 | ||
|
|
2de3df61e8 | ||
|
|
b84d7aa06d | ||
|
|
ed48f900a3 | ||
|
|
d197a49707 | ||
|
|
b8ccaa3bf6 | ||
|
|
507a684b21 | ||
|
|
c969c9387a | ||
|
|
1709db4953 | ||
|
|
4d1c9ba316 | ||
|
|
45b0396355 | ||
|
|
1df2169e48 | ||
|
|
2c056b3621 | ||
|
|
680119006c | ||
|
|
c4ac4b7538 | ||
|
|
ff5d3b49ca | ||
|
|
e101c878f0 | ||
|
|
125193dcfa | ||
|
|
77efa9810d | ||
|
|
7f03d1917b | ||
|
|
55b4ca9350 | ||
|
|
7196a0f9d2 | ||
|
|
2caabde5ca | ||
|
|
137d7663c1 | ||
|
|
508b71a921 | ||
|
|
5d90820005 | ||
|
|
84727e90b1 | ||
|
|
9a1e3d3320 | ||
|
|
d33e0c8ee1 | ||
|
|
3332649480 | ||
|
|
c918b66199 | ||
|
|
dbbf56e17a | ||
|
|
c77500c15a | ||
|
|
75084aaa96 | ||
|
|
35714c8f1c | ||
|
|
3699cc97a6 | ||
|
|
5a7377acda | ||
|
|
6aaee629b5 | ||
|
|
b465fe569c | ||
|
|
5e6f72a688 | ||
|
|
51f80f6c15 | ||
|
|
45c314e594 | ||
|
|
cfce0892e0 | ||
|
|
05d1abf030 | ||
|
|
6c24a2626b | ||
|
|
870c75bd12 | ||
|
|
5fdd771708 | ||
|
|
06f39ac409 | ||
|
|
c92b0a2fb7 | ||
|
|
8a8d0e05ca | ||
|
|
74bae2baac | ||
|
|
4ba48676bd | ||
|
|
78480e7951 | ||
|
|
4cb9c412e8 | ||
|
|
75c83fed96 | ||
|
|
391de20ae0 | ||
|
|
1e2a9e8971 | ||
|
|
43cbd3a283 | ||
|
|
31cf6b5e64 | ||
|
|
99109ab78b | ||
|
|
a80d5f159d | ||
|
|
7ba4fc4aed | ||
|
|
9fb31e9868 | ||
|
|
3a2246de5b | ||
|
|
e7c4e2fa57 | ||
|
|
724ab285f0 | ||
|
|
d60e66fb00 | ||
|
|
97cdaca028 | ||
|
|
3044c8f905 | ||
|
|
2775a2a945 | ||
|
|
c43c1febba | ||
|
|
ceb6471d57 | ||
|
|
b99cc044f3 | ||
|
|
d91429dcec | ||
|
|
b1d1f7d8f1 | ||
|
|
86b608cf41 | ||
|
|
f263f75751 | ||
|
|
24bec05b86 | ||
|
|
ce1a5e9359 | ||
|
|
311525bc06 | ||
|
|
ecdfd96529 | ||
|
|
5aab32bc1a | ||
|
|
e152a1c6f2 | ||
|
|
e84fde78ec | ||
|
|
6ec4652bcf | ||
|
|
a5239c820b | ||
|
|
41b001b22c | ||
|
|
34e903b8b0 | ||
|
|
2b67e953fd | ||
|
|
aa0d3adf1d | ||
|
|
a1f57a8a80 | ||
|
|
6bc82a8580 | ||
|
|
c4c2e5d3a2 | ||
|
|
dd7d4b2173 | ||
|
|
2719c4d545 | ||
|
|
33c1e36b54 | ||
|
|
e7e46e185e | ||
|
|
9200d48873 | ||
|
|
831d054d24 | ||
|
|
f3af804ddb | ||
|
|
1f35149ef0 | ||
|
|
554a18842f | ||
|
|
869243b6d1 | ||
|
|
c0da02326a | ||
|
|
9b5f666fc5 | ||
|
|
1ce93426a4 | ||
|
|
6dacf3478b | ||
|
|
dff91699c3 | ||
|
|
9f83e8c1fc | ||
|
|
7b07cb0759 | ||
|
|
c2e7091632 | ||
|
|
1ab320042e | ||
|
|
b0cd307eaf | ||
|
|
ca2cf20cf3 | ||
|
|
b3acba1d2d | ||
|
|
6d2731c463 | ||
|
|
b7f8f8867c |
2
build/.cvsignore
Normal file
2
build/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
bin*
|
||||
*.pdb
|
||||
146
build/Jamfile
146
build/Jamfile
@@ -1,40 +1,122 @@
|
||||
# (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.
|
||||
# Copyright (C) 2001-2003
|
||||
# William E. Kempf
|
||||
#
|
||||
# Boost.Threads build and test Jamfile
|
||||
# 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)
|
||||
#
|
||||
# Declares the following targets:
|
||||
# 1. libboost_thread, a static link library.
|
||||
# 1a. On Win32, a dynamic link library libboost_threadmon,
|
||||
# which must be used in conjunction with libboost_thread.
|
||||
# Boost.Threads build Jamfile
|
||||
#
|
||||
# Additional configuration variables used:
|
||||
# See threads.jam.
|
||||
|
||||
# declare the location of this subproject relative to the root
|
||||
# Declare the location of this subproject relative to the root.
|
||||
subproject libs/thread/build ;
|
||||
|
||||
#######################
|
||||
# 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 ./threads ;
|
||||
|
||||
#
|
||||
# Declare the Boost.Threads static link library.
|
||||
#
|
||||
|
||||
# For Win32 we need to build a special DLL, libboost_threadmon, to handle
|
||||
# TSS destruction.
|
||||
if $(NT)
|
||||
{
|
||||
dll libboost_threadmon : ../src/threadmon.cpp
|
||||
# requirements
|
||||
: <threading>multi
|
||||
: debug release ;
|
||||
CPP_SOURCES =
|
||||
barrier
|
||||
condition
|
||||
exceptions
|
||||
mutex
|
||||
once
|
||||
recursive_mutex
|
||||
read_write_mutex
|
||||
thread
|
||||
tss_hooks
|
||||
tss_dll
|
||||
tss_pe
|
||||
tss
|
||||
xtime
|
||||
;
|
||||
|
||||
template boost_thread_lib_base
|
||||
: ## sources ##
|
||||
<template>thread_base
|
||||
../src/$(CPP_SOURCES).cpp
|
||||
: ## requirements ##
|
||||
<sysinclude>$(BOOST_ROOT) #:should be unnecessary (because already included in thread_base)
|
||||
<define>BOOST_THREAD_BUILD_LIB=1
|
||||
# the common names rule ensures that the library will
|
||||
# be named according to the rules used by the install
|
||||
# and auto-link features:
|
||||
common-variant-tag
|
||||
: ## default build ##
|
||||
;
|
||||
|
||||
template boost_thread_dll_base
|
||||
: ## sources ##
|
||||
<template>thread_base
|
||||
../src/$(CPP_SOURCES).cpp
|
||||
: ## requirements ##
|
||||
<sysinclude>$(BOOST_ROOT) #:should be unnecessary (because already included in thread_base)
|
||||
<define>BOOST_THREAD_BUILD_DLL=1
|
||||
<runtime-link>dynamic
|
||||
# the common names rule ensures that the library will
|
||||
# be named according to the rules used by the install
|
||||
# and auto-link features:
|
||||
common-variant-tag
|
||||
: ## default build ##
|
||||
;
|
||||
|
||||
lib $(boost_thread_lib_name)
|
||||
: ## sources ##
|
||||
<template>boost_thread_lib_base
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name)
|
||||
: ## default build ##
|
||||
;
|
||||
|
||||
dll $(boost_thread_lib_name)
|
||||
: ## sources ##
|
||||
<template>boost_thread_dll_base
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name)
|
||||
: ## default build ##
|
||||
;
|
||||
|
||||
stage bin-stage
|
||||
: <dll>$(boost_thread_lib_name)
|
||||
<lib>$(boost_thread_lib_name)
|
||||
;
|
||||
|
||||
install thread lib
|
||||
: <dll>$(boost_thread_lib_name)
|
||||
<lib>$(boost_thread_lib_name)
|
||||
;
|
||||
|
||||
if $(boost_thread_lib_settings_ptw32)
|
||||
{
|
||||
lib $(boost_thread_lib_name_ptw32)
|
||||
: ## sources ##
|
||||
<template>boost_thread_lib_base
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name_ptw32)
|
||||
$(boost_thread_lib_settings_ptw32)
|
||||
: ## default build ##
|
||||
;
|
||||
|
||||
dll $(boost_thread_lib_name_ptw32)
|
||||
: ## sources ##
|
||||
<template>boost_thread_dll_base
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name_ptw32)
|
||||
$(boost_thread_lib_settings_ptw32)
|
||||
: ## default build ##
|
||||
;
|
||||
|
||||
stage bin-stage
|
||||
: <dll>$(boost_thread_lib_name_ptw32)
|
||||
<lib>$(boost_thread_lib_name_ptw32)
|
||||
;
|
||||
|
||||
install thread lib
|
||||
: <dll>$(boost_thread_lib_name_ptw32)
|
||||
<lib>$(boost_thread_lib_name_ptw32)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
# Base names of the source files for libboost_thread
|
||||
CPP_SOURCES =
|
||||
condition mutex recursive_mutex semaphore thread tss xtime once ;
|
||||
|
||||
lib libboost_thread : ../src/$(CPP_SOURCES).cpp
|
||||
# requirements
|
||||
: <include>$(BOOST_ROOT)
|
||||
<threading>multi
|
||||
: debug release ;
|
||||
|
||||
39
build/Jamfile.v2
Normal file
39
build/Jamfile.v2
Normal file
@@ -0,0 +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 ;
|
||||
|
||||
|
||||
project boost/thread
|
||||
: source-location ../src
|
||||
: requirements <link>shared:<define>BOOST_THREAD_BUILD_DLL=1 <threading>multi
|
||||
: default-build <threading>multi
|
||||
;
|
||||
|
||||
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
|
||||
;
|
||||
65
build/threads.jam
Normal file
65
build/threads.jam
Normal file
@@ -0,0 +1,65 @@
|
||||
# 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)
|
||||
|
||||
# Additional configuration variables used:
|
||||
# 1. PTW32_DIR and PTW32_LIB may be used on Win32 platforms to specify that
|
||||
# a version of Boost.Threads should be built that uses the
|
||||
# the pthreads-win32 library instead of the Win32 native threading APIs.
|
||||
# This feature is mostly used for testing and it's generally recommended
|
||||
# that you use the Win32 native threading libraries instead.
|
||||
#
|
||||
# PTW32_Dir should be set to the installation path of the
|
||||
# pthreads-win32 library and PTW32_LIB should be set to the name of the
|
||||
# library variant to link against (see the pthreads-win32 documentation).
|
||||
# Example: jam -sPTW32_DIR="c:\pthreads-win32" -sPTW32_LIB="pthreadVCE.lib"
|
||||
# Alternately, environment variables having the names PTW32_DIR and PTW32_LIB
|
||||
# can be set instead of passing these values on the command line.
|
||||
#
|
||||
# In either case, libraries having the names boost_thread_ptw32<tags>.dll
|
||||
# and libboost_thread_ptw32<tags>.lib will be built
|
||||
# in addition to the usual boost_thread<tags>.dll and
|
||||
# libboost_thread<tags>.lib. Link with one of the ptw32 versions
|
||||
# of the Boost.Threads libraries to use the version of Boost.Threads
|
||||
# that is implemented using pthreads-win32 (you will need to #define
|
||||
# BOOST_THREAD_NO_LIB or BOOST_ALL_NO_LIB to disable auto-linking
|
||||
# if your platform supports auto-linking in order to prevent
|
||||
# your build from attempting to link to two different versions of
|
||||
# the Boost.Threads library).
|
||||
|
||||
# Do some OS-specific setup
|
||||
{
|
||||
#thread library name
|
||||
boost_thread_lib_name = boost_thread ;
|
||||
|
||||
#thread library name with "pthreads-win32" library
|
||||
boost_thread_lib_name_ptw32 = boost_thread_ptw32 ;
|
||||
|
||||
if $(NT)
|
||||
{
|
||||
if $(PTW32_DIR)
|
||||
{
|
||||
if $(PTW32_LIB)
|
||||
{
|
||||
boost_thread_lib_settings_ptw32 =
|
||||
<define>BOOST_HAS_PTHREADS
|
||||
<define>PtW32NoCatchWarn
|
||||
<include>$(PTW32_DIR)/pre-built/include
|
||||
<library-file>$(PTW32_DIR)/pre-built/lib/$(PTW32_LIB)
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template thread_base
|
||||
: ## sources ##
|
||||
: ## requirements ##
|
||||
<sysinclude>$(BOOST_ROOT)
|
||||
<threading>multi
|
||||
<borland><*><cxxflags>-w-8004
|
||||
<borland><*><cxxflags>-w-8057
|
||||
: ## default build ##
|
||||
;
|
||||
}
|
||||
BIN
build/threads.mcp
Normal file
BIN
build/threads.mcp
Normal file
Binary file not shown.
11
doc/Jamfile.v2
Normal file
11
doc/Jamfile.v2
Normal file
@@ -0,0 +1,11 @@
|
||||
# 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 ;
|
||||
|
||||
boostbook thread : thread.xml ;
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Boost.Threads Acknowledgements</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">Acknowledgements</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2>Acknowledgments</h2>
|
||||
|
||||
<p><a href="../../../people/william_kempf.htm">William E. Kempf</a> was the
|
||||
architect, designer, and implementor of <b>Boost.Threads</b>.</p>
|
||||
|
||||
<p>Important contributions were also made by Jeremy Siek (lots of input on
|
||||
the design and on the implementation), Alexander Terekhov (lots of input on
|
||||
the Win32 implementation, especially in regards to boost::condition, as well
|
||||
as a lot of explanation of POSIX behavior), Greg Colvin (lots of input on the
|
||||
design), and Paul Mclachlan, Thomas Matelich and Iain Hanson (for help in
|
||||
trying to get the build to work on other platforms).</p>
|
||||
|
||||
<p>The documentation was written by William E. Kempf. Beman Dawes provided
|
||||
additional documentation material and editing.</p>
|
||||
|
||||
<p>Discussions on the boost.org mailing list were essential in the development
|
||||
of <b>Boost.Threads</b>. 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, Branko
|
||||
Èibej, Brent Verner, Craig Henderson, Csaba Szepesvari, Dale Peakall, Damian
|
||||
Dixon, Dan Nuffer, Darryl Green, Daryle Walker, David Abrahams, David Allan
|
||||
Finch, Dejan Jelovic, Dietmar Kuehl, Doug Gregor, Douglas Gregor, Duncan Harris,
|
||||
Ed Brey, Eric Swanson, Eugene Karpachov, Fabrice Truillot, Frank
|
||||
Gerlach, Gary Powell, Gernot Neppert, Geurt Vos, Ghazi Ramadan, Greg Colvin,
|
||||
Gregory Seidman, HYS, Iain Hanson, Ian Bruntlett, J Panzer, Jeff Garland, Jeff
|
||||
Paquette, Jens Maurer, Jeremy Siek, Jesse Jones, Joe Gottman, John (EBo) David,
|
||||
John Bandela, John Maddock, John Max Skaller, John Panzer, Jon Jagger , Karl
|
||||
Nelson, Kevlin Henney, KG Chandrasekhar, Levente Farkas, Lie-Quan Lee, Lois
|
||||
Goldthwaite, Luis Pedro Coelho, Marc Girod, Mark A. Borgerding, Mark Rodgers,
|
||||
Marshall Clow, Matthew Austern, Matthew Hurd, Michael D. Crawford, Michael H.
|
||||
Cox , Mike Haller, Miki Jovanovic, Nathan Myers, Paul Moore, Pavel Cisler, Peter
|
||||
Dimov, Petr Kocmid, Philip Nash, Rainer Deyke, Reid Sweatman, Ross Smith, Scott
|
||||
McCaskill, Shalom Reich , Steve Cleary, Steven Kirk, Thomas Holenstein, Thomas
|
||||
Matelich, Trevor Perrin, Valentin Bonnard, Vesa Karvonen, Wayne Miller, and
|
||||
William Kempf.</p>
|
||||
|
||||
<p>Apologies for anyone inadvertently missed.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->29 August, 2001<!--webbot bot="Timestamp" endspan i-checksum="34360" -->
|
||||
</p>
|
||||
|
||||
<p>©<i> Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001</i></p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
68
doc/acknowledgements.xml
Normal file
68
doc/acknowledgements.xml
Normal file
@@ -0,0 +1,68 @@
|
||||
<?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 % 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.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>
|
||||
,
|
||||
<code>thread_pool</code>
|
||||
,
|
||||
<code>read_write_mutex</code>
|
||||
,
|
||||
<code>read_write_try_mutex</code>
|
||||
and
|
||||
<code>read_write_timed_mutex</code>
|
||||
classes.</para>
|
||||
<para>Important contributions were also made by Jeremy Siek (lots of input
|
||||
on the design and on the implementation), Alexander Terekhov (lots of input
|
||||
on the Win32 implementation, especially in regards to boost::condition, as
|
||||
well as a lot of explanation of POSIX behavior), Greg Colvin (lots of input
|
||||
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.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
|
||||
read_write_mutex and related classes.</para>
|
||||
<para>The documentation was written by William E. Kempf. Beman Dawes
|
||||
provided additional documentation material and editing.
|
||||
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.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,
|
||||
Branko èibej, Brent Verner, Craig Henderson, Csaba Szepesvari,
|
||||
Dale Peakall, Damian Dixon, Dan Nuffer, Darryl Green, Daryle Walker, David
|
||||
Abrahams, David Allan Finch, Dejan Jelovic, Dietmar Kuehl, Douglas Gregor,
|
||||
Duncan Harris, Ed Brey, Eric Swanson, Eugene Karpachov, Fabrice Truillot,
|
||||
Frank Gerlach, Gary Powell, Gernot Neppert, Geurt Vos, Ghazi Ramadan, Greg
|
||||
Colvin, Gregory Seidman, HYS, Iain Hanson, Ian Bruntlett, J Panzer, Jeff
|
||||
Garland, Jeff Paquette, Jens Maurer, Jeremy Siek, Jesse Jones, Joe Gottman,
|
||||
John (EBo) David, John Bandela, John Maddock, John Max Skaller, John
|
||||
Panzer, Jon Jagger , Karl Nelson, Kevlin Henney, KG Chandrasekhar, Levente
|
||||
Farkas, Lie-Quan Lee, Lois Goldthwaite, Luis Pedro Coelho, Marc Girod, Mark
|
||||
A. Borgerding, Mark Rodgers, Marshall Clow, Matthew Austern, Matthew Hurd,
|
||||
Michael D. Crawford, Michael H. Cox , Mike Haller, Miki Jovanovic, Nathan
|
||||
Myers, Paul Moore, Pavel Cisler, Peter Dimov, Petr Kocmid, Philip Nash,
|
||||
Rainer Deyke, Reid Sweatman, Ross Smith, Scott McCaskill, Shalom Reich,
|
||||
Steve Cleary, Steven Kirk, Thomas Holenstein, Thomas Matelich, Trevor
|
||||
Perrin, Valentin Bonnard, Vesa Karvonen, Wayne Miller, and William
|
||||
Kempf.</para>
|
||||
<para>Apologies for anyone inadvertently missed.</para>
|
||||
</section>
|
||||
|
||||
82
doc/barrier-ref.xml
Normal file
82
doc/barrier-ref.xml
Normal file
@@ -0,0 +1,82 @@
|
||||
<?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 % 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">
|
||||
<class name="barrier">
|
||||
<inherit access="private">
|
||||
<type><classname>boost::noncopyable</classname></type>
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<purpose>
|
||||
<para>An object of class <classname>barrier</classname> is a synchronization
|
||||
primitive used to cause a set of threads to wait until they each perform a
|
||||
certain function or each reach a particular point in their execution.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>When a barrier is created, it is initialized with a thread count N.
|
||||
The first N-1 calls to <code>wait()</code> will all cause their threads to be blocked.
|
||||
The Nth call to <code>wait()</code> will allow all of the waiting threads, including
|
||||
the Nth thread, to be placed in a ready state. The Nth call will also "reset"
|
||||
the barrier such that, if an additional N+1th call is made to <code>wait()</code>,
|
||||
it will be as though this were the first call to <code>wait()</code>; in other
|
||||
words, the N+1th to 2N-1th calls to <code>wait()</code> will cause their
|
||||
threads to be blocked, and the 2Nth call to <code>wait()</code> will allow all of
|
||||
the waiting threads, including the 2Nth thread, to be placed in a ready state
|
||||
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="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>
|
||||
|
||||
<constructor>
|
||||
<parameter name="count">
|
||||
<paramtype>size_t</paramtype>
|
||||
</parameter>
|
||||
|
||||
<effects><simpara>Constructs a <classname>barrier</classname> object that
|
||||
will cause <code>count</code> threads to block on a call to <code>wait()</code>.
|
||||
</simpara></effects>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<effects><simpara>Destroys <code>*this</code>. If threads are still executing
|
||||
their <code>wait()</code> operations, the behavior for these threads is undefined.
|
||||
</simpara></effects>
|
||||
</destructor>
|
||||
|
||||
<method-group name="waiting">
|
||||
<method name="wait">
|
||||
<type>bool</type>
|
||||
|
||||
<effects><simpara>Wait until N threads call <code>wait()</code>, where
|
||||
N equals the <code>count</code> provided to the constructor for the
|
||||
barrier object.</simpara>
|
||||
<simpara><emphasis role="bold">Note</emphasis> that if the barrier is
|
||||
destroyed before <code>wait()</code> can return, the behavior is
|
||||
undefined.</simpara></effects>
|
||||
|
||||
<returns>Exactly one of the N threads will receive a return value
|
||||
of <code>true</code>, the others will receive a value of <code>false</code>.
|
||||
Precisely which thread receives the return value of <code>true</code> will
|
||||
be implementation-defined. Applications can use this value to designate one
|
||||
thread as a leader that will take a certain action, and the other threads
|
||||
emerging from the barrier can wait for that action to take place.</returns>
|
||||
</method>
|
||||
</method-group>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
@@ -1,145 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Boost.Threads Bibliography</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">Bibliography</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2>Bibliography</h2>
|
||||
<table border="0" cellpadding="5" width="777">
|
||||
<tr>
|
||||
<td width="102" valign="top" align="left"><b>[<a name="Andrews-83">Andrews
|
||||
83</a>]</b></td>
|
||||
<td width="645">
|
||||
Gregory R. Andrews, Fred B. Schneider, <cite>Concepts and Notations for Concurrent
|
||||
Programming</cite>, ACM Computing Surveys, Vol. 15, No. 1, March, 1983. <a href="http://www.acm.org/pubs/citations/journals/surveys/1983-15-1/p3-andrews/">http://www.acm.org/pubs/citations/journals/surveys/1983-15-1/p3-andrews/</a>
|
||||
<p>Good general background reading. Includes descriptions of Path
|
||||
Expressions, Message Passing, and Remote Procedure Call in addition to the
|
||||
basics.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="102" valign="top" align="left"><b>[<a name="Boost">Boost</a>]</b></td>
|
||||
<td width="645">
|
||||
The <cite> Boost</cite> world-wide web site. <a href="http://www.boost.org">http://www.boost.org</a>
|
||||
<p>Boost.Threads 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.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="102" valign="top" align="left"><b>[<a name="Brinch-Hansen-73">Brinch
|
||||
Hansen 73</a>]</b></td>
|
||||
<td width="645">
|
||||
Per Brinch Hansen, <cite>Concurrent Programming Concepts</cite>, ACM Computing
|
||||
Surveys, Vol. 5, No. 4, December, 1973. <a href="http://www.acm.org/pubs/articles/journals/surveys/1973-5-4/p223-hansen/p223-hansen.pdf">http://www.acm.org/pubs/articles/journals/surveys/1973-5-4/p223-hansen/</a>
|
||||
<p>"This paper describes the evolution of language features for
|
||||
multiprogramming from event queues and semaphores to critical regions and
|
||||
monitors." Includes analysis of why <i>events</i> are considered
|
||||
error-prone. Also noteworthy because of an introductory quotation from
|
||||
Christopher Alexander; Brinch Hansen was years ahead of others in recognizing
|
||||
pattern concepts applied to software too.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="102" valign="top" align="left"><b>]<a name="Butenhof-97">Butenhof
|
||||
97</a>]</b></td>
|
||||
<td width="645">
|
||||
<p> David R. Butenhof, <cite>Programming with
|
||||
POSIX Threads</cite>, Addison-Wesley 1997, ISBN 0-201-63392-2 <a href="http://cseng.aw.com/book/0,3828,0201633922,00.html">http://cseng.aw.com/book/0,3828,0201633922,00.html</a></p>
|
||||
<p>This is a very readable explanation of threads and how to use them. Many
|
||||
of the insights given apply to all multi-threaded programming, not just POSIX
|
||||
Threads.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="102" valign="top" align="left"><b>[<a name="Hoare-74">Hoare 74</a>]</b></td>
|
||||
<td width="645">
|
||||
<p>C.A.R Hoare, <cite> Monitors: An Operating System Structuring Concept</cite>,
|
||||
Communications of the ACM, Vol. 17, No. 10. October
|
||||
1974, pp. 549-557 <a href="http://www.acm.org/classics/feb96/">http://www.acm.org/classics/feb96/ </a></p>
|
||||
<p>Hoare and Brinch Hansen's work on Monitors is the basis for reliable
|
||||
multi-threading patterns. This is one of the most often referenced papers in
|
||||
all of computer science, and with good reason.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="102" valign="top" align="left"><b>[<a name="ISO-98">ISO 98</a>]</b></td>
|
||||
<td width="645">
|
||||
<p>ISO/IEC 14882:1998(E) <cite> Programming Language C++</cite> <a href="http://www.ansi.org">http://www.ansi.org</a></p>
|
||||
<p>This is the official C++ Standards
|
||||
document. Available from the ANSI (American
|
||||
National Standards Institute) Electronic Standards Store.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="102" valign="top" align="left"><b>[<a name="McDowell-89">McDowell
|
||||
89</a>]</b></td>
|
||||
<td width="645">
|
||||
Charles E McDowell, David P. Helmbold, <cite>Debugging Concurrent Programs</cite>,
|
||||
ACM Computing Surveys, Vol. 21, No. 2, December, 1989. <a href="http://www.acm.org/pubs/citations/journals/surveys/1989-21-4/p593-mcdowell/">http://www.acm.org/pubs/citations/journals/surveys/1989-21-4/p593-mcdowell/</a>
|
||||
<p>Identifies many of the unique failure modes and debugging difficulties
|
||||
associated with concurrent programs.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="102" valign="top" align="left"> <b>[<a name="Schmidt">Schmidt</a>] </b></td>
|
||||
<td width="645">
|
||||
<p> Douglas C. Schmidt and Irfan Pyarali, <cite>Strategies for
|
||||
Implementing POSIX Condition Variables on Win32</cite>, Department of Computer Science, Washington University, St. Louis, Missouri.
|
||||
<a href="http://www.cs.wustl.edu/~schmidt/win32-cv-1.html">http://www.cs.wustl.edu/~schmidt/win32-cv-1.html</a></p>
|
||||
<p>Rationale for understanding Boost.Threads condition variables. Note that Alexander Terekhov found some bugs in
|
||||
the implementation given in this article, so pthreads-win32 and Boost.Threads
|
||||
are even more complicated yet.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="102" valign="top" align="left"> <b>[<a name="Schmidt-00">Schmidt
|
||||
00</a>] </b></td>
|
||||
<td width="645">
|
||||
<p> Douglas C. Schmidt, Michael Stal, Hans Rohnert and Frank Buschmann, <cite>Pattern-Oriented Software Architecture Volume 2 - Patterns for
|
||||
Concurrent and Networked Objects</cite>, Wiley 2000, ISBN 0-471-60695-2 <a href="http://www.wiley.com/Corporate/Website/Objects/Products/0,9049,104671,00.html">http://www.wiley.com/Corporate/Website/Objects/Products/0,9049,104671,00.html</a></p>
|
||||
<p>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 <b>Boost.Threads</b>
|
||||
documentation.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="102" valign="top" align="left"> <b>[<a name="Stroustrup-00">Stroustrup
|
||||
00</a>]</b></td>
|
||||
<td width="645">
|
||||
Bjarne Stroustrup, <cite> The C++ Programming Language</cite>, Special Edition, Addison-Wesley
|
||||
2000, ISBN 0-201-70073-5 <a href="http://cseng.aw.com/book/0,3828,0201700735,00.html">http://cseng.aw.com/book/0,3828,0201700735,00.html</a>
|
||||
<p>The first book a C++ programmer should own. Note that the 3rd edition
|
||||
(and subsequent editions like the Special Edition) has been rewritten to cover
|
||||
the ISO standard language and library.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>Note: The URL's above are provided in plain text form so that they will be visible
|
||||
on printed copies of this document.</p>
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %b %Y" startspan -->17 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14763" -->
|
||||
</p>
|
||||
|
||||
<p>© Copyright Beman Dawes, 2001</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
234
doc/bibliography.xml
Normal file
234
doc/bibliography.xml
Normal file
@@ -0,0 +1,234 @@
|
||||
<?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 % 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)
|
||||
-->
|
||||
<bibliography id="thread.bibliography"
|
||||
last-revision="$Date$">
|
||||
<title>Bibliography</title>
|
||||
<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>
|
||||
<issuenum>No. 1</issuenum>
|
||||
<date>March, 1983</date>
|
||||
</biblioset>
|
||||
<biblioset relation="article">
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Gregory</firstname>
|
||||
<othername>R.</othername>
|
||||
<surname>Andrews</surname>
|
||||
</author>
|
||||
<author>
|
||||
<firstname>Fred</firstname>
|
||||
<othername>B.</othername>
|
||||
<surname>Schneider</surname>
|
||||
</author>
|
||||
</authorgroup>
|
||||
<title>
|
||||
<ulink
|
||||
url="http://www.acm.org/pubs/citations/journals/surveys/1983-15-1/p3-andrews/"
|
||||
>Concepts and Notations for Concurrent Programming</ulink>
|
||||
</title>
|
||||
</biblioset>
|
||||
<para>Good general background reading. Includes descriptions of Path
|
||||
Expressions, Message Passing, and Remote Procedure Call in addition to the
|
||||
basics</para>
|
||||
</biblioentry>
|
||||
<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.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="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, 1973</date>
|
||||
</biblioset>
|
||||
<biblioset relation="article">
|
||||
<author>0-201-63392-2
|
||||
<firstname>Per Brinch</firstname>
|
||||
<lastname>Hansen</lastname>
|
||||
</author>
|
||||
<title>
|
||||
<ulink
|
||||
url="http://www.acm.org/pubs/articles/journals/surveys/1973-5-4/p223-hansen/"
|
||||
>Concurrent Programming Concepts</ulink>
|
||||
</title>
|
||||
</biblioset>
|
||||
<para>"This paper describes the evolution of language features for
|
||||
multiprogramming from event queues and semaphores to critical regions and
|
||||
monitors." Includes analysis of why events are considered error-prone. Also
|
||||
noteworthy because of an introductory quotation from Christopher Alexander;
|
||||
Brinch Hansen was years ahead of others in recognizing pattern concepts
|
||||
applied to software, too.</para>
|
||||
</biblioentry>
|
||||
<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>
|
||||
</title>
|
||||
<author>
|
||||
<firstname>David</firstname>
|
||||
<othername>R.</othername>
|
||||
<surname>Butenhof</surname>
|
||||
</author>
|
||||
<publisher>Addison-Wesley</publisher>
|
||||
<copyright><year>1997</year></copyright>
|
||||
<isbn>ISNB: 0-201-63392-2</isbn>
|
||||
<para>This is a very readable explanation of threads and how to use
|
||||
them. Many of the insights given apply to all multithreaded programming, not
|
||||
just POSIX Threads</para>
|
||||
</biblioentry>
|
||||
<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>
|
||||
<issuenum>No. 10</issuenum>
|
||||
<date>October, 1974</date>
|
||||
</biblioset>
|
||||
<biblioset relation="article">
|
||||
<title>
|
||||
<ulink url=" http://www.acm.org/classics/feb96/"
|
||||
>Monitors: An Operating System Structuring Concept</ulink>
|
||||
</title>
|
||||
<author>
|
||||
<firstname>C.A.R.</firstname>
|
||||
<surname>Hoare</surname>
|
||||
</author>
|
||||
<pagenums>549-557</pagenums>
|
||||
</biblioset>
|
||||
<para>Hoare and Brinch Hansen's work on Monitors is the basis for reliable
|
||||
multithreading patterns. This is one of the most often referenced papers in
|
||||
all of computer science, and with good reason.</para>
|
||||
</biblioentry>
|
||||
<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>
|
||||
<orgname>ISO/IEC</orgname>
|
||||
<releaseinfo>14882:1998(E)</releaseinfo>
|
||||
<para>This is the official C++ Standards document. Available from the ANSI
|
||||
(American National Standards Institute) Electronic Standards Store.</para>
|
||||
</biblioentry>
|
||||
<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>
|
||||
<issuenum>No. 2</issuenum>
|
||||
<date>December, 1989</date>
|
||||
</biblioset>
|
||||
<biblioset>
|
||||
<author>
|
||||
<firstname>Charles</firstname>
|
||||
<othername>E.</othername>
|
||||
<surname>McDowell</surname>
|
||||
</author>
|
||||
<author>
|
||||
<firstname>David</firstname>
|
||||
<othername>P.</othername>
|
||||
<surname>Helmbold</surname>
|
||||
</author>
|
||||
<title>
|
||||
<ulink
|
||||
url="http://www.acm.org/pubs/citations/journals/surveys/1989-21-4/p593-mcdowell/"
|
||||
>Debugging Concurrent Programs</ulink>
|
||||
</title>
|
||||
</biblioset>
|
||||
<para>Identifies many of the unique failure modes and debugging difficulties
|
||||
associated with concurrent programs.</para>
|
||||
</biblioentry>
|
||||
<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>
|
||||
</title>
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Douglas</firstname>
|
||||
<othername>C.</othername>
|
||||
<surname>Schmidt</surname>
|
||||
</author>
|
||||
<author>
|
||||
<firstname>Irfan</firstname>
|
||||
<surname>Pyarali</surname>
|
||||
</author>
|
||||
</authorgroup>
|
||||
<orgname>Department of Computer Science, Washington University, St. Louis,
|
||||
Missouri</orgname>
|
||||
<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.Thread;
|
||||
are even more complicated yet.</para>
|
||||
</biblioentry>
|
||||
<biblioentry id="thread.bib.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"
|
||||
>Pattern-Oriented Architecture Volume 2</ulink>
|
||||
</title>
|
||||
<subtitle>Patterns for Concurrent and Networked Objects</subtitle>
|
||||
<titleabbrev>POSA2</titleabbrev>
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Douglas</firstname>
|
||||
<othername>C.</othername>
|
||||
<surname>Schmidt</surname>
|
||||
</author>
|
||||
<author>
|
||||
<firstname>Michael</firstname>
|
||||
<lastname>Stal</lastname>
|
||||
</author>
|
||||
<author>
|
||||
<firstname>Hans</firstname>
|
||||
<surname>Rohnert</surname>
|
||||
</author>
|
||||
<author>
|
||||
<firstname>Frank</firstname>
|
||||
<surname>Buschmann</surname>
|
||||
</author>
|
||||
</authorgroup>
|
||||
<publisher>Wiley</publisher>
|
||||
<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.Thread;
|
||||
documentation.</para>
|
||||
</biblioentry>
|
||||
<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>
|
||||
</title>
|
||||
<edition>Special Edition</edition>
|
||||
<publisher>Addison-Wesley</publisher>
|
||||
<copyright><year>2000</year></copyright>
|
||||
<isbn>ISBN: 0-201-70073-5</isbn>
|
||||
<para>The first book a C++ programmer should own. Note that the 3rd edition
|
||||
(and subsequent editions like the Special Edition) has been rewritten to
|
||||
cover the ISO standard language and library.</para>
|
||||
</biblioentry>
|
||||
</bibliography>
|
||||
62
doc/build.xml
Normal file
62
doc/build.xml
Normal file
@@ -0,0 +1,62 @@
|
||||
<?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 % 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.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.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.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.Thread;, as well as for building their own projects using
|
||||
&Boost.Thread;.
|
||||
</para>
|
||||
<section id="thread.build.building">
|
||||
<title>Building the &Boost.Thread; Libraries</title>
|
||||
<para>
|
||||
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.Thread; library.
|
||||
<note>Invoking the above command in <emphasis>boost_root</emphasis> will build all of
|
||||
the Boost distribution, including &Boost.Thread;.</note>
|
||||
</para>
|
||||
<para>
|
||||
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.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.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
|
||||
guidelines. One of the most frequently reported problems when trying to do this
|
||||
occurs from not enabling the compiler's and linker's support for multi-threading.
|
||||
</para>
|
||||
</section>
|
||||
<section id="thread.build.testing">
|
||||
<title>Testing the &Boost.Thread; Libraries</title>
|
||||
<para>
|
||||
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>
|
||||
</section>
|
||||
</section>
|
||||
@@ -1,128 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, Boost.Threads, thread library, C++">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<title>Boost.Threads, call_once</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">call_once</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><A href="#Introduction">Introduction</A><br>
|
||||
<A href="#Header">Header</A><br>
|
||||
<A href="#Synopsis">Synopsis</A><br>
|
||||
<A href="#Members">Members</A><br>
|
||||
<A href="#Example">Example</A></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>The <code>call_once</code> routine and <code>once_flag</code> type can be used to
|
||||
run a routine exactly once. This can be used to initialize data in a
|
||||
<a href="definitions.html#Thread-safe">thread-safe</a> manner.</p>
|
||||
|
||||
<h2><a name="Header">Header</a></h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/once.hpp"><boost/thread/once.hpp></a>
|
||||
</pre>
|
||||
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
|
||||
<pre>
|
||||
namespace boost {
|
||||
|
||||
typedef <i>[implementation defined]</i> once_flag;
|
||||
const once_flag once_init = <i>[implementation defined]</i>;
|
||||
void call_once(void (*func)(), once_flag& flag);
|
||||
|
||||
} // namespace boost
|
||||
</pre>
|
||||
|
||||
<h2><a name="Reference">Reference</a></h2>
|
||||
|
||||
<hr>
|
||||
<h3>once_flag</h3>
|
||||
|
||||
<p>This implementation defined type is used as a flag to insure a routine is called only once.
|
||||
Instances of this type should be statically initialized to <code>once_init</code>.</p>
|
||||
|
||||
<hr>
|
||||
<h3>once_init</h3>
|
||||
|
||||
<p>This is a constant value used to initialize <code>once_flag</code> instances
|
||||
to indicate that the logically associated routine has not been run yet.</p>
|
||||
|
||||
<hr>
|
||||
<h3>call_once</h3>
|
||||
|
||||
<pre>
|
||||
void call_once(void (*func)(), once_flag& flag);
|
||||
</pre>
|
||||
|
||||
<p><b>Requires:</b> The function <code>func</code> shall not throw exceptions.</p>
|
||||
|
||||
<p><b>Effects:</b> As if (in an atomic fashion)</p>
|
||||
|
||||
<code>
|
||||
if (flag == once_init)<br>
|
||||
func();
|
||||
</code>
|
||||
|
||||
<p><b>Postcondition:</b> <code>flag</code> != <code>once_init</code></p>
|
||||
|
||||
<hr>
|
||||
<h2><a name="Example">Example Usage</a></h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
||||
#include <a href="../../../boost/thread/tss.hpp"><boost/thread/once.hpp></a>
|
||||
#include <cassert>
|
||||
|
||||
int value=0;
|
||||
boost::once_flag once = boost::once_init;
|
||||
|
||||
void init()
|
||||
{
|
||||
++value;
|
||||
}
|
||||
|
||||
void thread_proc()
|
||||
{
|
||||
boost::call_once(&init, once);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
boost::thread_group threads;
|
||||
for (int i=0; i<5; ++i)
|
||||
threads.create_thread(&thread_proc);
|
||||
threads.join_all();
|
||||
assert(value == 1);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39334" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
2290
doc/concepts.xml
Normal file
2290
doc/concepts.xml
Normal file
File diff suppressed because it is too large
Load Diff
196
doc/condition-ref.xml
Normal file
196
doc/condition-ref.xml
Normal file
@@ -0,0 +1,196 @@
|
||||
<?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 % 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">
|
||||
<class name="condition">
|
||||
<inherit access="private">
|
||||
<type><classname>boost::noncopyable</classname></type>
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<purpose>
|
||||
<para>An object of class <classname>condition</classname> is a
|
||||
synchronization primitive used to cause a thread to wait until a
|
||||
particular shared-data condition (or time) is met.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>A <classname>condition</classname> object is always used in
|
||||
conjunction with a <link linkend="thread.concepts.mutexes">mutex</link>
|
||||
object (an object whose type is a model of a <link
|
||||
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="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
|
||||
from a call to one of the <classname>condition</classname> object's wait
|
||||
functions the mutex object is again locked. The tricky unlock/lock
|
||||
sequence is performed automatically by the
|
||||
<classname>condition</classname> object's wait functions.</para>
|
||||
<para>The <classname>condition</classname> type is often used to
|
||||
implement the Monitor Object and other important patterns (see
|
||||
&cite.SchmidtStalRohnertBuschmann; and &cite.Hoare74;). Monitors are one
|
||||
of the most important patterns for creating reliable multithreaded
|
||||
programs.</para>
|
||||
<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>
|
||||
|
||||
<constructor>
|
||||
<effects><simpara>Constructs a <classname>condition</classname>
|
||||
object.</simpara></effects>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<effects><simpara>Destroys <code>*this</code>.</simpara></effects>
|
||||
</destructor>
|
||||
|
||||
<method-group name="notification">
|
||||
<method name="notify_one">
|
||||
<type>void</type>
|
||||
<effects><simpara>If there is a thread waiting on <code>*this</code>,
|
||||
change that thread's state to ready. Otherwise there is no
|
||||
effect.</simpara></effects>
|
||||
<notes><simpara>If more than one thread is waiting on <code>*this</code>,
|
||||
it is unspecified which is made ready. After returning to a ready
|
||||
state the notified thread must still acquire the mutex again (which
|
||||
occurs within the call to one of the <classname>condition</classname>
|
||||
object's wait functions.)</simpara></notes>
|
||||
</method>
|
||||
|
||||
<method name="notify_all">
|
||||
<type>void</type>
|
||||
<effects><simpara>Change the state of all threads waiting on
|
||||
<code>*this</code> to ready. If there are no waiting threads,
|
||||
<code>notify_all()</code> has no effect.</simpara></effects>
|
||||
</method>
|
||||
</method-group>
|
||||
|
||||
<method-group name="waiting">
|
||||
<method name="wait">
|
||||
<template>
|
||||
<template-type-parameter name="ScopedLock"/>
|
||||
</template>
|
||||
|
||||
<type>void</type>
|
||||
|
||||
<parameter name="lock">
|
||||
<paramtype>ScopedLock&</paramtype>
|
||||
</parameter>
|
||||
|
||||
<requires><simpara><code>ScopedLock</code> meets the <link
|
||||
linkend="thread.concepts.ScopedLock">ScopedLock</link>
|
||||
requirements.</simpara></requires>
|
||||
<effects><simpara>Releases the lock on the <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
|
||||
lock.</simpara></effects>
|
||||
<throws><simpara><classname>lock_error</classname> if
|
||||
<code>!lock.locked()</code></simpara></throws>
|
||||
</method>
|
||||
|
||||
<method name="wait">
|
||||
<template>
|
||||
<template-type-parameter name="ScopedLock"/>
|
||||
<template-type-parameter name="Pred"/>
|
||||
</template>
|
||||
|
||||
<type>void</type>
|
||||
|
||||
<parameter name="lock">
|
||||
<paramtype>ScopedLock&</paramtype>
|
||||
</parameter>
|
||||
|
||||
<parameter name="pred">
|
||||
<paramtype>Pred</paramtype>
|
||||
</parameter>
|
||||
|
||||
<requires><simpara><code>ScopedLock</code> meets the <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())
|
||||
wait(lock)</code></simpara></effects>
|
||||
<throws><simpara><classname>lock_error</classname> if
|
||||
<code>!lock.locked()</code></simpara></throws>
|
||||
</method>
|
||||
|
||||
<method name="timed_wait">
|
||||
<template>
|
||||
<template-type-parameter name="ScopedLock"/>
|
||||
</template>
|
||||
|
||||
<type>bool</type>
|
||||
|
||||
<parameter name="lock">
|
||||
<paramtype>ScopedLock&</paramtype>
|
||||
</parameter>
|
||||
|
||||
<parameter name="xt">
|
||||
<paramtype>const <classname>boost::xtime</classname>&</paramtype>
|
||||
</parameter>
|
||||
|
||||
<requires><simpara><code>ScopedLock</code> meets the <link
|
||||
linkend="thread.concepts.ScopedLock">ScopedLock</link>
|
||||
requirements.</simpara></requires>
|
||||
<effects><simpara>Releases the lock on the <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>
|
||||
is reached, and then reacquires the lock.</simpara></effects>
|
||||
<returns><simpara><code>false</code> if time <code>xt</code> is reached,
|
||||
otherwise <code>true</code>.</simpara></returns>
|
||||
<throws><simpara><classname>lock_error</classname> if
|
||||
<code>!lock.locked()</code></simpara></throws>
|
||||
</method>
|
||||
|
||||
<method name="timed_wait">
|
||||
<template>
|
||||
<template-type-parameter name="ScopedLock"/>
|
||||
<template-type-parameter name="Pred"/>
|
||||
</template>
|
||||
|
||||
<type>bool</type>
|
||||
|
||||
<parameter name="lock">
|
||||
<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="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,
|
||||
xt)) return false; } return true;</code></simpara></effects>
|
||||
<returns><simpara><code>false</code> if <code>xt</code> is reached,
|
||||
otherwise <code>true</code>.</simpara></returns>
|
||||
<throws><simpara><classname>lock_error</classname> if
|
||||
<code>!lock.locked()</code></simpara></throws>
|
||||
</method>
|
||||
</method-group>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
@@ -1,333 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, BTL, thread library, C++">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<title>Boost.Threads, condition</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080" text="#000000">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><IMG height=86 alt="C++ Boost" src="../../../c++boost.gif" width=277></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">condition</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><A href="#Introduction">Introduction</a><br>
|
||||
<A href="#Header">Header</a><br>
|
||||
<A href="#Synopsis">Synopsis</a><br>
|
||||
<A href="#Members">Members</a><br>
|
||||
<A href="#Example">Example</a></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>An object of class <code>condition</code> is a synchronization primitive used to
|
||||
cause a thread to wait until a particular shared-data condition (or time) is met.
|
||||
A <code>condition</code> object is always used in conjunction with a mutex
|
||||
object modeling a <a href="mutex_concept.html">Mutex Concept</a>. The mutex must be locked prior to waiting on the
|
||||
<code>condition</code>, which is ensured by passing a lock object modeling a <a href="lock_concept.html">Lock
|
||||
Concept</a> to the <code>condition</code> object's <code>wait</code> functions. While the thread is waiting on the <code>condition</code>
|
||||
object,
|
||||
the mutex associated with the lock is unlocked. When the thread returns
|
||||
from a call to one of the <code>condition</code> object's <code>wait</code> functions,
|
||||
the mutex is again locked. The tricky lock/unlock/lock sequence is performed
|
||||
automatically by the <code>condition</code> object's <code>wait</code>
|
||||
functions.</p>
|
||||
|
||||
<p>The <code>condition</code> type is often used to implement the <i>Monitor Object</i>
|
||||
and other important patterns. See <A href="bibliography.html#Schmidt-00">[Schmidt-00]</a>
|
||||
and <A href="bibliography.html#Hoare-74">[Hoare 74]</a>. Monitors are one of the most
|
||||
important patterns for creating reliable multithreaded programs.</p>
|
||||
|
||||
<p>See <A href="definitions.html">Formal Definitions</a> for definitions of thread
|
||||
states <A href="definitions.html#state">blocked</a> and
|
||||
<A href="definitions.html#state">ready</a>. Note that "waiting" is a synonym
|
||||
for blocked.</p>
|
||||
|
||||
<h2><a name="Header">Header</a></h2>
|
||||
|
||||
<pre>
|
||||
#include <A href="../../../boost/thread/condition.hpp"><boost/thread/condition.hpp></a>
|
||||
</pre>
|
||||
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
|
||||
<pre>
|
||||
namespace boost {
|
||||
|
||||
class condition : private <A href="../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
|
||||
// Class condition meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
|
||||
{
|
||||
public:
|
||||
condition();
|
||||
~condition();
|
||||
|
||||
void notify_one();
|
||||
void notify_all();
|
||||
template <typename <a href="scoped_lock.html">ScopedLock</a>>
|
||||
void wait(<a href="scoped_lock.html">ScopedLock</a>& lock);
|
||||
template <typename <a href="scoped_lock.html">ScopedLock</a>, typename <A href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</A>>
|
||||
void wait(<a href="scoped_lock.html">ScopedLock</a>& lock, <A href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</A> pred);
|
||||
template <typename <a href="scoped_lock.html">ScopedLock</a>>
|
||||
bool timed_wait(<a href="scoped_lock.html">ScopedLock</a>& lock, const xtime& xt);
|
||||
template <typename <a href="scoped_lock.html">ScopedLock</a>, typename <A href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</A>>
|
||||
bool timed_wait(<a href="scoped_lock.html">ScopedLock</a>& lock, const xtime& xt, <A href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</A> pred);
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
</pre>
|
||||
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Constructor</h3>
|
||||
|
||||
<pre>
|
||||
condition();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> Constructs a <code>condition</code>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Destructor</h3>
|
||||
|
||||
<pre>
|
||||
~condition();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> Destroys <code>*this</code>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>notify_one</h3>
|
||||
|
||||
<pre>
|
||||
void notify_one();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> If there is a thread waiting on <code>*this</code>, change
|
||||
that thread's state to ready. Otherwise there is no effect.</p>
|
||||
|
||||
<p><b>Notes:</b> If more that one thread is waiting on the condition, it is
|
||||
unspecified which is made ready.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>notify_all</h3>
|
||||
|
||||
<pre>
|
||||
void notify_all();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> Change the state of all threads waiting on <code>*this</code>
|
||||
to ready. If there are no waiting threads, <code>notify_all()</code> has no effect.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>wait</h3>
|
||||
|
||||
<pre>
|
||||
template <typename ScopedLock>
|
||||
void wait(ScopedLock& lock);
|
||||
</pre>
|
||||
|
||||
<p><b>Requires:</b> ScopedLock meets the
|
||||
<A href="lock_concept.html#ScopedLock">ScopedLock</a> requirements.</p>
|
||||
|
||||
<p><b>Effects:</b> Releases the lock on the <A href="mutex_concept.html">mutex model</a>
|
||||
associated with <code>lock</code>, blocks the current thread of execution until readied
|
||||
by a call to <code>this->notify_one()</code> or <code>this->notify_all()</code>,
|
||||
and then reacquires the lock. All effects occur in an atomic fashion.</p>
|
||||
|
||||
<p><b>Throws:</b> <code><A href="lock_error.html">lock_error</a></code>
|
||||
if <code>!lock.locked()</code></p>
|
||||
|
||||
<p><b>Danger:</b> This version should always be used within a loop checking that the
|
||||
state logically associated with the <code>condition</code> has become true. Without
|
||||
the loop, race conditions can ensue due to possible "spurious wake ups". The second
|
||||
version encapsulates this loop idiom internally and is generally the preferred method.</p>
|
||||
|
||||
<pre>
|
||||
template <typename ScopedLock, typename Pr>
|
||||
void wait(ScopedLock& lock, Pr pred);
|
||||
</pre>
|
||||
|
||||
<p><b>Requires:</b> ScopedLock meets the
|
||||
<A href="lock_concept.html#ScopedLock">ScopedLock</a> requirements, return from
|
||||
<code>pred()</code> convertible to bool.</p>
|
||||
|
||||
<p><b>Effects:</b> As if:</p>
|
||||
|
||||
<code>
|
||||
while (!pred()) wait(lock)
|
||||
</code>
|
||||
|
||||
<p><b>Throws:</b> <code><A href="lock_error.html">lock_error</a></code> if
|
||||
<code>!lock.locked()</code></p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>timed_wait</h3>
|
||||
|
||||
<pre>
|
||||
template <typename ScopedTimedLock>
|
||||
bool timed_wait(ScopedTimedLock& lock, const <a href="xtime.html">xtime</a>& xt);
|
||||
</pre>
|
||||
|
||||
<p><b>Requires:</b> ScopedTimeLock meets the
|
||||
<A href="lock_concept.html#ScopedTimedLock">ScopedTimedLock</a> requirements.</p>
|
||||
|
||||
<p><b>Effects:</b> Releases the lock on the <A href="mutex_concept.html">mutex model</a>
|
||||
associated with the <code>lock</code>, blocks the current thread of execution until
|
||||
readied by a call to <code>this->notify_one()</code> or
|
||||
<code>this->notify_all()</code>, or until <code>xt</code>, and then reacquires the
|
||||
lock. All effects occur in an atomic fashion.</p>
|
||||
|
||||
<p><b>Throws:</b> <code><A href="lock_error.html">lock_error</a></code> if
|
||||
<code>!lock.locked()</code></p>
|
||||
|
||||
<p><b>Danger:</b> This version should always be used within a loop checking that the
|
||||
state logically associated with the <code>condition</code> has become true. Without
|
||||
the loop, race conditions can ensue due to "spurious wake ups". The second version
|
||||
encapsulates this loop idiom internally and is generally the preferred method.</p>
|
||||
|
||||
<p><b>Returns:</b> <code>false</code> if <code>xt</code> is reached, otherwise
|
||||
<code>true</code>.</p>
|
||||
|
||||
<pre>
|
||||
template <typename ScopedTimedLock, typename Pr>
|
||||
bool timed_wait(ScopedTimedLock& lock, const <a href="xtime.html">xtime</a>& xt, Pr pred);
|
||||
</pre>
|
||||
|
||||
<p><b>Requires: </b>ScopedTimeLock meets the
|
||||
<A href="lock_concept.html#ScopedTimedLock">ScopedTimedLock</a> requirements,
|
||||
return from <code>pred()</code> convertible to bool.</p>
|
||||
|
||||
<p><b>Effects: </b>As if:</p>
|
||||
|
||||
<code>
|
||||
while (!pred())<br>
|
||||
{<br>
|
||||
if (!timed_wait(lock, xt))<br>
|
||||
return false;<br>
|
||||
}
|
||||
</code>
|
||||
|
||||
<p><b>Throws:</b> <code><A href="lock_error.html">lock_error</a></code> if
|
||||
<code>!lock.locked()</code></p>
|
||||
|
||||
<p><b>Returns:</b> <code>false</code> if <code>xt</code> is reached, otherwise
|
||||
<code>true</code>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="Example">Example Usage</a></h2>
|
||||
|
||||
<pre>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <A href="../../../boost/utility.hpp"><boost/utility.hpp></a>
|
||||
#include <A href="../../../boost/thread/condition.hpp"><boost/thread/condition.hpp></a>
|
||||
#include <A href="../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
||||
|
||||
class bounded_buffer : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
typedef boost::mutex::scoped_lock lock;
|
||||
|
||||
bounded_buffer(int n) : begin(0), end(0), buffered(0), circular_buf(n) { }
|
||||
|
||||
void send (int m) {
|
||||
lock lk(monitor);
|
||||
while (buffered == circular_buf.size())
|
||||
buffer_not_full.wait(lk);
|
||||
circular_buf[end] = m;
|
||||
end = (end+1) % circular_buf.size();
|
||||
++buffered;
|
||||
buffer_not_empty.notify_one();
|
||||
}
|
||||
int receive() {
|
||||
lock lk(monitor);
|
||||
while (buffered == 0)
|
||||
buffer_not_empty.wait(lk);
|
||||
int i = circular_buf[begin];
|
||||
begin = (begin+1) % circular_buf.size();
|
||||
--buffered;
|
||||
buffer_not_full.notify_one();
|
||||
return i;
|
||||
}
|
||||
|
||||
private:
|
||||
int begin, end, buffered;
|
||||
std::vector<int> circular_buf;
|
||||
boost::condition buffer_not_full, buffer_not_empty;
|
||||
boost::mutex monitor;
|
||||
};
|
||||
|
||||
bounded_buffer buf(2);
|
||||
|
||||
void sender() {
|
||||
int n = 0;
|
||||
while (n < 100) {
|
||||
buf.send(n);
|
||||
std::cout << "sent: " << n << std::endl;
|
||||
++n;
|
||||
}
|
||||
buf.send(-1);
|
||||
}
|
||||
|
||||
void receiver() {
|
||||
int n;
|
||||
do {
|
||||
n = buf.receive();
|
||||
std::cout << "received: " << n << std::endl;
|
||||
} while (n != -1); // -1 indicates end of buffer
|
||||
}
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
boost::thread thrd1(&sender);
|
||||
boost::thread thrd2(&receiver);
|
||||
thrd1.join();
|
||||
thrd2.join();
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Typical output (dependent on scheduling policies) is:</p>
|
||||
|
||||
<pre>
|
||||
sent: 0
|
||||
sent: 1
|
||||
received: 0
|
||||
received: 1
|
||||
sent: 2
|
||||
sent: 3
|
||||
received: 2
|
||||
received: 3
|
||||
sent: 4
|
||||
received: 4
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39334" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <A href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
103
doc/config.html
103
doc/config.html
@@ -1,103 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, BTL, thread library, C++">
|
||||
<title>Boost.Threads, Configuration Information</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">Configuration Information</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><b>Boost.Threads</b> uses several configuration macros in <a href="../../config/config.htm"> <boost/config.hpp></a>.
|
||||
These macros are documented here. Most of the macros are
|
||||
of interest only to developers attempting to provide new implementations of <b>Boost.Threads</b>.
|
||||
The one exception to this is BOOST_HAS_THREADS.</p>
|
||||
|
||||
<table cellspacing="10" width="100%">
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<b>Macro</b>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<b>Meaning</b>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
BOOST_HAS_THREADS
|
||||
</td>
|
||||
<td valign="top">
|
||||
Indicates that threading support is available. This means both that there is a
|
||||
platform specific implementation for <b>Boost.Threads</b> and that threading
|
||||
support has been enabled in a platform specific manner. For instance, on the
|
||||
Win32 platform there's an implementation for <b>Boost.Threads</b> but unless
|
||||
the program is compiled against one of the multi-threading runtimes
|
||||
(often determined by the
|
||||
compiler predefining the macro _MT) the
|
||||
BOOST_HAS_THREADS macro remains undefined.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
BOOST_HAS_WINTHREADS
|
||||
</td>
|
||||
<td valign="top">
|
||||
Indicates that the platform has the Microsoft Win32 threading libraries,
|
||||
and that they should be used
|
||||
to implement <b>Boost.Threads</b>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
BOOST_HAS_PTHREADS
|
||||
</td>
|
||||
<td valign="top">
|
||||
Indicates that the platform has the POSIX pthreads libraries, and that
|
||||
they should be used
|
||||
to implement <b>Boost.Threads</b>.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
BOOST_HAS_FTIME
|
||||
</td>
|
||||
<td valign="top">
|
||||
Indicates that the implementation should use GetSystemTimeAsFileTime() and
|
||||
the FILETIME type to calculate the current time. This is an implementation
|
||||
detail used by boost::detail::getcurtime().
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top">
|
||||
BOOST_HAS_GETTTIMEOFDAY
|
||||
</td>
|
||||
<td valign="top">
|
||||
Indicates that the implementation should use gettimeofday() to calculate the
|
||||
current time. This is an implementation detail used by boost::detail::getcurtime().
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->18 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39344" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
96
doc/configuration.xml
Normal file
96
doc/configuration.xml
Normal file
@@ -0,0 +1,96 @@
|
||||
<?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 % 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.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.Thread; but are expected to be used
|
||||
by application code.
|
||||
</para>
|
||||
<informaltable>
|
||||
<tgroup cols="2">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Macro</entry>
|
||||
<entry>Meaning</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>BOOST_HAS_THREADS</entry>
|
||||
<entry>
|
||||
Indicates that threading support is available. This means both that there
|
||||
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.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.
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</section>
|
||||
<section id="thread.configuration.implementation">
|
||||
<title>Library Defined Implementation Macros</title>
|
||||
<para>
|
||||
These macros are defined by &Boost.Thread; and are implementation details
|
||||
of interest only to implementors.
|
||||
</para>
|
||||
<informaltable>
|
||||
<tgroup cols="2">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Macro</entry>
|
||||
<entry>Meaning</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<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.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.Thread;.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>BOOST_HAS_FTIME</entry>
|
||||
<entry>
|
||||
Indicates that the implementation should use GetSystemTimeAsFileTime()
|
||||
and the FILETIME type to calculate the current time. This is an implementation
|
||||
detail used by boost::detail::getcurtime().
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>BOOST_HAS_GETTTIMEOFDAY</entry>
|
||||
<entry>
|
||||
Indicates that the implementation should use gettimeofday() to calculate
|
||||
the current time. This is an implementation detail used by boost::detail::getcurtime().
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</section>
|
||||
</section>
|
||||
@@ -1,244 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Boost.Threads Definitions</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center"> Definitions</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2>Introduction</h2>
|
||||
<p>The definitions are given in terms of the <a href="bibliography.html#ISO-98"> C++ Standard</a>. References to the standard
|
||||
are in the form [1.2.3/4], which
|
||||
represents the section number, with the paragraph number following the "/".</p>
|
||||
<p>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++ implementation as defined by the C++ Standard.</p>
|
||||
<h2>Definitions</h2>
|
||||
<h3>Thread</h3>
|
||||
<p>Thread is short for "thread of execution". A thread of execution is an execution environment [1.9/7] within the execution environment
|
||||
of a C++ program [1.9]. The main() function [3.6.1] of the program is the
|
||||
initial function of the initial thread. A program in a multi-threading
|
||||
environment always has an initial thread even if the program explicitly creates
|
||||
no additional threads.</p>
|
||||
<p>Unless otherwise specified, each thread shares all aspects of its execution environment with
|
||||
other threads in the program. Shared aspects of the execution environment
|
||||
include, but are not limited to, the following:</p>
|
||||
<ul>
|
||||
<li>Static storage duration (static, extern) objects [3.7.1].</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>Dynamic storage duration (heap) objects [3.7.3]. Thus each memory
|
||||
allocation will return a unique addresses, regardless of the thread making
|
||||
the allocation request.</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>Automatic storage duration (stack) objects [3.7.2] accessed via pointer or
|
||||
reference from another thread.</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>Resources provided by the operating
|
||||
system. For example, files.</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>The program itself. In other words, each thread is executing some
|
||||
function of the same program, not a totally different program.</li>
|
||||
</ul>
|
||||
<p>Each thread has its own:</p>
|
||||
<ul>
|
||||
<li>Registers and current execution sequence (program counter) [1.9/5].</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>Automatic storage duration (stack) objects [3.7.2].</li>
|
||||
</ul>
|
||||
<h3><a name="Thread-safe">Thread-safe</a></h3>
|
||||
<p>A program is thread-safe if it has no <a href="#Race condition">race
|
||||
conditions</a>, does not <a href="#Deadlock">deadlock</a>, and has no <a href="#Priority failure">priority
|
||||
failures</a>.</p>
|
||||
<p>Note that thread-safety does not necessarily imply efficiency, and than while
|
||||
some thread-safety violations can be determined statically at compile time, many
|
||||
thread-safety errors can only only be detected at runtime.</p>
|
||||
<h3>Thread <a name="State">State</a></h3>
|
||||
<p>During the lifetime of a thread, it shall be in one of the following
|
||||
states:</p>
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<td><b>State</b></td>
|
||||
<td><b>Description</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Ready</td>
|
||||
<td>Ready to run, but waiting for a processor.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Running</td>
|
||||
<td>Currently executing on a processor. Zero or more threads may be running
|
||||
at any time, with a maximum equal to the number of processors. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Blocked</td>
|
||||
<td>Waiting for some resource other than a processor which is not currently
|
||||
available, or for the completion of calls to library functions [1.9/6].
|
||||
The term "waiting" is synonymous for "blocked"</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Terminated</td>
|
||||
<td>Finished execution but not yet detached or joined.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>Thread state transitions shall occur only as specified:</p>
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<td><b>From</b></td>
|
||||
<td><b>To</b></td>
|
||||
<td><b>Cause</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<p align="left">[none]</td>
|
||||
<td>Ready</td>
|
||||
<td>Thread is created by a call to a library function. In the case of
|
||||
the initial thread, creation is implicit and occurs during the startup of
|
||||
the main() function [3.6.1].</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Ready</td>
|
||||
<td>Running</td>
|
||||
<td>Processor becomes available.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Running</td>
|
||||
<td>Ready</td>
|
||||
<td>Thread preempted.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Running</td>
|
||||
<td>Blocked</td>
|
||||
<td>Thread calls a library function which waits for a resource or for the
|
||||
completion of I/O.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Running</td>
|
||||
<td>Terminated</td>
|
||||
<td>Thread returns from its initial function, calls a thread termination
|
||||
library function, or is cancelled by some other thread calling a thread
|
||||
termination library function.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Blocked</td>
|
||||
<td>Ready</td>
|
||||
<td>The resource being waited for becomes available, or the blocking library
|
||||
function completes.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Terminated</td>
|
||||
<td>[none]</td>
|
||||
<td>Thread is detached or joined by some other thread calling the
|
||||
appropriate library function, or by program termination [3.6.3].</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>[Note: if a suspend() function is added to the threading library, additional
|
||||
transitions to the blocked state will have to be added to the above table.]</p>
|
||||
<h3><a name="Race condition">Race condition</a></h3>
|
||||
<p>A race condition is what occurs when multiple threads read and
|
||||
write to the same memory without proper synchronization, resulting in an
|
||||
incorrect value being read or written. The result of a race condition may
|
||||
be a bit pattern which isn't even a valid value for the data type. A race
|
||||
condition results in undefined behavior [1.3.12].</p>
|
||||
<p>Race conditions can be prevented by serializing memory access
|
||||
using the tools provided by Boost.Threads. </p>
|
||||
<h3><a name="Deadlock">Deadlock</a></h3>
|
||||
<p>Deadlock is an execution state where for some set of threads, each thread in
|
||||
the set is blocked waiting for some action by one of the other threads in the
|
||||
set. Since each is waiting on the others, none will ever become ready again.</p>
|
||||
<h3><a name="Priority failure">Priority failure</a></h3>
|
||||
<p>A priority failure (such as priority inversion or infinite overtaking) occurs
|
||||
when threads executed in such a sequence that required work is not performed in
|
||||
time to be useful.</p>
|
||||
<h2>Memory visibility between threads</h2>
|
||||
<p>An address [1.7] shall always point to the same memory byte, regardless of the
|
||||
thread or processor dereferencing the address.</p>
|
||||
<p>An object [1.8, 1.9] is accessible from multiple threads if it is of
|
||||
static storage duration (static, extern) [3.7.1], or if a pointer or reference to
|
||||
it is explicitly or
|
||||
implicitly dereferenced in multiple threads.</p>
|
||||
<p>For an object accessible from multiple threads, the value of the object
|
||||
accessed from one thread may be indeterminate or different than the value
|
||||
accessed from another thread, except under the conditions specified in the following
|
||||
table. For the same row of the table, the value of an object
|
||||
accessible at the indicated sequence point in thread A will be determinate and the
|
||||
same if accessed at or after the indicated sequence point in thread B, provided
|
||||
the object is not otherwise modified. In the table, the
|
||||
"sequence point at a call" is the sequence point after the evaluation
|
||||
of all function arguments [1.9/17], while the "sequence point after a
|
||||
call" is the sequence point after the copying of the returned
|
||||
value..." [1.9/17].</p>
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<td align="center"><b>Thread A</b></td>
|
||||
<td align="center"><b>Thread B</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>The sequence point at a call to a library thread-creation
|
||||
function. </td>
|
||||
<td>The first sequence point of the initial function in the new thread
|
||||
created by the Thread A call.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>The sequence point at a call to a library function which locks a mutex,
|
||||
directly or by waiting for a condition variable.</td>
|
||||
<td>The sequence point after a call to a library function which unlocks the
|
||||
same mutex.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>The last sequence point before thread termination.</td>
|
||||
<td>The sequence point after a call to a library function which joins the
|
||||
terminated thread.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>The sequence point at a call to a library function which signals or
|
||||
broadcasts a condition variable.</td>
|
||||
<td>The sequence point after the call to the library function which was
|
||||
waiting on that same condition variable or signal.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>The architecture of the execution environment and the observable behavior of
|
||||
the abstract machine [1.9] shall be the same on all processors.</p>
|
||||
<p>The latitude granted by the C++ standard for an implementation to alter the
|
||||
definition of observable behavior of the abstract machine to include additional library I/O
|
||||
functions [1.9/6] is extended to include threading library functions.</p>
|
||||
<p>When an exception is thrown and there is no matching exception handler in the
|
||||
same thread, behavior is undefined. The preferred behavior is the same as when there is no matching exception handler
|
||||
in a program [15.3/9]. That is, terminate() is called, and it is implementation defined
|
||||
whether or not the stack is unwound.</p>
|
||||
<h2><a name="Acknowledgements">Acknowledgements</a></h2>
|
||||
<p>This document has been much improved by the incorporation of comments from
|
||||
William Kempf.</p>
|
||||
<p>The visibility rules are based on <a href="bibliography.html#Butenhof-97">[Butenhof
|
||||
97]</a>. </p>
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %b %Y" startspan -->07 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14762" -->
|
||||
</p>
|
||||
<p>© Copyright Beman Dawes, 2001</p>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
159
doc/design.xml
Normal file
159
doc/design.xml
Normal file
@@ -0,0 +1,159 @@
|
||||
<?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 % 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.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
|
||||
able to handle parallel processing. Modern day operating systems usually
|
||||
provide some support for this through native thread APIs. Unfortunately,
|
||||
writing portable code that makes use of parallel processing in C++ is made
|
||||
very difficult by a lack of a standard interface for these native APIs.
|
||||
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.Thread; library is an attempt to define a portable interface
|
||||
for writing parallel processes in C++.</para>
|
||||
<section id="thread.design.goals">
|
||||
<title>Goals</title>
|
||||
<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.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>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Safety</term>
|
||||
<listitem>
|
||||
<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:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<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="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="thread.rationale.events" />.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Dangerous features, or features which may be misused, are
|
||||
identified as such in the documentation to make users aware of
|
||||
potential pitfalls.</para>
|
||||
</listitem>
|
||||
</itemizedlist></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Flexibility</term>
|
||||
<listitem>
|
||||
<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.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
|
||||
the documentation is written to explain why.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Efficiency</term>
|
||||
<listitem>
|
||||
<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.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
|
||||
effort was made to ensure efficient implementations, but when in
|
||||
conflict <emphasis>safety</emphasis> has always taken
|
||||
precedence.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist></para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Iterative Phases</title>
|
||||
<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.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.Thread; shall go through several growth cycles. Each phase in its
|
||||
development shall be roughly documented here.</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Phase 1, Synchronization Primitives</title>
|
||||
<para>Boost is all about providing high quality libraries with
|
||||
implementations for many platforms. Unfortunately, there's a big problem
|
||||
faced by developers wishing to supply such high quality libraries, namely
|
||||
thread-safety. The C++ standard doesn't address threads at all, but real
|
||||
world programs often make use of native threading support. A portable
|
||||
library that doesn't address the issue of thread-safety is therefore not
|
||||
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="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.Thread; focuses
|
||||
solely on providing portable primitive concepts for thread
|
||||
synchronization. Types provided in this phase include the
|
||||
<classname>boost::mutex</classname>,
|
||||
<classname>boost::try_mutex</classname>,
|
||||
<classname>boost::timed_mutex</classname>,
|
||||
<classname>boost::recursive_mutex</classname>,
|
||||
<classname>boost::recursive_try_mutex</classname>,
|
||||
<classname>boost::recursive_timed_mutex</classname>, and
|
||||
<classname>boost::lock_error</classname>. These are considered the "core"
|
||||
synchronization primitives, though there are others that will be added in
|
||||
later phases.</para>
|
||||
</section>
|
||||
<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.Thread; adds the <classname>boost::thread</classname> and
|
||||
<classname>boost::thread_specific_ptr</classname> types. With these
|
||||
additions the &Boost.Thread; library can be considered minimal but
|
||||
complete.</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>The Next Phase</title>
|
||||
<para>The next phase will address more advanced synchronization concepts,
|
||||
such as read/write mutexes and barriers.</para>
|
||||
</section>
|
||||
</section>
|
||||
30
doc/entities.xml
Normal file
30
doc/entities.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<!-- 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='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='thread.bib.McDowellHelmbold89'
|
||||
endterm='thread.bib.McDowellHelmbold89.abbrev'/></citation>">
|
||||
<!ENTITY cite.SchmidtPyarali "<citation><xref
|
||||
linkend='thread.bib.SchmidtPyarali'
|
||||
endterm='thread.bib.SchmidtPyarali.abbrev'/></citation>">
|
||||
<!ENTITY cite.SchmidtStalRohnertBuschmann "<citation><xref
|
||||
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>">
|
||||
62
doc/exceptions-ref.xml
Normal file
62
doc/exceptions-ref.xml
Normal file
@@ -0,0 +1,62 @@
|
||||
<?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 % 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">
|
||||
<class name="lock_error">
|
||||
<purpose>
|
||||
<simpara>The lock_error class defines an exception type thrown
|
||||
to indicate a locking related error has been detected.</simpara>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<simpara>Examples of errors indicated by a lock_error exception
|
||||
include a lock operation which can be determined to result in a
|
||||
deadlock, or unlock operations attempted by a thread that does
|
||||
not own the lock.</simpara>
|
||||
</description>
|
||||
|
||||
<inherit access="public">
|
||||
<type><classname>std::logical_error</classname></type>
|
||||
</inherit>
|
||||
|
||||
<constructor>
|
||||
<effects><simpara>Constructs a <code>lock_error</code> object.
|
||||
</simpara></effects>
|
||||
</constructor>
|
||||
</class>
|
||||
|
||||
<class name="thread_resource_error">
|
||||
<purpose>
|
||||
<simpara>The <classname>thread_resource_error</classname> class
|
||||
defines an exception type that is thrown by constructors in the
|
||||
&Boost.Thread; library when thread-related resources can not be
|
||||
acquired.</simpara>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<simpara><classname>thread_resource_error</classname> is used
|
||||
only when thread-related resources cannot be acquired; memory
|
||||
allocation failures are indicated by
|
||||
<classname>std::bad_alloc</classname>.</simpara>
|
||||
</description>
|
||||
|
||||
<inherit access="public">
|
||||
<type><classname>std::runtime_error</classname></type>
|
||||
</inherit>
|
||||
|
||||
<constructor>
|
||||
<effects><simpara>Constructs a <code>thread_resource_error</code>
|
||||
object.</simpara></effects>
|
||||
</constructor>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
174
doc/faq.html
174
doc/faq.html
@@ -1,174 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, BTL, thread library, C++">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<title>Boost.Threads, FAQ</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">Frequently Asked Questions</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>1. Are lock objects <a href="definitions.html#Thread-safe">thread-safe</a>?</h2>
|
||||
|
||||
<p><b>No!</b> 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 any way. Share
|
||||
<a href="mutex_concept.html">mutexes</a>, not locks. For more information see the
|
||||
<a href="rationale.html#lock_objects">rationale</a> behind the design for lock objects.</p>
|
||||
|
||||
<h2>2a. Why was Boost.Threads modeled after (specific library name)?</h2>
|
||||
|
||||
<p>It wasn't. Boost.Threads 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 theWin32 threading API. But the Boost.Threads
|
||||
design is very much in the spirit of C++, and thus doesn't model such C based
|
||||
APIs.</p>
|
||||
|
||||
<h2>2b. Why wasn't Boost.Threads modeled after (specific library name)?</h2>
|
||||
|
||||
<p>Existing C++ libraries either seemed dangerous (often failing to take
|
||||
advantage of prior art to reduce errors) or had excessive dependencies on
|
||||
library components unrelated to threading. Existing C libraries couldn't meet
|
||||
our C++ requirements, and were also missing certain features. For
|
||||
instance, POSIX threads doesn't support a maximum value for semaphores.
|
||||
The WIN32 thread API lacks condition variables, even though these are critical
|
||||
for the important Monitor pattern <a href="bibliography.html#Schmidt-00">[Schmidt
|
||||
00]</a>.</p>
|
||||
|
||||
<h2>3. Why do <a href="mutex_concept.html"> Mutexes</a> have noncopyable semantics?</h2>
|
||||
|
||||
<p>To ensure that <a href="definitions.html#Deadlock"> deadlocks</a> 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
|
||||
and ObjB is copy constructed from it, then when ObjB::foo() locks the mutex it has effectively
|
||||
locked ObjA as well. This behavior can result in deadlock. Other
|
||||
copy semantics result in similar problems (if you think you can prove this to
|
||||
be wrong then supply us with an alternative and we'll reconsider).</p>
|
||||
|
||||
<h2>4. How can you prevent <a href="definitions.html#Deadlock"> deadlock</a> from occurring when a thread must lock multiple
|
||||
mutexes?</h2>
|
||||
|
||||
<p>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 reusable class.</p>
|
||||
|
||||
<h2>5. Don't noncopyable <a href="mutex_concept.html"> mutex</a> semantics mean that a
|
||||
class with a mutex member will be noncopyable as well?</h2>
|
||||
|
||||
<p>No, but what it does mean is that the compiler can't generate a copy constructor
|
||||
and assignment operator, so they will have to be coded explicitly. This is a
|
||||
<b>good thing</b>, however, since the compiler generated operations would not
|
||||
be <a href="definitions.html#Thread-safe">thread-safe</a>. The following is a
|
||||
simple example of a class with copyable semantics and internal synchronization through
|
||||
a mutex member.</p>
|
||||
|
||||
<pre>
|
||||
class counter
|
||||
{
|
||||
public:
|
||||
// Doesn't need synchronization since there can be no references to *this
|
||||
// until after it's constructed!
|
||||
explicit counter(int initial_value)
|
||||
: m_value(initial_value)
|
||||
{
|
||||
}
|
||||
|
||||
// We only need to syncronize other for the same reason we don't have to
|
||||
// synchronize on construction!
|
||||
counter(const counter& other)
|
||||
{
|
||||
boost::mutex::scoped_lock scoped_lock(other.m_mutex);
|
||||
m_value = other.m_value;
|
||||
}
|
||||
|
||||
// For assignment we need to synchronize both objects!
|
||||
const counter& operator=(const counter& other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
boost::mutex::scoped_lock lock1(&m_mutex < &other.m_mutex ? m_mutex : other.m_mutex);
|
||||
boost::mutex::scoped_lock lock2(&m_mutex > &other.m_mutex ? m_mutex : other.m_mutex);
|
||||
m_value = other.m_value;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
int value() const
|
||||
{
|
||||
boost::mutex::scoped_lock scoped_lock(m_mutex);
|
||||
return m_value;
|
||||
}
|
||||
int increment()
|
||||
{
|
||||
boost::mutex::scoped_lock scoped_lock(m_mutex);
|
||||
return ++m_value;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable boost::mutex m_mutex;
|
||||
int m_value;
|
||||
};
|
||||
</pre>
|
||||
|
||||
<h2>6. How can you lock a <a href="mutex_concept.html"> mutex</a> member in a const member function, in order to
|
||||
implement the Monitor Pattern?</h2>
|
||||
|
||||
<p>The Monitor Pattern mutex <a href="bibliography.html#Schmidt-00">[Schmidt
|
||||
00]</a> should simply be declared as mutable. See the example code above. The internal state of mutex
|
||||
types could have been made mutable, with all lock calls made via const
|
||||
functions, but
|
||||
this does a poor job of documenting the actual semantics. Declaring a mutex member
|
||||
as mutable clearly documentations the intended semantics.</p>
|
||||
|
||||
<h2>7. Why supply <a href="condition.html">condition variables</a> rather than <a href="rationale.html#Events">
|
||||
event variables</a>?</h2>
|
||||
|
||||
<p>Condition variables result in user code much less prone to <a href="definitions.html#Race condition">race
|
||||
conditions</a> than event variables. See <a href="rationale.html#Events">Rationale</a>
|
||||
for analysis. Also see <a href="bibliography.html#Hoare-74">[Hoare74]</a>
|
||||
and <a href="bibliography.html#Schmidt-00">[Schmidt
|
||||
00]</a>.</p>
|
||||
|
||||
<h2>8. Why isn't thread cancellation or termination provided?</h2>
|
||||
|
||||
<p>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 truly safe (and portable)
|
||||
mechanism for this concept.</p>
|
||||
|
||||
<h2>9. Is it safe for threads to share automatic storage duration (stack)
|
||||
objects via pointers or references?</h2>
|
||||
|
||||
<p>Only if you can guarantee that the lifetime of the stack object will not end
|
||||
while other threads might still access the object. Thus the safest practice is
|
||||
to avoid sharing stack objects, particularly in designs where threads are
|
||||
created and destroyed dynamically. Restrict sharing of stack objects to simple
|
||||
designs with very clear and unchanging function and thread lifetimes. (Suggested
|
||||
by Darryl Green).</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->04 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39335" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
235
doc/faq.xml
Normal file
235
doc/faq.xml
Normal file
@@ -0,0 +1,235 @@
|
||||
<?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 % 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.faq" last-revision="$Date$">
|
||||
<title>Frequently Asked Questions</title>
|
||||
<qandaset>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Are lock objects <link
|
||||
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="thread.concepts.mutexes">Mutexes</link>, not
|
||||
Locks. For more information see the <link
|
||||
linkend="thread.rationale.locks">rationale</link> behind the
|
||||
design for lock objects.</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Why was &Boost.Thread; modeled after (specific library
|
||||
name)?</para>
|
||||
</question>
|
||||
<answer>
|
||||
<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.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.Thread; modeled after (specific library
|
||||
name)?</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>Existing C++ libraries either seemed dangerous (often failing to
|
||||
take advantage of prior art to reduce errors) or had excessive
|
||||
dependencies on library components unrelated to threading. Existing C
|
||||
libraries couldn't meet our C++ requirements, and were also missing
|
||||
certain features. For instance, the WIN32 thread API lacks condition
|
||||
variables, even though these are critical for the important Monitor
|
||||
pattern &cite.SchmidtStalRohnertBuschmann;.</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Why do <link linkend="thread.concepts.mutexes">Mutexes</link>
|
||||
have noncopyable semantics?</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>To ensure that <link
|
||||
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
|
||||
and ObjB is copy constructed from it, then when ObjB::foo() locks the
|
||||
mutex it has effectively locked ObjA as well. This behavior can result
|
||||
in deadlock. Other copy semantics result in similar problems (if you
|
||||
think you can prove this to be wrong then supply us with an alternative
|
||||
and we'll reconsider).</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>How can you prevent <link
|
||||
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.Thread; concept may wrap this pattern up in a
|
||||
reusable class.</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Don't noncopyable <link
|
||||
linkend="thread.concepts.mutexes">Mutex</link> semantics mean that a
|
||||
class with a mutex member will be noncopyable as well?</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>No, but what it does mean is that the compiler can't generate a
|
||||
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="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>
|
||||
class counter
|
||||
{
|
||||
public:
|
||||
// Doesn't need synchronization since there can be no references to *this
|
||||
// until after it's constructed!
|
||||
explicit counter(int initial_value)
|
||||
: m_value(initial_value)
|
||||
{
|
||||
}
|
||||
// We only need to synchronize other for the same reason we don't have to
|
||||
// synchronize on construction!
|
||||
counter(const counter& other)
|
||||
{
|
||||
boost::mutex::scoped_lock scoped_lock(other.m_mutex);
|
||||
m_value = other.m_value;
|
||||
}
|
||||
// For assignment we need to synchronize both objects!
|
||||
const counter& operator=(const counter& other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
boost::mutex::scoped_lock lock1(&m_mutex < &other.m_mutex ? m_mutex : other.m_mutex);
|
||||
boost::mutex::scoped_lock lock2(&m_mutex > &other.m_mutex ? m_mutex : other.m_mutex);
|
||||
m_value = other.m_value;
|
||||
return *this;
|
||||
}
|
||||
int value() const
|
||||
{
|
||||
boost::mutex::scoped_lock scoped_lock(m_mutex);
|
||||
return m_value;
|
||||
}
|
||||
int increment()
|
||||
{
|
||||
boost::mutex::scoped_lock scoped_lock(m_mutex);
|
||||
return ++m_value;
|
||||
}
|
||||
private:
|
||||
mutable boost::mutex m_mutex;
|
||||
int m_value;
|
||||
};
|
||||
</programlisting>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>How can you lock a <link
|
||||
linkend="thread.concepts.mutexes">Mutex</link> member in a const member
|
||||
function, in order to implement the Monitor Pattern?</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>The Monitor Pattern &cite.SchmidtStalRohnertBuschmann; mutex
|
||||
should simply be declared as mutable. See the example code above. The
|
||||
internal state of mutex types could have been made mutable, with all
|
||||
lock calls made via const functions, but this does a poor job of
|
||||
documenting the actual semantics (and in fact would be incorrect since
|
||||
the logical state of a locked mutex clearly differs from the logical
|
||||
state of an unlocked mutex). Declaring a mutex member as mutable clearly
|
||||
documents the intended semantics.</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Why supply <classname>boost::condition</classname> variables rather than
|
||||
event variables?</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>Condition variables result in user code much less prone to <link
|
||||
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>
|
||||
</qandaentry>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Why isn't thread cancellation or termination provided?</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>There's a valid need for thread termination, so at some point
|
||||
&Boost.Thread; probably will include it, but only after we can find a
|
||||
truly safe (and portable) mechanism for this concept.</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Is it safe for threads to share automatic storage duration (stack)
|
||||
objects via pointers or references?</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>Only if you can guarantee that the lifetime of the stack object
|
||||
will not end while other threads might still access the object. Thus the
|
||||
safest practice is to avoid sharing stack objects, particularly in
|
||||
designs where threads are created and destroyed dynamically. Restrict
|
||||
sharing of stack objects to simple designs with very clear and
|
||||
unchanging function and thread lifetimes. (Suggested by Darryl
|
||||
Green).</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Why has class semaphore disappeared?</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>Semaphore was removed as too error prone. The same effect can be
|
||||
achieved with greater safety by the combination of a mutex and a
|
||||
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>
|
||||
304
doc/glossary.xml
Normal file
304
doc/glossary.xml
Normal file
@@ -0,0 +1,304 @@
|
||||
<?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 % 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)
|
||||
-->
|
||||
<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
|
||||
represents the section number, with the paragraph number following the
|
||||
"/".</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.Thread; places on a C++
|
||||
implementation as defined by the C++ Standard.</para>
|
||||
<glossentry id="thread.glossary.thread">
|
||||
<glossterm>Thread</glossterm>
|
||||
<glossdef>
|
||||
<para>Thread is short for "thread of execution". A thread of execution is
|
||||
an execution environment [1.9/7] within the execution environment of a C++
|
||||
program [1.9]. The main() function [3.6.1] of the program is the initial
|
||||
function of the initial thread. A program in a multithreading environment
|
||||
always has an initial thread even if the program explicitly creates no
|
||||
additional threads.</para>
|
||||
<para>Unless otherwise specified, each thread shares all aspects of its
|
||||
execution environment with other threads in the program. Shared aspects of
|
||||
the execution environment include, but are not limited to, the
|
||||
following:</para>
|
||||
<itemizedlist>
|
||||
<listitem><para>Static storage duration (static, extern) objects
|
||||
[3.7.1].</para></listitem>
|
||||
<listitem><para>Dynamic storage duration (heap) objects [3.7.3]. Thus
|
||||
each memory allocation will return a unique addresses, regardless of the
|
||||
thread making the allocation request.</para></listitem>
|
||||
<listitem><para>Automatic storage duration (stack) objects [3.7.2]
|
||||
accessed via pointer or reference from another thread.</para></listitem>
|
||||
<listitem><para>Resources provided by the operating system. For example,
|
||||
files.</para></listitem>
|
||||
<listitem><para>The program itself. In other words, each thread is
|
||||
executing some function of the same program, not a totally different
|
||||
program.</para></listitem>
|
||||
</itemizedlist>
|
||||
<para>Each thread has its own:</para>
|
||||
<itemizedlist>
|
||||
<listitem><para>Registers and current execution sequence (program
|
||||
counter) [1.9/5].</para></listitem>
|
||||
<listitem><para>Automatic storage duration (stack) objects
|
||||
[3.7.2].</para></listitem>
|
||||
</itemizedlist>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="thread.glossary.thread-safe">
|
||||
<glossterm>Thread-safe</glossterm>
|
||||
<glossdef>
|
||||
<para>A program is thread-safe if it has no <link
|
||||
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
|
||||
compile time, many thread-safety errors can only only be detected at
|
||||
runtime.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<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
|
||||
states:</para>
|
||||
<table>
|
||||
<title>Thread States</title>
|
||||
<tgroup cols="2" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>State</entry>
|
||||
<entry>Description</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Ready</entry>
|
||||
<entry>Ready to run, but waiting for a processor.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Running</entry>
|
||||
<entry>Currently executing on a processor. Zero or more threads
|
||||
may be running at any time, with a maximum equal to the number of
|
||||
processors.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Blocked</entry>
|
||||
<entry>Waiting for some resource other than a processor which is
|
||||
not currently available, or for the completion of calls to library
|
||||
functions [1.9/6]. The term "waiting" is synonymous with
|
||||
"blocked"</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Terminated</entry>
|
||||
<entry>Finished execution but not yet detached or joined.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
<para>Thread state transitions shall occur only as specified:</para>
|
||||
<table>
|
||||
<title>Thread States Transitions</title>
|
||||
<tgroup cols="3" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>From</entry>
|
||||
<entry>To</entry>
|
||||
<entry>Cause</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>[none]</entry>
|
||||
<entry>Ready</entry>
|
||||
<entry><para>Thread is created by a call to a library function.
|
||||
In the case of the initial thread, creation is implicit and
|
||||
occurs during the startup of the main() function [3.6.1].</para></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Ready</entry>
|
||||
<entry>Running</entry>
|
||||
<entry><para>Processor becomes available.</para></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Running</entry>
|
||||
<entry>Ready</entry>
|
||||
<entry>Thread preempted.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Running</entry>
|
||||
<entry>Blocked</entry>
|
||||
<entry>Thread calls a library function which waits for a resource or
|
||||
for the completion of I/O.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Running</entry>
|
||||
<entry>Terminated</entry>
|
||||
<entry>Thread returns from its initial function, calls a thread
|
||||
termination library function, or is canceled by some other thread
|
||||
calling a thread termination library function.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Blocked</entry>
|
||||
<entry>Ready</entry>
|
||||
<entry>The resource being waited for becomes available, or the
|
||||
blocking library function completes.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Terminated</entry>
|
||||
<entry>[none]</entry>
|
||||
<entry>Thread is detached or joined by some other thread calling the
|
||||
appropriate library function, or by program termination
|
||||
[3.6.3].</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
<para>[Note: if a suspend() function is added to the threading library,
|
||||
additional transitions to the blocked state will have to be added to the
|
||||
above table.]</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<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
|
||||
to the same memory without proper synchronization, resulting in an incorrect
|
||||
value being read or written. The result of a race condition may be a bit
|
||||
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.Thread;.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="thread.glossary.deadlock">
|
||||
<glossterm>Deadlock</glossterm>
|
||||
<glossdef>
|
||||
<para>Deadlock is an execution state where for some set of threads, each
|
||||
thread in the set is blocked waiting for some action by one of the other
|
||||
threads in the set. Since each is waiting on the others, none will ever
|
||||
become ready again.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<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="thread.glossary.priority-failure">
|
||||
<glossterm>Priority Failure</glossterm>
|
||||
<glossdef>
|
||||
<para>A priority failure (such as priority inversion or infinite overtaking)
|
||||
occurs when threads are executed in such a sequence that required work is not
|
||||
performed in time to be useful.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="thread.glossary.undefined-behavior">
|
||||
<glossterm>Undefined Behavior</glossterm>
|
||||
<glossdef>
|
||||
<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>
|
||||
|
||||
<para>An operation whose behavior is undefined can work "correctly"
|
||||
in some implementations (i.e., do what the programmer thought it
|
||||
would do), while in other implementations it may exhibit almost
|
||||
any "incorrect" behavior--such as returning an invalid value,
|
||||
throwing an exception, generating an access violation, or terminating
|
||||
the process.</para>
|
||||
|
||||
<para>Executing a statement whose behavior is undefined is a
|
||||
programming error.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="thread.glossary.memory-visibility">
|
||||
<glossterm>Memory Visibility</glossterm>
|
||||
<glossdef>
|
||||
<para>An address [1.7] shall always point to the same memory byte,
|
||||
regardless of the thread or processor dereferencing the address.</para>
|
||||
<para>An object [1.8, 1.9] is accessible from multiple threads if it is of
|
||||
static storage duration (static, extern) [3.7.1], or if a pointer or
|
||||
reference to it is explicitly or implicitly dereferenced in multiple
|
||||
threads.</para>
|
||||
<para>For an object accessible from multiple threads, the value of the
|
||||
object accessed from one thread may be indeterminate or different from the
|
||||
value accessed from another thread, except under the conditions specified in
|
||||
the following table. For the same row of the table, the value of an object
|
||||
accessible at the indicated sequence point in thread A will be determinate
|
||||
and the same if accessed at or after the indicated sequence point in thread
|
||||
B, provided the object is not otherwise modified. In the table, the
|
||||
"sequence point at a call" is the sequence point after the evaluation of all
|
||||
function arguments [1.9/17], while the "sequence point after a call" is the
|
||||
sequence point after the copying of the returned value... [1.9/17].</para>
|
||||
<table>
|
||||
<title>Memory Visibility</title>
|
||||
<tgroup cols="2">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Thread A</entry>
|
||||
<entry>Thread B</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>The sequence point at a call to a library thread-creation
|
||||
function.</entry>
|
||||
<entry>The first sequence point of the initial function in the new
|
||||
thread created by the Thread A call.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>The sequence point at a call to a library function which
|
||||
locks a mutex, directly or by waiting for a condition
|
||||
variable.</entry>
|
||||
<entry>The sequence point after a call to a library function which
|
||||
unlocks the same mutex.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>The last sequence point before thread termination.</entry>
|
||||
<entry>The sequence point after a call to a library function which
|
||||
joins the terminated thread.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>The sequence point at a call to a library function which
|
||||
signals or broadcasts a condition variable.</entry>
|
||||
<entry>The sequence point after the call to the library function
|
||||
which was waiting on that same condition variable or signal.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
<para>The architecture of the execution environment and the observable
|
||||
behavior of the abstract machine [1.9] shall be the same on all
|
||||
processors.</para>
|
||||
<para>The latitude granted by the C++ standard for an implementation to
|
||||
alter the definition of observable behavior of the abstract machine to
|
||||
include additional library I/O functions [1.9/6] is extended to include
|
||||
threading library functions.</para>
|
||||
<para>When an exception is thrown and there is no matching exception handler
|
||||
in the same thread, behavior is undefined. The preferred behavior is the
|
||||
same as when there is no matching exception handler in a program
|
||||
[15.3/9]. That is, terminate() is called, and it is implementation-defined
|
||||
whether or not the stack is unwound.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<section>
|
||||
<title>Acknowledgements</title>
|
||||
<para>This document was originally written by Beman Dawes, and then much
|
||||
improved by the incorporation of comments from William Kempf, who now
|
||||
maintains the contents.</para>
|
||||
<para>The visibility rules are based on &cite.Butenhof97;.</para>
|
||||
</section>
|
||||
</glossary>
|
||||
38
doc/implementation_notes.xml
Normal file
38
doc/implementation_notes.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<?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 % 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.implementation_notes" last-revision="$Date$">
|
||||
<title>Implementation Notes</title>
|
||||
<section id="thread.implementation_notes.win32">
|
||||
<title>Win32</title>
|
||||
<para>
|
||||
In the current Win32 implementation, creating a boost::thread object
|
||||
during dll initialization will result in deadlock because the thread
|
||||
class constructor causes the current thread to wait on the thread that
|
||||
is being created until it signals that it has finished its initialization,
|
||||
and, as stated in the
|
||||
<ulink url="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/dllmain.asp">MSDN Library, "DllMain" article, "Remarks" section</ulink>,
|
||||
"Because DLL notifications are serialized, entry-point functions should not
|
||||
attempt to communicate with other threads or processes. Deadlocks may occur as a result."
|
||||
(Also see <ulink url="http://www.microsoft.com/msj/archive/S220.aspx">"Under the Hood", January 1996</ulink>
|
||||
for a more detailed discussion of this issue).
|
||||
</para>
|
||||
<para>
|
||||
The following non-exhaustive list details some of the situations that
|
||||
should be avoided until this issue can be addressed:
|
||||
<itemizedlist>
|
||||
<listitem>Creating a boost::thread object in DllMain() or in any function called by it.</listitem>
|
||||
<listitem>Creating a boost::thread object in the constructor of a global static object or in any function called by one.</listitem>
|
||||
<listitem>Creating a boost::thread object in MFC's CWinApp::InitInstance() function or in any function called by it.</listitem>
|
||||
<listitem>Creating a boost::thread object in the function pointed to by MFC's _pRawDllMain function pointer or in any function called by it.</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
@@ -1,87 +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="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, BTL, thread library, C++">
|
||||
<title>Boost.Threads, Index</title>
|
||||
<meta http-equiv="refresh" content="0; URL=../../../doc/html/thread.html">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">Documentation Map</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>Contents</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="overview.html">Overview</a></li>
|
||||
<li>Class <a href="semaphore.html">semaphore</a></li>
|
||||
<li><a href="mutex_concept.html">Mutex Concepts</a></li>
|
||||
<ul>
|
||||
<li><a href="mutex_concept.html#Mutex">Mutex</a></li>
|
||||
<li><a href="mutex_concept.html#TryMutex">TryMutex</a></li>
|
||||
<li><a href="mutex_concept.html#TimedMutex">TimedMutex</a></li>
|
||||
</ul>
|
||||
<li>Mutex Classes</li>
|
||||
<ul>
|
||||
<li><a href="mutex.html">mutex / try_mutex / timed_mutex</a></li>
|
||||
<li><a href="recursive_mutex.html">recursive_mutex / recursive_try_mutex / recursive_timed_mutex</a></li>
|
||||
</ul>
|
||||
<li><a href="lock_concept.html">Lock Concepts</a></li>
|
||||
<ul>
|
||||
<li><a href="lock_concept.html#Lock">Lock</a></li>
|
||||
<li><a href="lock_concept.html#ScopedLock">ScopedLock</a></li>
|
||||
<li><a href="lock_concept.html#ScopedTryLock">ScopedTryLock</a></li>
|
||||
<li><a href="lock_concept.html#ScopedTimedLock">ScopedTimedLock</a></li>
|
||||
</ul>
|
||||
<li>Lock Classes</li>
|
||||
<ul>
|
||||
<li><a href="scoped_lock.html">scoped_lock</a></li>
|
||||
<li><a href="scoped_try_lock.html">scoped_try_lock</a></li>
|
||||
<li><a href="scoped_timed_lock.html">scoped_timed_lock</a></li>
|
||||
</ul>
|
||||
<li>Class <a href="condition.html">condition</a></li>
|
||||
<li>Class <a href="thread_specific_ptr.html">thread_specific_ptr</a></li>
|
||||
<li>Class <a href="thread.html">thread</a></li>
|
||||
<li>Class <a href="thread_group.html">thread_group</a></li>
|
||||
<li>Class <a href="xtime.html">xtime</a></li>
|
||||
<li>Class <a href="lock_error.html">lock_error</a></li>
|
||||
<li>Class <a href="thread_resource_error.html">thread_resource_error</a></li>
|
||||
<li>Routine <a href="call_once.html">call_once</a></li>
|
||||
<li><a href="config.html">Configuration Information</a></li>
|
||||
<li><a href="introduction.html">Introduction to design</a></li>
|
||||
<li><a href="rationale.html">Rationale for design decisions</a></li>
|
||||
<li><a href="definitions.html">Definitions</a></li>
|
||||
<li><a href="faq.html">Frequently Asked Questions</a></li>
|
||||
<li><a href="bibliography.html">Bibliography</a></li>
|
||||
<li><a href="acknowledgements.html">Acknowledgements</a></li>
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->12 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39332" -->
|
||||
</p>
|
||||
|
||||
<p>©<i> Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001</i></p>
|
||||
<p>Permission to use, copy, modify, distribute and sell this software
|
||||
and its documentation for any purpose is hereby granted without fee,
|
||||
provided that the above copyright notice appear in all copies and
|
||||
that both that copyright notice and this permission notice appear
|
||||
in supporting documentation. William E. Kempf makes no representations
|
||||
about the suitability of this software for any purpose.
|
||||
It is provided "as is" without express or implied warranty.</p>
|
||||
|
||||
<body>
|
||||
Automatic redirection failed, please go to <a href="../../../doc/html/thread.html">../../../doc/html/thread.html</a>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, BTL, thread library, C++">
|
||||
<title>Boost.Threads, Introduction</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><IMG height=86 alt="C++ Boost" src="../../../c++boost.gif" width=277></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">Introduction</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Motivation</h3>
|
||||
|
||||
<p>With client/server and three-tier architectures becoming common place in today's
|
||||
world, it's becoming increasingly important for programs to be able to handle parallel
|
||||
processing. Modern day operating systems usually provide some support for this
|
||||
through native thread APIs. Unfortunately, writing portable code that makes use
|
||||
of parallel processing in C++ is made very difficult by a lack of a standard interface
|
||||
for these native APIs. Further, these APIs are almost universally C APIs and fail to
|
||||
take advantage of C++'s strengths, or to address C++'s issues.</p>
|
||||
|
||||
<p>The <b>Boost.Threads</b> library is an attempt to define a portable interface for writing
|
||||
parallel processes in C++.</p>
|
||||
|
||||
<h3>Goals</h3>
|
||||
|
||||
<p>The <b>Boost.Threads</b> 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.<p>
|
||||
|
||||
<ul>
|
||||
<li><b>Portability</b>
|
||||
<p><b>Boost.Threads</b> 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.</p>
|
||||
<li><b>Safety</b>
|
||||
<p><b>Boost.Threads</b> was designed to be as safe as possible. Writing
|
||||
<a href="definitions.html#Thread-safe">thread-safe</a>
|
||||
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:</p>
|
||||
<ul>
|
||||
<li><p align="left">C++ language features are used make correct usage easy (if possible,
|
||||
the default) and error-prone impossible or at least more difficult.
|
||||
For example, see the <a href="mutex_concept.html">Mutex</a> and <a href="lock_concept.html">Lock</a>
|
||||
designs, and how note how they interact.</p></li>
|
||||
<li>
|
||||
<p align="left">Certain traditional concurrent programming features
|
||||
are considered so error-prone that they are not provided at all. For
|
||||
example, see the <a href="rationale.html#Events">Events Not Provided</a>
|
||||
rationale.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p align="left">Dangerous features, or features which may be misused,
|
||||
are identified as such in the documentation to make users aware of
|
||||
potential pitfalls. For example, see <a href="semaphore.html#Danger">Semaphore</a>.</p>
|
||||
</li>
|
||||
</ul>
|
||||
<li><b>Flexibility</b>
|
||||
<p><b>Boost.Threads</b> was designed to be flexible. This goal is often at odds
|
||||
with <i>safety</i>. When functionality might be compromised by the desire
|
||||
to keep the interface safe, <b>Boost.Threads</b> has been designed to provide
|
||||
the functionality, but to make it's use prohibitive for general use.</p>
|
||||
<li><b>Efficiency</b>
|
||||
<p><b>Boost.Threads</b> 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. <b>Boost.Threads</b> 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 <i>safety</i>. Every effort was made to
|
||||
ensure efficient implementations, but when in conflict <i>safety</i> has always taken
|
||||
precedence.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Iterative Phases</h3>
|
||||
|
||||
<p>Another goal of <b>Boost.Threads</b> 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 they are very difficult to use safely or to provide
|
||||
formal proofs for constructs built on top of them. Until recently, these primitives
|
||||
were "state of the art" and the only concepts available to programmers. Recently
|
||||
there has been a lot of research in other concepts, such as in "Communicating Sequential
|
||||
Processes." <b>Boost.Threads</b> was designed in iterative steps, providing the building
|
||||
blocks necessary for the next step, and giving the researcher the tools necessary to
|
||||
explore new concepts in a portable manner.</p>
|
||||
|
||||
<p>Given the goal of following a dynamic, iterative approach <b>Boost.Threads</b> shall go through
|
||||
several growth cycles. Each phase in its development shall be roughly documented here.</p>
|
||||
|
||||
<h4>Phase 1, Synchronization Primitives</h4>
|
||||
|
||||
<p>Boost is all about providing high quality libraries with implementations for many platforms.
|
||||
Unfortunately, there's a big problem faced by developers wishing to supply such high quality
|
||||
libraries, namely thread-safety. The C++ standard doesn't address threads at all, but real
|
||||
world programs often make use of native threading support. A portable library that doesn't
|
||||
address the issue of thread-safety is there for not much help to a programmer who wants to
|
||||
use the library in his multi-threaded application. So there's a very great need for portable
|
||||
primitives that will allow the library developer to create <a href="file:///c:/boost/site/libs/thread/doc/definitions.html#Thread-safe">thread-safe</a>
|
||||
implementations. This
|
||||
need far out weighs the need for portable methods to create and manage threads.</p>
|
||||
|
||||
<p>Because of this need, the first phase of <b>Boost.Threads</b> focuses solely on providing
|
||||
portable primitive concepts for thread synchronization. Types provided in this phase include
|
||||
the <A href="semaphore.html">semaphore</a>, <A href="mutex.html">mutex/try_mutex/timed_mutex</a>,
|
||||
<A href="recursive_mutex.html">recursive_mutex/recursive_try_mutex/recursive_timed_mutex</a>,
|
||||
<A href="scoped_lock.html">scoped_lock</a>, <A href="scoped_try_lock.html">scoped_try_lock</a>,
|
||||
<A href="scoped_timed_lock.html">scoped_timed_lock</a> and <A href="lock_error.html">lock_error</a>.
|
||||
These are considered the "core" synchronization primitives, though there are others that will
|
||||
be added in later phases.</p>
|
||||
|
||||
<h4>Phase 2, Thread Management and Thread Specific Storage</h4>
|
||||
|
||||
<p>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 multi-threaded program. Later
|
||||
phases are likely to add additional functionality in this area. This phase of <b>Boost.Threads</b>
|
||||
adds the <A href="thread.html">thread</a> and
|
||||
<A href="thread_specific_ptr.html">thread_specific_ptr</a> types. With these additions
|
||||
the <b>Boost.Threads</b> library can be considered minimal but complete.</p>
|
||||
|
||||
<h4>The Next Phase</h4>
|
||||
|
||||
<p>The next phase will address more advanced synchronization concepts, such as read/write mutexes
|
||||
and barriers.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->03 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39333" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <A href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,242 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, BTL, thread library, C++">
|
||||
<title>Boost.Threads, Lock Concept</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">Lock Concepts</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Requirements">Concept Requirements</a><br>
|
||||
<a href="#Lock">Lock Concept</a><br>
|
||||
<a href="#ScopedLock">ScopedLock Concept</a><br>
|
||||
<a href="#ScopedTryLock">ScopedTryLock Concept</a><br>
|
||||
<a href="#ScopedTimedLock">ScopedTimedLock Concept</a><br>
|
||||
<a href="#Models">Models</a></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>The lock concepts provide exception safe means for locking and unlocking a
|
||||
<a href="mutex_concept.html">mutex model</a>. In other words they are an
|
||||
implementation of the <i>Scoped Locking</i>
|
||||
<a href="bibliography.html#Schmidt 00">[Schmidt 00]</a> pattern. The
|
||||
<a href="#ScopedLock">ScopedLock</a> concept, with
|
||||
<a href="#ScopedTryLock">ScopedTryLock</a> and
|
||||
<a href="#ScopedTimedLock">ScopedTimedLock</a> refinements, formalize the
|
||||
requirements.</p>
|
||||
|
||||
<p>Lock models are constructed with a reference to a
|
||||
<a href="mutex_concept.html">mutex model</a> and typically acquire ownership of the
|
||||
<a href="mutex_concept.html">mutex model</a> by setting its state to locked. They also
|
||||
ensure ownership is relinquished in the destructor. Lock models also expose functions
|
||||
to query the lock status and to manually lock and unlock the
|
||||
<a href="mutex_concept.html">mutex model</a>.</p>
|
||||
|
||||
<p>Instances of lock models are meant to be short lived, expected to be used at block
|
||||
scope only. The lock models are not
|
||||
<a href="definitions.html#Thread-safe">thread-safe</a>. Lock models must maintain state
|
||||
to indicate whether or not they've been locked and this state is not protected by any
|
||||
synchronization concepts. For this reason an instance of a lock model should never be
|
||||
shared between multiple threads.</p>
|
||||
|
||||
<h2>Concept <a name="Requirements">Requirements</a></h2>
|
||||
|
||||
<p>[For documentation purposes, portions of the concept requirements are
|
||||
repeated in the documentation for specific lock classes. Those copies need
|
||||
to be kept in sync with the requirements here.]</p>
|
||||
|
||||
<h3><a name="Lock">Lock</a> Concept</h3>
|
||||
|
||||
<p>For a <a href="#ScopedLock"> ScopedLock</a>,
|
||||
<a href="#ScopedTryLock">ScopedTryLock</a>, or
|
||||
<a href="#ScopedTimedLock">ScopedTimedLock</a> type <code>L</code> and an object
|
||||
<code>lk</code> and const object <code>clk</code> of that type, the following expressions
|
||||
must be well-formed and have the indicated effects.</p>
|
||||
|
||||
<p>The Lock concept is used as a base for the <a href="#ScopedLock">ScopedLock</a>,
|
||||
<a href="#ScopedTryLock">ScopedTryLock</a>, and
|
||||
<a href="#ScopedTimedLock">ScopedTimedLock</a> refinements. The associated mutex type
|
||||
is as specified for each of those refinements respectively.</p>
|
||||
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<td><b>Expression</b></td>
|
||||
<td><b>Effects</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>(&lk)->~L();</code></td>
|
||||
<td><code>if (locked()) unlock();</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>(&clk)->operator const void*()</code></td>
|
||||
<td>Returns type void*, non-zero if if the associated mutex has been locked
|
||||
by <code>clk</code>, otherwise 0.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>clk.locked()</code></td>
|
||||
<td>Returns a <code>bool</code>, <code>(&clk)->operator const void*() != 0</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>lk.lock()</code></td>
|
||||
<td>Throws lock_error if locked(). If the associated mutex is already locked by some other
|
||||
thread, places the current thread in the
|
||||
<a href="definitions.html#State">Blocked</a> state until the associated mutex is
|
||||
unlocked, after which the current thread is placed in the
|
||||
<a href="definitions.html#State">Ready</a> state, eventually to be returned to the
|
||||
<a href="definitions.html#State">Running</a> state.<br>
|
||||
Postcondition: locked()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>lk.unlock()</code></td>
|
||||
<td>If !locked(), throws lock_error, otherwise unlocks the associated mutex.<br>
|
||||
Postcondition: !locked()</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3><a name="ScopedLock">ScopedLock</a> Concept</h3>
|
||||
|
||||
<p>A ScopedLock must meet the <a href="#Lock">Lock</a> requirements. For a ScopedLock
|
||||
type <code>L</code> and an object <code>lk</code> of that type,
|
||||
and an object <code>m</code> of a type meeting the
|
||||
<a href="mutex_concept.html#Mutex">Mutex</a> requirements, and an object <code>b</code>
|
||||
of type <code>bool</code>, the following expressions must be well-formed and have the
|
||||
indicated effects.</p>
|
||||
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<td><b>Expression</b></td>
|
||||
<td><b>Effects</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>L lk(m);</code></td>
|
||||
<td>Constructs an object <code>lk</code>, and associates mutex <code>m</code> with
|
||||
it, then calls <code>lock()</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>L lk(m,b);</code></td>
|
||||
<td>Constructs an object <code>lk</code>, and associates mutex <code>m</code> with
|
||||
it, then if <code>b</code>, calls <code>lock()</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3><a name="ScopedTryLock">ScopedTryLock</a> Concept</h3>
|
||||
|
||||
<p>A ScopedTryLock must meet the <a href="#Lock">Lock</a> requirements. For a
|
||||
ScopedTryLock type <code>L</code> and an object <code>lk</code> of that type,
|
||||
and an object <code>m</code> of a type meeting the
|
||||
<a href="mutex_concept.html#TryMutex">TryMutex</a> requirements, and an object
|
||||
<code>b</code> of type <code>bool</code>, the following expressions must be well-formed
|
||||
and have the indicated effects.</p>
|
||||
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<td><b>Expression</b></td>
|
||||
<td><b>Effects</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>L lk(m);</code></td>
|
||||
<td>Constructs an object <code>lk</code>, and associates mutex <code>m</code> with
|
||||
it, then calls <code>try_lock()</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>L lk(m,b);</code></td>
|
||||
<td>Constructs an object <code>lk</code>, and associates mutex <code>m</code> with
|
||||
it, then if <code>b</code>, calls <code>lock()</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>lk.try_lock()</code></td>
|
||||
<td>If locked(), throws <code>lock_error</code>. Makes a non-blocking attempt to
|
||||
lock the associated mutex, returning <code>true</code> if the lock attempt is
|
||||
successful, otherwise <code>false</code>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3><a name="ScopedTimedLock">ScopedTimedLock</a> Concept</h3>
|
||||
|
||||
<p>A ScopedTimedLock must meet the <a href="#Lock">Lock</a> requirements. For a
|
||||
ScopedTimedLock type <code>L</code> and an object <code>lk</code> of that type,
|
||||
and an object <code>m</code> of a type meeting the
|
||||
<a href="mutex_concept.html#TimedMutex">TimedMutex</a> requirements, and an object
|
||||
<code>b</code> of type <code>bool</code>, and an object <code>t</code> of type
|
||||
<code><a href="xtime.html">xtime</a></code>, the following expressions must be well-formed and have the indicated
|
||||
effects.</p>
|
||||
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<td><b>Expression</b></td>
|
||||
<td><b>Effects</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>L lk(m,t);</code></td>
|
||||
<td>Constructs an object <code>lk</code>, and associates mutex <code>m</code> with
|
||||
it, then calls <code>timed_lock(t)</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>L lk(m,b);</code></td>
|
||||
<td>Constructs an object <code>lk</code>, and associates mutex <code>m</code> with
|
||||
it, then if <code>b</code>, calls <code>lock()</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>lk.timed_lock(t)</code></td>
|
||||
<td>If locked(), throws lock_error. Makes a blocking attempt to lock the
|
||||
associated mutex, and returns <code>true</code> if successful within the specified
|
||||
time <code>t</code>, otherwise <code>false</code>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2><a name="Models">Models</a></h2>
|
||||
|
||||
<p><b>Boost.Threads</b> currently supplies three classes which model lock concepts.</p>
|
||||
|
||||
<p>These classes are normally accessed via typedefs of the same name supplied by
|
||||
a <a href="mutex_concept.html">mutex model</a>.</p>
|
||||
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<td><b>Concept</b></td>
|
||||
<td><b>Refines</b></td>
|
||||
<td><b>Classes Modeling the Concept</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#ScopedLock">ScopedLock</a></td>
|
||||
<td> </td>
|
||||
<td><a href="scoped_lock.html">scoped_lock</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#ScopedTryLock">ScopedTryLock</a></td>
|
||||
<td><a href="#ScopedLock">ScopedLock</a></td>
|
||||
<td><a href="scoped_try_lock.html">scoped_try_lock</a> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#ScopedTimedLock">ScopedTimedLock</a></td>
|
||||
<td><a href="#ScopedLock">ScopedLock</a></td>
|
||||
<td><a href="scoped_timed_lock.html">scoped_timed_lock</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->04 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39335" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,111 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, BTL, thread library, C++">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<title>Boost.Threads, lock_error</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">lock_error</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Header">Header</a><br>
|
||||
<a href="#Synopsis">Synopsis</a><br>
|
||||
<a href="#Members">Members</a><br>
|
||||
<a href="#Example">Example</a></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>The <tt>lock_error</tt> class defines an exception type thrown to indicate a
|
||||
locking related error has been detected. Examples of such errors include a lock
|
||||
operation which can be determined to result in a deadlock, or unlock operations
|
||||
attempted by a thread that does not own the lock.</p>
|
||||
|
||||
<h2><a name="Header">Header</a></h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
||||
</pre>
|
||||
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
|
||||
<pre>
|
||||
namespace boost
|
||||
|
||||
class lock_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
lock_error();
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Constructor</h3>
|
||||
|
||||
<pre>
|
||||
lock_error();
|
||||
</pre>
|
||||
|
||||
<p>Constructs a <tt>lock_error</tt> object.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="Example">Example</a> Usage</h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/mutex.hpp"><boost/thread/mutex.hpp></a>
|
||||
#include <a href="../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
||||
#include <iostream>
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
boost::mutex mutex;
|
||||
boost::mutex::scoped_lock scoped_lock(mutex);
|
||||
try
|
||||
{
|
||||
boost::mutex::scoped_lock deadlock(mutex);
|
||||
std::cout << "lock succeeded" << std::endl;
|
||||
}
|
||||
catch (boost::lock_error& err)
|
||||
{
|
||||
std::cout << err.what() << " - deadlock occurred." << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The output is:</p>
|
||||
|
||||
<pre>
|
||||
thread lock error - deadlock occurred.
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->10 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39328" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
309
doc/mutex-ref.xml
Normal file
309
doc/mutex-ref.xml
Normal file
@@ -0,0 +1,309 @@
|
||||
<?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 % 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="thread.concepts.Mutex">Mutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.Mutex">Mutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<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="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="thread.concepts.lock-models">models</link>
|
||||
the specified locking strategy:
|
||||
|
||||
<informaltable>
|
||||
<tgroup cols="2" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Lock Name</entry>
|
||||
<entry>Lock Concept</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
|
||||
<para>The <classname>mutex</classname> class uses an
|
||||
<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>.
|
||||
This strategy allows implementations to be as efficient as possible
|
||||
on any given platform. It is, however, recommended that
|
||||
implementations include debugging support to detect misuse when
|
||||
<code>NDEBUG</code> is not defined.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="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>
|
||||
|
||||
<inherit access="private">
|
||||
<type><classname>boost::noncopyable</classname></type>
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<typedef name="scoped_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<constructor>
|
||||
<effects>Constructs a <classname>mutex</classname> object.
|
||||
</effects>
|
||||
|
||||
<postconditions><code>*this</code> is in an unlocked state.
|
||||
</postconditions>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<effects>Destroys a <classname>mutex</classname> object.</effects>
|
||||
|
||||
<requires><code>*this</code> is in an unlocked state.</requires>
|
||||
|
||||
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
|
||||
locked mutex is a serious programming error resulting in undefined
|
||||
behavior such as a program crash.</notes>
|
||||
</destructor>
|
||||
</class>
|
||||
|
||||
<class name="try_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>try_mutex</classname> class is a model of the
|
||||
<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="thread.concepts.TryMutex">TryMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<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="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="thread.concepts.lock-models">model</link>
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
<tgroup cols="2" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Lock Name</entry>
|
||||
<entry>Lock Concept</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
|
||||
<para>The <classname>try_mutex</classname> class uses an
|
||||
<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>.
|
||||
This strategy allows implementations to be as efficient as possible
|
||||
on any given platform. It is, however, recommended that
|
||||
implementations include debugging support to detect misuse when
|
||||
<code>NDEBUG</code> is not defined.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="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>
|
||||
|
||||
<inherit access="private">
|
||||
<type><classname>boost::noncopyable</classname></type>
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<typedef name="scoped_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<constructor>
|
||||
<effects>Constructs a <classname>try_mutex</classname> object.
|
||||
</effects>
|
||||
|
||||
<postconditions><code>*this</code> is in an unlocked state.
|
||||
</postconditions>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<effects>Destroys a <classname>try_mutex</classname> object.
|
||||
</effects>
|
||||
|
||||
<requires><code>*this</code> is in an unlocked state.</requires>
|
||||
|
||||
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
|
||||
locked mutex is a serious programming error resulting in undefined
|
||||
behavior such as a program crash.</notes>
|
||||
</destructor>
|
||||
</class>
|
||||
|
||||
<class name="timed_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>timed_mutex</classname> class is a model of the
|
||||
<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="thread.concepts.TimedMutex">TimedMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<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="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="thread.concepts.lock-models">model</link>
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
<tgroup cols="2" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Lock Name</entry>
|
||||
<entry>Lock Concept</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
|
||||
<para>The <classname>timed_mutex</classname> class uses an
|
||||
<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>.
|
||||
This strategy allows implementations to be as efficient as possible
|
||||
on any given platform. It is, however, recommended that
|
||||
implementations include debugging support to detect misuse when
|
||||
<code>NDEBUG</code> is not defined.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="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>
|
||||
|
||||
<inherit access="private">
|
||||
<type><classname>boost::noncopyable</classname></type>
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<typedef name="scoped_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_timed_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<constructor>
|
||||
<effects>Constructs a <classname>timed_mutex</classname> object.
|
||||
</effects>
|
||||
|
||||
<postconditions><code>*this</code> is in an unlocked state.
|
||||
</postconditions>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<effects>Destroys a <classname>timed_mutex</classname> object.</effects>
|
||||
|
||||
<requires><code>*this</code> is in an unlocked state.</requires>
|
||||
|
||||
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
|
||||
locked mutex is a serious programming error resulting in undefined
|
||||
behavior such as a program crash.</notes>
|
||||
</destructor>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
319
doc/mutex.html
319
doc/mutex.html
@@ -1,319 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, BTL, thread library, C++">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<title>Boost.Threads, mutex</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><IMG alt="C++ Boost" src="../../../c++boost.gif" width="277" height="86"></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">mutex<br>
|
||||
try_mutex<br>
|
||||
timed_mutex</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Header">Header</a><br>
|
||||
<a href="#mutex Synopsis">Class mutex Synopsis</a><br>
|
||||
<a href="#mutex Members">Class mutex Members</a><br>
|
||||
<a href="#try_mutex Synopsis">Class try_mutex Synopsis</a><br>
|
||||
<a href="#try_mutex Members">Class try_mutex Members</a><br>
|
||||
<a href="#timed_mutex Synopsis">Class timed_mutex Synopsis</a><br>
|
||||
<a href="#timed_mutex Members">Class timed_mutex Members</a><br>
|
||||
<a href="#Example">Example</a></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>The <tt><a href="#mutex Synopsis">mutex</a></tt>, <tt><a href="#try_mutex Synopsis">try_mutex</a></tt> and <tt><a href="#timed_mutex Synopsis">timed_mutex</a></tt> classes define full featured
|
||||
models of the <a href="mutex_concept.html#Mutex">Mutex</a>, <a href="mutex_concept.html#TryMutex">TryMutex</a>,
|
||||
and <a href="mutex_concept.html#TimedMutex">TimedMutex</a> concepts. These types should be used to
|
||||
non-recursively synchronize access to
|
||||
shared resources. For recursive locking mechanics, see <a href="recursive_mutex.html">recursive
|
||||
mutexes</a>.</p>
|
||||
|
||||
<p>Each class supplies one or more typedefs for lock types which model matching
|
||||
lock concepts. For the best possible performance you should use the mutex class that supports
|
||||
the minimum set of lock
|
||||
types that you need.</p>
|
||||
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<td><b>Mutex Class</b></td>
|
||||
<td><b>Lock name</b></td>
|
||||
<td><b>Implementation defined Lock Type</b></td>
|
||||
<td><b> Lock Concept</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><a href="#mutex Synopsis"><code>mutex</code></a></td>
|
||||
<td valign="middle"><code>scoped_lock</code></td>
|
||||
<td valign="middle"><code><a href="scoped_lock.html">boost::</a></code><a href="scoped_lock.html"><code>detail::thread::scoped_lock<mutex></code></a></td>
|
||||
<td valign="middle"><a href="lock_concept.html#ScopedLock">ScopedLock</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><tt><a href="#try_mutex Synopsis">try_mutex</a></tt> </td>
|
||||
<td valign="middle"><code>scoped_lock<br>
|
||||
scoped_try_lock</code></td>
|
||||
<td valign="middle"><code><a href="scoped_lock.html">boost::</a></code><a href="scoped_lock.html"><code>detail::thread::scoped_lock<try_mutex><br>
|
||||
</code></a><code><a href="scoped_try_lock.html">boost::detail::thread::scoped_try_lock<try_mutex></a></code></td>
|
||||
<td valign="middle"><a href="lock_concept.html#ScopedLock">ScopedLock</a><br>
|
||||
<a href="lock_concept.html#ScopedTryLock">ScopedTryLock</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code><a href="#timed_mutex Synopsis">timed_mutex</a></code> </td>
|
||||
<td valign="middle"><code>scoped_lock<br>
|
||||
scoped_try_lock<br>
|
||||
scoped_timed_lock</code></td>
|
||||
<td valign="middle"><code><a href="scoped_lock.html">boost::</a></code><a href="scoped_lock.html"><code>detail::thread::scoped_lock<timed_mutex></code></a><br>
|
||||
<code><a href="scoped_try_lock.html">boost::</a></code><a href="scoped_try_lock.html"><code>detail::thread::scoped_try_lock<timed_mutex></code></a><br>
|
||||
<code><a href="scoped_timed_lock.html">boost::</a></code><a href="scoped_timed_lock.html"><code>detail::thread::scoped_timed_lock<timed_mutex></code></a></td>
|
||||
<td valign="middle"><a href="lock_concept.html#ScopedLock">ScopedLock</a><br>
|
||||
<a href="lock_concept.html#ScopedTryLock">ScopedTryLock</a><br>
|
||||
<a href="lock_concept.html#ScopedTimedLock">ScopedTimedLock</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>The <tt>mutex</tt>, <tt>try_mutex</tt> and <tt>timed_mutex</tt> classes use an <tt>Unspecified</tt>
|
||||
<A href="mutex_concept.html#LockingStrategies">locking strategy</a>, so attempts to recursively lock
|
||||
them or attempts to unlock them by threads that don't own a lock on them result in <b>undefined behavior</b>.
|
||||
This strategy allows implementations to be as efficient as possible on any given platform. It is, however,
|
||||
recommended that implementations include debugging support to detect misuse when <tt>NDEBUG</tt> is
|
||||
not defined.</p>
|
||||
|
||||
<p>Like all the <b>Boost.Threads</b> <A href="mutex_concept.html">mutex models</a>, the <tt>mutex</tt>,
|
||||
<tt>try_mutex</tt> and <tt>timed_mutex</tt> leave the
|
||||
<A href="mutex_concept.html#SchedulingPolicies">scheduling policy</a> as <tt>Unspecified</tt>.
|
||||
Programmers should assume that threads waiting for a lock on objects of these types
|
||||
acquire
|
||||
the lock in a random order, even though the specific behavior for a given platform may be different.</p>
|
||||
|
||||
<h2><a name="Header">Header</a></h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/mutex.hpp"><boost/thread/mutex.hpp></a>
|
||||
</pre>
|
||||
|
||||
<h2>Class <a name="mutex Synopsis"> mutex Synopsis</a></h2>
|
||||
|
||||
<pre>
|
||||
namespace boost
|
||||
{
|
||||
class mutex : private <a href="../../utility/utility.htm">boost::noncopyable</a> // Exposition only.
|
||||
// Class mutex meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
|
||||
{
|
||||
public:
|
||||
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_lock;
|
||||
|
||||
mutex();
|
||||
~mutex();
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2>
|
||||
Class <a name="mutex Members">mutex Members</a>
|
||||
</h2>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Constructor</h3>
|
||||
|
||||
<pre>
|
||||
mutex();
|
||||
</pre>
|
||||
|
||||
<p><b>Postconditions: </b><code>*this</code> is in the unlocked state.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Destructor</h3>
|
||||
|
||||
<pre>
|
||||
~mutex();
|
||||
</pre>
|
||||
|
||||
<p><b>Requires:</b> <code>*this</code> is in the unlocked state.</p>
|
||||
|
||||
<p><b>Effects:</b> Destroys <code>*this</code>.</p>
|
||||
|
||||
<p><b>Dangers:</b> Destruction of a locked mutex is a serious programming error
|
||||
resulting in undefined behavior such as a program crash.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>
|
||||
Class <a name="try_mutex Synopsis">try_mutex Synopsis</a>
|
||||
</h2>
|
||||
|
||||
<pre>
|
||||
namespace boost
|
||||
{
|
||||
class try_mutex : private boost::noncopyable // Exposition only.
|
||||
// Class try_mutex meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
|
||||
{
|
||||
public:
|
||||
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_lock;
|
||||
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_try_lock;
|
||||
|
||||
try_mutex();
|
||||
~try_mutex();
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2>Class <a name="try_mutex Members">try_mutex Members</a></h2>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Constructor</h3>
|
||||
|
||||
<pre>
|
||||
try_mutex();
|
||||
</pre>
|
||||
|
||||
<p><b>Postconditions: </b><code>*this</code> is in the unlocked state.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Destructor</h3>
|
||||
|
||||
<pre>
|
||||
~try_mutex();
|
||||
</pre>
|
||||
|
||||
<p><b>Requires:</b> <code>*this</code> is in the unlocked state.</p>
|
||||
|
||||
<p><b>Effects:</b> Destroys <code>*this</code>.</p>
|
||||
|
||||
<p><b>Dangers:</b> Destruction of a locked mutex is a serious programming error
|
||||
resulting in undefined behavior such as a program crash.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>
|
||||
Class <a name="timed_mutex Synopsis">timed_mutex Synopsis</a>
|
||||
</h2>
|
||||
|
||||
<pre>
|
||||
namespace boost
|
||||
{
|
||||
class timed_mutex : private boost::noncopyable // Exposition only.
|
||||
// Class timed_mutex meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
|
||||
{
|
||||
public:
|
||||
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_lock;
|
||||
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_try_lock;
|
||||
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_timed_lock;
|
||||
|
||||
timed_mutex();
|
||||
~timed_mutex();
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2>Class <a name="timed_mutex Members">timed_mutex Members</a></h2>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Constructor</h3>
|
||||
|
||||
<pre>
|
||||
timed_mutex();
|
||||
</pre>
|
||||
|
||||
<p><b>Postconditions: </b><code>*this</code> is in the unlocked state.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Destructor</h3>
|
||||
|
||||
<pre>
|
||||
~timed_mutex();
|
||||
</pre>
|
||||
|
||||
<p><b>Requires:</b> <code>*this</code> is in the unlocked state.</p>
|
||||
|
||||
<p><b>Effects:</b> Destroys <code>*this</code>.</p>
|
||||
|
||||
<p><b>Dangers:</b> Destruction of a locked mutex is a serious programming error
|
||||
resulting in undefined behavior such as a program crash.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="Example">Example</a> Usage</h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/mutex.hpp"><boost/thread/mutex.hpp></a>
|
||||
#include <a href="../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
||||
#include <iostream>
|
||||
|
||||
boost::mutex io_mutex; // The iostreams are not guaranteed to be <a href="file:///c:/boost/site/libs/thread/doc/definitions.html#Thread-safe">thread-safe</a>!
|
||||
|
||||
class counter
|
||||
{
|
||||
public:
|
||||
counter() : count(0) { }
|
||||
|
||||
int increment() {
|
||||
boost::mutex::scoped_lock scoped_lock(mutex);
|
||||
return ++count;
|
||||
}
|
||||
|
||||
private:
|
||||
boost::mutex mutex;
|
||||
int count;
|
||||
};
|
||||
|
||||
counter c;
|
||||
|
||||
void change_count(void*)
|
||||
{
|
||||
int i = c.increment();
|
||||
boost::mutex::scoped_lock scoped_lock(io_mutex);
|
||||
std::cout << "count == " << i << std::endl;
|
||||
}
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
const int num_threads = 4;
|
||||
boost::thread_group thrds;
|
||||
for (int i=0; i < num_threads; ++i)
|
||||
thrds.create_thread(&change_count, 0);
|
||||
|
||||
thrds.join_all();
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The output is:</p>
|
||||
|
||||
<pre>
|
||||
count == 1
|
||||
count == 2
|
||||
count == 3
|
||||
count == 4
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39334" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <A href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,275 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, BTL, thread library, C++">
|
||||
<title>Boost.Threads, Mutex Concept</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><IMG height=86 alt="C++ Boost" src="../../../c++boost.gif" width=277></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">Mutex Concepts</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><a href="#Introduction">Introduction</a><br>
|
||||
<a href="#LockingStrategies">Locking Strategies</a><br>
|
||||
<a href="#Recursive">Recursive</a><br>
|
||||
<a href="#CheckedStrategy">Checked</a><br>
|
||||
<a href="#UncheckedStrategy">Unchecked</a><br>
|
||||
<a href="#UnspecifiedStrategy">Unspecified</a><br>
|
||||
<a href="#SchedulingPolicies">Scheduling Policies</a><br>
|
||||
<a href="#FIFO">FIFO</a><br>
|
||||
<a href="#Priority Driven">Priority Driven</a><br>
|
||||
<a href="#UndefinedScheduling">Undefined</a><br>
|
||||
<a href="#UnspecifiedScheduling">Unspecified</a><br>
|
||||
<a href="#Requirements">Concept Requirements</a><br>
|
||||
<a href="#Mutex">Mutex Concept</a><br>
|
||||
<a href="#TryMutex">TryMutex Concept</a><br>
|
||||
<a href="#TimedMutex">TimedMutex Concept</a><br>
|
||||
<a href="#Models">Models</a></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>A mutex (short for mutual-exclusion) concept serializes access to
|
||||
a resource shared between multiple threads. The <a href="#Mutex">Mutex</a>
|
||||
concept, with <a href="#TryMutex">TryMutex</a> and <a href="#TimedMutex">TimedMutex</a>
|
||||
refinements, formalize the requirements. A model that implements Mutex and its
|
||||
refinements has two states: <b> locked</b> and <b>unlocked</b>. Before using a
|
||||
shared resource, a thread locks a Boost.Threads mutex model object,
|
||||
insuring <a href="definitions.html#Thread-safe">thread-safe</a> access to the shared
|
||||
resource. When use of the shared resource is complete, the thread unlocks the mutex
|
||||
model object, allowing another thread to acquire the lock and use the shared resource.</p>
|
||||
|
||||
<p>Traditional C thread APIs, like Pthreads or the Windows thread APIs, expose
|
||||
functions to lock and unlock a mutex model. This is dangerous since it's easy to forget
|
||||
to unlock a locked mutex. When the flow of control is complex, with multiple return
|
||||
points, the likelihood of forgetting to unlock a mutex model would become even greater.
|
||||
When exceptions are thrown, it becomes nearly impossible to ensure that the mutex is
|
||||
unlocked properly when using these traditional API's. The result is
|
||||
<a href="definitions.html#Deadlock">deadlock</a>.</p>
|
||||
|
||||
<p>Many C++ threading libraries use a pattern known as <i>Scoped Locking</i>
|
||||
<a href="bibliography.html#Schmidt 00">[Schmidt 00]</a> to free the programmer from the
|
||||
need to explicitly lock and unlock mutexes. With this pattern, a
|
||||
<A href="lock_concept.html">lock concept</A> is employed where the lock model's
|
||||
constructor locks the associated mutex model and the destructor automatically does the
|
||||
unlocking. The <b>Boost.Threads</b> library takes this pattern to the extreme in that
|
||||
lock concepts are the only way to lock and unlock a mutex model: lock and unlock
|
||||
functions are not exposed by any <b>Boost.Threads </b>mutex models. This helps to
|
||||
ensure safe usage patterns, especially when code throws exceptions.</p>
|
||||
|
||||
<h2><a name="LockingStrategies">Locking Strategies</a></h2>
|
||||
|
||||
<p>Every mutex model follows one of several locking strategies. These strategies
|
||||
define the semantics for the locking operation when the calling thread already
|
||||
owns a lock on the mutex model.</p>
|
||||
|
||||
<h3><a name="Recursive">Recursive</a></h3>
|
||||
|
||||
<p>With a recursive locking strategy when a thread attempts to acquire a lock on
|
||||
the mutex model for which it already owns a lock, the operation is successful.
|
||||
Note the distinction between a thread, which may have multiple locks outstanding
|
||||
on a recursive mutex, and a lock object, which even for a recursive mutex cannot
|
||||
have its lock() function called multiple times without first calling unlock().</p>
|
||||
|
||||
<p>Internally a lock count is maintained and the owning thread must unlock the
|
||||
mutex model the same number of times that it's locked it before the mutex model's
|
||||
state returns to unlocked. Since mutex models in <b>Boost.Threads</b> expose
|
||||
locking functionality only through lock concepts, a thread will always unlock a mutex
|
||||
model the same number of times that it locked it. This helps to eliminate a whole set
|
||||
of errors typically found in traditional C style thread APIs.</p>
|
||||
|
||||
<p>Classes <A href="recursive_mutex.html">recursive_mutex</A>,
|
||||
<A href="recursive_mutex.html">recursive_try_mutex</A> and
|
||||
<A href="recursive_mutex.html">recursive_timed_mutex</A> use this locking strategy.</p>
|
||||
|
||||
<h3><a name="CheckedStrategy">Checked</a></h3>
|
||||
|
||||
<p>With a checked locking strategy when a thread attempts to acquire a lock on
|
||||
the mutex model for which the thread already owns a lock, the operation will fail with
|
||||
some sort of error indication. Further, attempts by a thread to unlock a mutex
|
||||
that was not locked by the thread will also return some sort of error indication.
|
||||
In <b>Boost.Threads</b>, an exception of type <A href="lock_error.html">lock_error</A>
|
||||
would be thrown in these cases.</p>
|
||||
|
||||
<p><b>Boost.Threads</b> does not currently provide any mutex models that use this
|
||||
strategy.</p>
|
||||
|
||||
<h3><a name="UncheckedStrategy">Unchecked</a></h3>
|
||||
|
||||
<p>With an unchecked locking strategy when a thread attempts to acquire a lock
|
||||
on the mutex model for which the thread already owns a lock the operation will
|
||||
<a href="definitions.html#Deadlock">deadlock</a>. In general this locking strategy is
|
||||
less safe than a checked or recursive strategy, but it's also a faster strategy and so
|
||||
is employed by many libraries.</p>
|
||||
|
||||
<p><b>Boost.Threads</b> does not currently provide any mutex models that use this
|
||||
strategy.</p>
|
||||
|
||||
<h3><a name="UnspecifiedStrategy">Unspecified</a></h3>
|
||||
|
||||
<p>With an unspecified locking strategy, when a thread attempts to acquire a lock
|
||||
on a mutex model for which the thread already owns a lock the operation results in
|
||||
<b>undefined behavior</b>. When a mutex model has an unspecified locking strategy the
|
||||
programmer must assume that the mutex model instead uses an unchecked strategy.</p>
|
||||
|
||||
<p>In general a mutex model with an unspecified locking strategy is unsafe, and it
|
||||
requires programmer discipline to use the mutex model properly. However, this strategy
|
||||
allows an implementation to be as fast as possible with no restrictions on its
|
||||
implementation. This is especially true for portable implementations that wrap the
|
||||
native threading support of a platform. For this reason, the classes
|
||||
<A href="mutex.html">mutex</A>, <A href="mutex.html">try_mutex</A> and
|
||||
<A href="mutex.html">timed_mutex</A> use this locking strategy despite the lack of
|
||||
safety.</p>
|
||||
|
||||
<h2><a name="SchedulingPolicies">Scheduling Policies</a></h2>
|
||||
|
||||
<p>Every mutex model follows one of several scheduling policies. These policies
|
||||
define the semantics when the mutex model is unlocked and there is more than one
|
||||
thread waiting to acquire a lock. In other words, the policy defines which waiting
|
||||
thread shall acquire the lock.</p>
|
||||
|
||||
<h3><a name="FIFO">FIFO</a></h3>
|
||||
|
||||
<p>With a FIFO scheduling policy, threads waiting for the lock will acquire it in
|
||||
a first come first serve order (or First In First Out). This can help prevent a
|
||||
high priority thread from starving lower priority threads that are also waiting
|
||||
on the mutex lock.</p>
|
||||
|
||||
<h3><a name="Priority Driven">Priority Driven</a></h3>
|
||||
|
||||
<p>With a Priority Driven scheduling policy, the thread with the highest priority
|
||||
acquires the lock. Note that this means that low-priority threads may never acquire
|
||||
the lock if the mutex model has high contention and there is always at least one
|
||||
high-priority thread waiting. This is known as thread starvation. When multiple threads
|
||||
of the same priority are waiting on the mutex lock one of the other scheduling
|
||||
priorities will determine which thread shall acquire the lock.</p>
|
||||
|
||||
<h3><a name="UndefinedScheduling">Undefined</a></h3>
|
||||
|
||||
<p>Threads acquire the lock in no particular order. Users should assume that
|
||||
low-priority threads may wait indefinitely, and that threads of the same
|
||||
priority acquire the lock in essentially random order.</p>
|
||||
|
||||
<h3><a name="UnspecifiedScheduling">Unspecified</a></h3>
|
||||
|
||||
<p>The mutex model does not specify which scheduling policy is used. The programmer
|
||||
must assume that an undefined scheduling policy is used. In order to ensure portability,
|
||||
all <b>Boost.Threads</b> mutex models use an unspecified scheduling policy.</p>
|
||||
|
||||
<h2>Concept <a name="Requirements">Requirements</a></h2>
|
||||
|
||||
<h3><a name="Mutex">Mutex</a> Concept</h3>
|
||||
|
||||
<p>A Mutex object has two states: locked and unlocked. Mutex object state can only be
|
||||
determined by an object meeting the <a href="lock_concept.html#ScopedLock">ScopedLock</a>
|
||||
requirements and constructed for the Mutex object.</p>
|
||||
|
||||
<p>A Mutex is <a href="../../utility/utility.htm#Class noncopyable">noncopyable</a>.</p>
|
||||
|
||||
<p>For a Mutex type M and an object m of that type, the following expressions must be
|
||||
well-formed and have the indicated effects.</p>
|
||||
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<td><b>Expression</b></td>
|
||||
<td><b>Effects</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>M m;</code></td>
|
||||
<td>Constructs a mutex object m. Post-condition: m is unlocked.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>(&m)->~M();</code></td>
|
||||
<td>Precondition: m is unlocked. Destroys a mutex object m.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>M::scoped_lock</code></td>
|
||||
<td>A type meeting the <a href="lock_concept.html#ScopedLock">ScopedLock</a>
|
||||
requirements.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3><a name="TryMutex">TryMutex</a> Concept</h3>
|
||||
<p>A TryMutex must meet the <a href="#Mutex"> Mutex</a> requirements. In addition, for a
|
||||
TryMutex type M and an object m of that type, the following expressions must be
|
||||
well-formed and have the indicated effects.</p>
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<td><b>Expression</b></td>
|
||||
<td><b>Effects</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>M::scoped_try_lock</code></td>
|
||||
<td>A type meeting the <a href="lock_concept.html#ScopedTryLock">ScopedTryLock</a>
|
||||
requirements.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3><a name="TimedMutex">TimedMutex</a> Concept</h3>
|
||||
<p>A TimedMutex must meet the <a href="#TryMutex"> TryMutex</a> requirements. In addition, for a
|
||||
TimedMutex type M and an object m of that type, the following
|
||||
expressions must be well-formed and have the indicated effects.</p>
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<td><b>Expression</b></td>
|
||||
<td><b>Effects</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>M::scoped_timed_lock</code></td>
|
||||
<td>A type meeting the <a href="lock_concept.html#ScopedTimedLock">ScopedTimedLock</a>
|
||||
requirements.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2><a name="Models">Models</a></h2>
|
||||
|
||||
<p> <b>Boost.Threads</b> currently supplies six classes which model mutex
|
||||
concepts.</p>
|
||||
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<td><b>Concept</b></td>
|
||||
<td><b>Refines</b></td>
|
||||
<td><b>Classes Modeling the Concept</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><a href="#Mutex">Mutex</a></td>
|
||||
<td valign="top"> </td>
|
||||
<td><A href="mutex.html">mutex</A><br>
|
||||
<A href="recursive_mutex.html">recursive_mutex</A></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><a href="#TryMutex">TryMutex</a></td>
|
||||
<td valign="top"><a href="#Mutex">Mutex</a></td>
|
||||
<td><A href="mutex.html">try_mutex<br>
|
||||
</A><A href="recursive_mutex.html">recursive_try_mutex</A> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><a href="#TimedMutex">TimedMutex</a></td>
|
||||
<td valign="top"><a href="#TryMutex">TryMutex</a></td>
|
||||
<td><A href="mutex.html">timed_mutex<br>
|
||||
</A><A href="recursive_mutex.html">recursive_timed_mutex</A></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->03 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39333" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <A href="mailto:williamkempf@hotmail.com">William E. Kempf</A>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
90
doc/once-ref.xml
Normal file
90
doc/once-ref.xml
Normal file
@@ -0,0 +1,90 @@
|
||||
<?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 % 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">
|
||||
<purpose>The <functionname>call_once</functionname> function and
|
||||
<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="thread.glossary.thread-safe">thread-safe</link>
|
||||
manner.</purpose>
|
||||
|
||||
<description>The implementation-defined macro
|
||||
<macroname>BOOST_ONCE_INIT</macroname> is a constant value used to
|
||||
initialize <code>once_flag</code> instances to indicate that the
|
||||
logically associated routine has not been run yet. See
|
||||
<functionname>call_once</functionname> for more details.</description>
|
||||
</macro>
|
||||
|
||||
<namespace name="boost">
|
||||
<typedef name="once_flag">
|
||||
<purpose>The <functionname>call_once</functionname> function and
|
||||
<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="thread.glossary.thread-safe">thread-safe</link>
|
||||
manner.</purpose>
|
||||
|
||||
<description>The implementation-defined type <code>once_flag</code>
|
||||
is used as a flag to insure a routine is called only once.
|
||||
Instances of this type should be statically initialized to
|
||||
<macroname>BOOST_ONCE_INIT</macroname>. See
|
||||
<functionname>call_once</functionname> for more details.
|
||||
</description>
|
||||
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<function name="call_once">
|
||||
<purpose>The <functionname>call_once</functionname> function and
|
||||
<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="thread.glossary.thread-safe">thread-safe</link>
|
||||
manner.</purpose>
|
||||
|
||||
<description>
|
||||
<para>Example usage is as follows:</para>
|
||||
<para>
|
||||
<programlisting>//Example usage:
|
||||
boost::once_flag once = BOOST_ONCE_INIT;
|
||||
|
||||
void init()
|
||||
{
|
||||
//...
|
||||
}
|
||||
|
||||
void thread_proc()
|
||||
{
|
||||
boost::call_once(&init, once);
|
||||
}</programlisting>
|
||||
</para></description>
|
||||
|
||||
<parameter name="func">
|
||||
<paramtype>void (*func)()</paramtype>
|
||||
</parameter>
|
||||
|
||||
<parameter name="flag">
|
||||
<paramtype>once_flag&</paramtype>
|
||||
</parameter>
|
||||
|
||||
<requires>The function <code>func</code> shall not throw
|
||||
exceptions.</requires>
|
||||
|
||||
<effects>As if (in an atomic fashion):
|
||||
<code>if (flag == BOOST_ONCE_INIT) func();</code></effects>
|
||||
|
||||
<postconditions><code>flag != BOOST_ONCE_INIT</code>
|
||||
</postconditions>
|
||||
</function>
|
||||
</namespace>
|
||||
</header>
|
||||
@@ -1,156 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Boost.Threads Overview</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><IMG height=86 alt="C++ Boost" src="../../../c++boost.gif" width=277></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">Overview</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p><a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Dangers">Dangers</a><br>
|
||||
<a href="#Library">C++ Standard Library usage</a><br>
|
||||
<a href="#Common">Common requirements</a></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
<p>Boost.Threads 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 call multi-threaded programs to distinguish them from
|
||||
traditional single-threaded programs. <a href="definitions.html">Definitions</a>
|
||||
gives a more complete description of the multi-threading execution environment.</p>
|
||||
<p>Multi-threading provides several advantages:</p>
|
||||
<ul>
|
||||
<li>Programs which would otherwise block waiting for some external event can
|
||||
continue to respond if the blocking operation is placed in a separate
|
||||
thread. Multi-threading is usually an absolute requirement for these
|
||||
programs.</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>Well-designed multi-threaded programs may execute faster than single-threaded
|
||||
programs, particularly on multi-processor hardware.
|
||||
Note, however, that poorly-designed multi-threaded programs are often slower
|
||||
that single-threaded programs.</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>Some program designs may be easier to formulate using a multi-threaded
|
||||
approach.
|
||||
After all, the real world is asynchronous! </li>
|
||||
</ul>
|
||||
<h2><a name="Dangers">Dangers</a></h2>
|
||||
<p>Beyond the errors which can occur in single-threaded programs, multi-threaded
|
||||
programs are subject to additional errors:</p>
|
||||
<ul>
|
||||
<li><a href="definitions.html#Race condition">Race conditions</a>.
|
||||
<li><a href="definitions.html#Deadlock">Deadlock</a> (sometimes called
|
||||
"deadly embrace")
|
||||
<li><a href="definitions.html#Priority failure">Priority failures</a>
|
||||
(priority inversion, infinite overtaking, starvation, etc.)</li>
|
||||
</ul>
|
||||
<p>Every multi-threaded program must be designed carefully to avoid race
|
||||
conditions and deadlock. These aren't rare or exotic failures - they are
|
||||
virtually guaranteed to occur unless multi-threaded code is designed to avoid
|
||||
them. Priority failures are somewhat less common, but are none-the-less
|
||||
serious.</p>
|
||||
<p>The <a href="introduction.html">Boost.Threads design</a> attempts to minimize
|
||||
these errors, but they will still occur unless the programmer proactively
|
||||
designs to avoid them.</p>
|
||||
<h3>Testing and debugging considerations</h3>
|
||||
<p>Multi-threaded programs are non-deterministic. In other words, the same
|
||||
program with the same input data may follow different execution paths each time
|
||||
it is invoked. That can make testing and debugging a nightmare:</p>
|
||||
<ul>
|
||||
<li>Failures are often not repeatable.
|
||||
<li>Probe effect causes debuggers to produce very different results from
|
||||
non-debug uses.
|
||||
<li>Debuggers require special support to show thread state.
|
||||
<li>Tests on a single processor system may give no indication of serious
|
||||
errors which would appear on multiprocessor systems, and visa versa. Thus test
|
||||
cases should include a varying number of processors. </li>
|
||||
<li>For programs which create a varying number of threads according to
|
||||
workload, tests which don't span the full range of possibilities may miss
|
||||
serious errors.</li>
|
||||
</ul>
|
||||
<h3>Getting a head start</h3>
|
||||
<p>Although it might appear that multi-threaded programs are inherently
|
||||
unreliable, many reliable multi-threaded programs do exist. Multi-threading
|
||||
techniques are known which lead to reliable programs.</p>
|
||||
<p>Design patterns for reliable multi-threaded programs, including the important
|
||||
<i>monitor</i> pattern, are presented in <cite>Pattern-Oriented Software Architecture Volume 2 - Patterns for
|
||||
Concurrent and Networked Objects</cite> [<a href="bibliography.html#Schmidt-00">Schmidt
|
||||
00</a>]. Many important multi-threading programming considerations
|
||||
(independent of threading library) are discussed in <cite>Programming with
|
||||
POSIX Threads</cite> [<a href="bibliography.html#Butenhof-97">Butenhof 97</a>].</p>
|
||||
<p>Reading and study first yields a head start toward designing reliable
|
||||
multi-threaded programs.</p>
|
||||
|
||||
<h2><a name="Library">C++ Standard Library usage in multi-threaded programs</a></h2>
|
||||
<h3>Runtime libraries</h3>
|
||||
<p><b>Warning:</b> Multi-threaded programs such as those using <b>Boost.Threads</b> must link to
|
||||
<a href="definitions.html#Thread-safe">thread-safe</a> versions of all runtime
|
||||
libraries used by the program, including the runtime library for the C++
|
||||
Standard Library. Otherwise <a href="definitions.html#Race condition">race
|
||||
conditions</a> will occur when multiple threads simultaneously execute runtime
|
||||
library functions for <i>new</i>, <i>delete</i>, or other language features
|
||||
which imply shared state. </p>
|
||||
<h3>Potentially non-thread-safe functions</h3>
|
||||
<p>Certain C++ Standard Library functions inherited from C are particular
|
||||
problems because they hold internal state between calls:</p>
|
||||
<ul>
|
||||
<li>rand</li>
|
||||
<li>strtok</li>
|
||||
<li>asctime</li>
|
||||
<li>ctime </li>
|
||||
<li>gmtime</li>
|
||||
<li>localtime</li>
|
||||
</ul>
|
||||
<p>It is possible to write thread-safe implementations of these by using <a href="thread_specific_ptr.html">thread-specific
|
||||
storage</a>, and several C++ compiler vendors do just that. The technique
|
||||
is well-know and is explained in [<a href="bibliography.html#Butenhof-97">Buttenhof-97</a>].</p>
|
||||
<p>But at least one vendor (HP-UX) does not provide thread-safe implementations
|
||||
of the above functions in their otherwise thread-safe runtime library.
|
||||
Instead they provide replacement functions with different names and arguments.</p>
|
||||
<p><b>Recommendation:</b> For the most portable, yet thread-safe code, use Boost
|
||||
replacements for the problem functions. See the <a href="../../random/index.html">Boost
|
||||
Random Number Library</a> and <a href="../../tokenizer/index.htm">Boost
|
||||
Tokenizer Library</a>.</p>
|
||||
<h2><a name="Common">Common</a> requirements for all Boost.Threads components</h2>
|
||||
<h3>Exceptions</h3>
|
||||
<p> <b>Boost.Threads</b> destructors never throw exceptions. Unless otherwise
|
||||
specified, other <b>Boost.Threads</b>
|
||||
functions that do not have an exception-specification may throw implementation-defined exceptions.</p>
|
||||
<p>In particular, <b>Boost.Threads</b> reports failure to allocate storage by throwing an exception of type
|
||||
std::bad_alloc, or a class derived from std::bad_alloc, failure to obtain
|
||||
thread resources other than memory by throwing an exception of type <a href="thread_resource_error.html">boost::thread_resource_error</a>,
|
||||
and certain lock related failures by throwing an exception of type <a href="lock_error.html">boost::lock_error</a></p>
|
||||
<p><b>Rationale: </b>Follows the C++ Standard Library practice of allowing all
|
||||
functions except destructors or other specified functions to throw exceptions on
|
||||
errors.</p>
|
||||
<h3><a name="NonCopyable">NonCopyable</a> requirement</h3>
|
||||
<p><b>Boost.Threads</b> 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 <a href="../../utility/utility.htm">boost::noncopyable</a>.
|
||||
Users should not depend on this derivation, however, as implementations are free
|
||||
to meet the NonCopyable requirement in other ways.</p>
|
||||
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->12 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39332" -->
|
||||
</p>
|
||||
<p>© Copyright 2001 Beman Dawes</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
206
doc/overview.xml
Normal file
206
doc/overview.xml
Normal file
@@ -0,0 +1,206 @@
|
||||
<?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 % 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.overview" last-revision="$Date$">
|
||||
<title>Overview</title>
|
||||
<section id="thread.introduction">
|
||||
<title>Introduction</title>
|
||||
<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="thread.glossary">glossary</link> gives a more complete description
|
||||
of the multithreading execution environment.</para>
|
||||
<para>Multithreading provides several advantages:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Programs which would otherwise block waiting for some external
|
||||
event can continue to respond if the blocking operation is placed in a
|
||||
separate thread. Multithreading is usually an absolute requirement for
|
||||
these programs.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Well-designed multithreaded programs may execute faster than
|
||||
single-threaded programs, particularly on multiprocessor hardware.
|
||||
Note, however, that poorly-designed multithreaded programs are often
|
||||
slower than single-threaded programs.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Some program designs may be easier to formulate using a
|
||||
multithreaded approach. After all, the real world is
|
||||
asynchronous!</para>
|
||||
</listitem>
|
||||
</itemizedlist></para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Dangers</title>
|
||||
<section>
|
||||
<title>General considerations</title>
|
||||
<para>Beyond the errors which can occur in single-threaded programs,
|
||||
multithreaded programs are subject to additional errors:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><link linkend="thread.glossary.race-condition">Race
|
||||
conditions</link></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><link linkend="thread.glossary.deadlock">Deadlock</link>
|
||||
(sometimes called "deadly embrace")</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><link linkend="thread.glossary.priority-failure">Priority
|
||||
failures</link> (priority inversion, infinite overtaking, starvation,
|
||||
etc.)</para>
|
||||
</listitem>
|
||||
</itemizedlist></para>
|
||||
<para>Every multithreaded program must be designed carefully to avoid these
|
||||
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="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="thread.implementation_notes"/>
|
||||
for additional, implementation-specific considerations.</note>
|
||||
</section>
|
||||
<section>
|
||||
<title>Testing and debugging considerations</title>
|
||||
<para>Multithreaded programs are non-deterministic. In other words, the
|
||||
same program with the same input data may follow different execution
|
||||
paths each time it is invoked. That can make testing and debugging a
|
||||
nightmare:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Failures are often not repeatable.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Probe effect causes debuggers to produce very different results
|
||||
from non-debug uses.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Debuggers require special support to show thread state.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Tests on a single processor system may give no indication of
|
||||
serious errors which would appear on multiprocessor systems, and visa
|
||||
versa. Thus test cases should include a varying number of
|
||||
processors.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>For programs which create a varying number of threads according
|
||||
to workload, tests which don't span the full range of possibilities
|
||||
may miss serious errors.</para>
|
||||
</listitem>
|
||||
</itemizedlist></para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Getting a head start</title>
|
||||
<para>Although it might appear that multithreaded programs are inherently
|
||||
unreliable, many reliable multithreaded programs do exist. Multithreading
|
||||
techniques are known which lead to reliable programs.</para>
|
||||
<para>Design patterns for reliable multithreaded programs, including the
|
||||
important <emphasis>monitor</emphasis> pattern, are presented in
|
||||
<emphasis>Pattern-Oriented Software Architecture Volume 2 - Patterns for
|
||||
Concurrent and Networked Objects</emphasis>
|
||||
&cite.SchmidtStalRohnertBuschmann;. Many important multithreading programming
|
||||
considerations (independent of threading library) are discussed in
|
||||
<emphasis>Programming with POSIX Threads</emphasis> &cite.Butenhof97;.</para>
|
||||
<para>Doing some reading before attempting multithreaded designs will
|
||||
give you a head start toward reliable multithreaded programs.</para>
|
||||
</section>
|
||||
</section>
|
||||
<section>
|
||||
<title>C++ Standard Library usage in multithreaded programs</title>
|
||||
<section>
|
||||
<title>Runtime libraries</title>
|
||||
<para>
|
||||
<emphasis role="bold">Warning:</emphasis> Multithreaded programs such as
|
||||
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="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>
|
||||
</section>
|
||||
<section>
|
||||
<title>Potentially non-thread-safe functions</title>
|
||||
<para>Certain C++ Standard Library functions inherited from C are
|
||||
particular problems because they hold internal state between
|
||||
calls:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><code>rand</code></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><code>strtok</code></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><code>asctime</code></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><code>ctime</code></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><code>gmtime</code></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><code>localtime</code></para>
|
||||
</listitem>
|
||||
</itemizedlist></para>
|
||||
<para>It is possible to write thread-safe implementations of these by
|
||||
using thread specific storage (see
|
||||
<classname>boost::thread_specific_ptr</classname>), and several C++
|
||||
compiler vendors do just that. The technique is well-know and is explained
|
||||
in &cite.Butenhof97;.</para>
|
||||
<para>But at least one vendor (HP-UX) does not provide thread-safe
|
||||
implementations of the above functions in their otherwise thread-safe
|
||||
runtime library. Instead they provide replacement functions with
|
||||
different names and arguments.</para>
|
||||
<para><emphasis role="bold">Recommendation:</emphasis> For the most
|
||||
portable, yet thread-safe code, use Boost replacements for the problem
|
||||
functions. See the <libraryname>Boost Random Number Library</libraryname>
|
||||
and <libraryname>Boost Tokenizer Library</libraryname>.</para>
|
||||
</section>
|
||||
</section>
|
||||
<section>
|
||||
<title>Common guarantees for all &Boost.Thread; components</title>
|
||||
<section>
|
||||
<title>Exceptions</title>
|
||||
<para>&Boost.Thread; destructors never
|
||||
throw exceptions. Unless otherwise specified, other
|
||||
&Boost.Thread; functions that do not have
|
||||
an exception-specification may throw implementation-defined
|
||||
exceptions.</para>
|
||||
<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
|
||||
memory by throwing an exception of type
|
||||
<classname>boost::thread_resource_error</classname>, and certain lock
|
||||
related failures by throwing an exception of type
|
||||
<classname>boost::lock_error</classname>.</para>
|
||||
<para><emphasis role="bold">Rationale:</emphasis> Follows the C++ Standard
|
||||
Library practice of allowing all functions except destructors or other
|
||||
specified functions to throw exceptions on errors.</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>NonCopyable requirement</title>
|
||||
<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
|
||||
should not depend on this derivation, however, as implementations are free
|
||||
to meet the NonCopyable requirement in other ways.</para>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
@@ -1,431 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, BTL, thread library, C++">
|
||||
<title>Boost.Threads, rationale</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><IMG height=86 alt="C++ Boost" src="../../../c++boost.gif" width=277></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">Rationale</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>This page explains the rationale behind various design decisions in the <b> Boost.Threads</b>
|
||||
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.</p>
|
||||
|
||||
<h2><a name="library">Rationale for the Creation of Boost.Threads</a></h2>
|
||||
|
||||
<p>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 multi-threaded programming are quite well known to most modern programmers,
|
||||
yet the C++ language doesn't directly support this concept.</p>
|
||||
|
||||
<p>Many platforms support multi-threaded programming despite the fact that the language doesn't support
|
||||
it. They do this through external libraries, which are, unfortunately, platform specific. POSIX has
|
||||
tried to address this problem through the standardization of a "pthread" library. However, this
|
||||
is a standard only on POSIX platforms, so its portability is limited.</p>
|
||||
|
||||
<p>Another problem with POSIX and other platform specific thread libraries is that they are
|
||||
almost universally C based libraries. This leaves several C++ specific issues unresolved, such
|
||||
as what happens when an exception is thrown in a thread. Further, there are some C++ concepts,
|
||||
such as destructors, that can make usage much easier than what's available in a C library.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<p>The Boost.Threads library was developed to provide a C++ developer with a portable interface
|
||||
for writing multi-threaded 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.</p>
|
||||
|
||||
<h2><a name="primitives">Rationale for the Low Level Primitives Supported in Boost.Threads</a></h2>
|
||||
|
||||
<p>The Boost.Threads library supplies a set of low level primitives for writing multi-threaded
|
||||
programs, such as semaphores, mutexes and condition variables. In fact, the first release of
|
||||
Boost.Threads supports only these low level primitives. However, computer
|
||||
science research has shown
|
||||
that use of these primitives is difficult since there's no way 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 lower level
|
||||
concepts?</p>
|
||||
|
||||
<p>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 level concepts makes it easier to develop
|
||||
the higher level concepts and will allow researchers to experiment with various techniques.</p>
|
||||
|
||||
<p>Beyond this theoretical application of higher level concepts, however, the fact remains that
|
||||
many multi-threaded programs are written using only the lower level concepts, so they are
|
||||
useful in and of themselves, even if it's hard to prove that their usage is correct. Since
|
||||
many users will be familiar with these lower level concepts but be unfamiliar with any of the
|
||||
higher level concepts there's also an argument for accessibility.</p>
|
||||
|
||||
<h2><a name="lock_objects">Rationale for the Lock Design</a></h2>
|
||||
|
||||
<p>Programmers who are used to multi-threaded programming issues will quickly note that the
|
||||
Boost.Thread's design for mutex lock concepts is not <a href="file:///c:/boost/site/libs/thread/doc/definitions.html#Thread-safe">thread-safe</a>
|
||||
(this is clearly documented
|
||||
as well). At first this may seem like a serious design flaw. Why have a multi-threading primitive
|
||||
that's not thread-safe itself?</p>
|
||||
|
||||
<p>A lock object is not a synchronization primitive. A lock object's sole responsibility is
|
||||
to ensure that a mutex is both locked and unlocked in a manner that won't result in the common
|
||||
error of locking a mutex and then forgetting to unlock it. This means that instances of a
|
||||
lock object are only going to be created, at least in theory, within block scope and won't
|
||||
be shared between threads. Only the mutex objects will be created outside of block scope and/or
|
||||
shared between threads. Though it's possible to create a lock object outside of block scope and
|
||||
to share it between threads to do so would not be a typical usage. Nor are there any cases when
|
||||
such usage would be required.</p>
|
||||
|
||||
<p>Lock objects must maintain some state information. In order to allow a program to determine
|
||||
if a try_lock or timed_lock was successful the lock object must retain state indicating
|
||||
the success or failure of the call made in its constructor. If a lock object were to have
|
||||
such state and remain thread-safe it would need to synchronize access to the state information
|
||||
which would result in roughly doubling the time of most operations. Worse, 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.</p>
|
||||
|
||||
<p>So, to avoid the overhead of synchronizing access to the state information and to avoid
|
||||
the race condition the Boost.Threads 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 multi-threading issues.</p>
|
||||
|
||||
<h2><a name="thread">Rationale for Non-copyable Thread Type</a></h2>
|
||||
|
||||
<p>Programmers who are used to C libraries for multi-threaded programming are likely to
|
||||
wonder why Boost.Threads uses a non-copyable design for <a href="thread.html">boost::thread</a>. 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 in this logic.</p>
|
||||
|
||||
<p>All C types are copyable. It is, in fact, not possible to make a non-copyable type in
|
||||
C. For this reason types that represent system resources in C are often designed to behave
|
||||
very similarly to a pointer to dynamic memory. There's an API for acquiring the resource
|
||||
and an API for releasing the resources. For memory we have pointers as the type and
|
||||
alloc/free for the acquisition and release APIs. For files we have FILE* as the type
|
||||
and fopen/fclose for the acquisition and release APIs. You can freely copy instances of the
|
||||
types but must manually manage the lifetime of the actual resource through the acquisition
|
||||
and release APIs.</p>
|
||||
|
||||
<p>C++ designs recognize that the acquisition and release APIs are error prone and try
|
||||
to eliminate possible errors by acquiring the resource in the constructor and releasing it
|
||||
in the destructor. The best example of such a design is the std::iostream set of classes
|
||||
which can represent the same resource as the FILE* type in C. A file is opened in the
|
||||
std::fstream's constructor and closed in its destructor. However, if an iostream were
|
||||
copyable it could lead to a file being closed twice, an obvious error, so the std::iostream
|
||||
types are noncopyable by design. This is the same design used by boost::thread, which
|
||||
is a simple and easy to understand design that's consistent with other C++ standard types.</p>
|
||||
|
||||
<p>During the design of boost::thread it was pointed out that it would be possible to allow
|
||||
it to be a copyable type if some form of "reference management" were used, such as ref-counting
|
||||
or ref-lists, and many argued for a boost::thread_ref design instead. The reasoning was
|
||||
that copying "thread" objects was a typical need in the C libraries, and so presumably would
|
||||
be in the C++ libraries as well. It was also thought that implementations could provide
|
||||
more efficient reference management then wrappers (such as boost::shared_ptr) around a noncopyable
|
||||
thread concept. Analysis of whether or not these arguments would hold true don't 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.</p>
|
||||
|
||||
<h3>1. Simple creation of a thread.</h3>
|
||||
|
||||
<pre>
|
||||
void foo()
|
||||
{
|
||||
create_thread(&bar);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>2. Creation of a thread that's later joined.</h3>
|
||||
|
||||
<pre>
|
||||
void foo()
|
||||
{
|
||||
thread = create_thread(&bar);
|
||||
join(thread);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>3. Simple creation of several threads in a loop.</h3>
|
||||
|
||||
<pre>
|
||||
void foo()
|
||||
{
|
||||
for (int i=0; i<NUM_THREADS; ++i)
|
||||
create_thread(&bar);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>4. Creation of several threads in a loop which are later joined.</h3>
|
||||
|
||||
<pre>
|
||||
void foo()
|
||||
{
|
||||
for (int i=0; i<NUM_THREADS; ++i)
|
||||
threads[i] = create_thread(&bar);
|
||||
for (int i=0; i<NUM_THREADS; ++i)
|
||||
threads[i].join();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>5. Creation of a thread whose ownership is passed to another object/method.</h3>
|
||||
|
||||
<pre>
|
||||
void foo()
|
||||
{
|
||||
thread = create_thread(&bar);
|
||||
manager.owns(thread);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>6. Creation of a thread whose ownership is shared between multiple objects.</h3>
|
||||
|
||||
<pre>
|
||||
void foo()
|
||||
{
|
||||
thread = create_thread(&bar);
|
||||
manager1.add(thread);
|
||||
manager2.add(thread);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Of these usage patterns there's only one that requires reference management (number 6).
|
||||
Hopefully it's fairly obvious that this usage pattern simply won't occur as often as the
|
||||
other usage patterns. So there really isn't a "typical need" for a thread concept, though
|
||||
there is some need.</p>
|
||||
|
||||
<p>Since the need isn't typical we must use different criteria for deciding on either a
|
||||
thread_ref or thread design. Possible criteria include ease of use and performance. So let's
|
||||
analyze both of these carefully.</p>
|
||||
|
||||
<p>With ease of use we can look at existing experience. The standard C++ objects that
|
||||
represent a system resource, such as std::iostream, are noncopyable, so we know that C++
|
||||
programmers must at least be experienced with this design. Most C++ developers are also
|
||||
used to smart pointers such as boost::shared_ptr, so we know they can at least adapt to
|
||||
a thread_ref concept with little effort. So existing experience isn't going to lead us
|
||||
to a choice.</p>
|
||||
|
||||
<p>The other thing we can look at is how difficult it is to use both types for the six usage
|
||||
patterns above. If we find it overly difficult to 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.</p>
|
||||
|
||||
<h3>1.</h3>
|
||||
|
||||
<pre>
|
||||
void foo()
|
||||
{
|
||||
thread thrd(&bar);
|
||||
}
|
||||
|
||||
void foo()
|
||||
{
|
||||
thread_ref thrd = create_thread(&bar);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>2.</h3>
|
||||
|
||||
<pre>
|
||||
void foo()
|
||||
{
|
||||
thread thrd(&bar);
|
||||
thrd.join();
|
||||
}
|
||||
|
||||
void foo()
|
||||
{
|
||||
thread_ref thrd =
|
||||
create_thread(&bar);thrd->join();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>3.</h3>
|
||||
|
||||
<pre>
|
||||
void foo()
|
||||
{
|
||||
for (int i=0; i<NUM_THREADS; ++i)
|
||||
thread thrd(&bar);
|
||||
}
|
||||
|
||||
void foo()
|
||||
{
|
||||
for (int i=0; i<NUM_THREADS; ++i)
|
||||
thread_ref thrd = create_thread(&bar);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>4.</h3>
|
||||
|
||||
<pre>
|
||||
void foo()
|
||||
{
|
||||
std::auto_ptr<thread> threads[NUM_THREADS];
|
||||
for (int i=0; i<NUM_THREADS; ++i)
|
||||
threads[i] = std::auto_ptr<thread>(new thread(&bar));
|
||||
for (int i= 0; i<NUM_THREADS;
|
||||
++i)threads[i]->join();
|
||||
}
|
||||
|
||||
void foo()
|
||||
{
|
||||
thread_ref threads[NUM_THREADS];
|
||||
for (int i=0; i<NUM_THREADS; ++i)
|
||||
threads[i] = create_thread(&bar);
|
||||
for (int i= 0; i<NUM_THREADS;
|
||||
++i)threads[i]->join();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>5.</h3>
|
||||
|
||||
<pre>
|
||||
void foo()
|
||||
{
|
||||
thread thrd* = new thread(&bar);
|
||||
manager.owns(thread);
|
||||
}
|
||||
|
||||
void foo()
|
||||
{
|
||||
thread_ref thrd = create_thread(&bar);
|
||||
manager.owns(thrd);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>6.</h3>
|
||||
|
||||
<pre>
|
||||
void foo()
|
||||
{
|
||||
boost::shared_ptr<thread> thrd(new thread(&bar));
|
||||
manager1.add(thrd);
|
||||
manager2.add(thrd);
|
||||
}
|
||||
|
||||
void foo()
|
||||
{
|
||||
thread_ref thrd = create_thread(&bar);
|
||||
manager1.add(thrd);
|
||||
manager2.add(thrd);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>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 (4), (5)
|
||||
and (6) and the use of std::auto_ptr and boost::shared_ptr in (4) and (6) respectively.
|
||||
However, that's not really much added complexity, and C++ programmers are used to using
|
||||
these idioms any way. 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 (4) down to:</p>
|
||||
|
||||
<pre>
|
||||
void foo()
|
||||
{
|
||||
thread_group threads;
|
||||
for (int i=0; i<NUM_THREADS; ++i)
|
||||
threads.create_thread(&bar);
|
||||
threads.join_all();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>So ease of use is really a wash and not much help in picking a design.</p>
|
||||
|
||||
<p>So what about performance? If you look at the above code examples we can analyze
|
||||
the theoretical impact to performance that both designs have. For (1) 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 (2) the
|
||||
performance impact will be identical to (1). The same for (3). For (4) 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 (5)
|
||||
we see the same impact as we do for (4). For (6) we still have a possible impact
|
||||
to the thread design because of dynamic allocation but thread_ref no longer suffers
|
||||
because of it's 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 (1), (2) and (3), with (4) and (5) the winner depends on the implementation and the platform
|
||||
but the thread design probably has a better chance, and with (6) 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.</p>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h2>Rationale for not providing <i><a name="Events">Event</a> Variables</i></h2>
|
||||
|
||||
<p><i>Event variables </i>are simply far too error-prone. <a href="condition.html">Condition
|
||||
variables</a> are a much safer alternative.</p>
|
||||
|
||||
<p>[Note that Graphical User Interface <i>events</i> are a different concept,
|
||||
and are not what is being discussed here.]</p>
|
||||
|
||||
<p>Event variables were one of the first synchronization primitives. They are
|
||||
still used today, for example, in the native Windows multithreading API.</p>
|
||||
|
||||
<p>Yet both respected computer science researchers and experienced
|
||||
multithreading practitioners believe event variables are so inherently
|
||||
error-prone that they should never be used, and thus should not be part of a
|
||||
multithreading library.</p>
|
||||
|
||||
<p>Per Brinch Hansen <a href="bibliography.html#Brinch-Hansen-73">[Brinch Hansen
|
||||
73]</a> analyzed event variables in some detail, pointing out [emphasis his]
|
||||
that "<i>event operations force the programmer to be aware of the relative
|
||||
speeds of the sending and receiving processes</i>". His summary:</p>
|
||||
|
||||
<blockquote>
|
||||
<p>We must therefore conclude that event variables of the previous type are
|
||||
impractical for system design. <i>The effect of an interaction between two
|
||||
processes must be independent of the speed at which it is carried out.</i></p>
|
||||
|
||||
</blockquote>
|
||||
<p>Experienced programmers using the Windows platform today
|
||||
report that event variables are a continuing source of errors, even after previous
|
||||
bad 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 <a href="definitions.html#Race condition">race
|
||||
condition</a> 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.</p>
|
||||
|
||||
<p>The decision to exclude event variables from Boost.Threads 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 events, like gotos, can't be made to work, but rather that
|
||||
virtually all programs using alternatives will be easier to write, debug,
|
||||
read, maintain, and be less likely to contain latent defects.</p>
|
||||
|
||||
<p>[Rationale provided by Beman Dawes]</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->17 August, 2001<!--webbot bot="Timestamp" endspan i-checksum="34355" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <A href="mailto:williamkempf@hotmail.com">William E. Kempf</A>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
438
doc/rationale.xml
Normal file
438
doc/rationale.xml
Normal file
@@ -0,0 +1,438 @@
|
||||
<?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 % 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.rationale" last-revision="$Date$">
|
||||
<title>Rationale</title>
|
||||
<para>This page explains the rationale behind various design decisions in the
|
||||
&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="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
|
||||
multithreaded programming are quite well known to most modern programmers,
|
||||
yet the C++ language doesn't directly support this concept.</para>
|
||||
<para>Many platforms support multithreaded programming despite the fact that
|
||||
the language doesn't support it. They do this through external libraries,
|
||||
which are, unfortunately, platform specific. POSIX has tried to address this
|
||||
problem through the standardization of a "pthread" library. However, this is
|
||||
a standard only on POSIX platforms, so its portability is limited.</para>
|
||||
<para>Another problem with POSIX and other platform specific thread
|
||||
libraries is that they are almost universally C based libraries. This leaves
|
||||
several C++ specific issues unresolved, such as what happens when an
|
||||
exception is thrown in a thread. Further, there are some C++ concepts, such
|
||||
as destructors, that can make usage much easier than what's available in a C
|
||||
library.</para>
|
||||
<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.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="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.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.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
|
||||
level concepts makes it easier to develop the higher level concepts and will
|
||||
allow researchers to experiment with various techniques.</para>
|
||||
<para>Beyond this theoretical application of higher level concepts, however,
|
||||
the fact remains that many multithreaded programs are written using only the
|
||||
lower level concepts, so they are useful in and of themselves, even if it's
|
||||
hard to prove that their usage is correct. Since many users will be familiar
|
||||
with these lower level concepts but unfamiliar with any of the higher
|
||||
level concepts, supporting the lower level concepts provides
|
||||
greater accessibility.</para>
|
||||
</section>
|
||||
<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.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>
|
||||
<para>A lock object is not a synchronization primitive. A lock object's sole
|
||||
responsibility is to ensure that a mutex is both locked and unlocked in a
|
||||
manner that won't result in the common error of locking a mutex and then
|
||||
forgetting to unlock it. This means that instances of a lock object are only
|
||||
going to be created, at least in theory, within block scope and won't be
|
||||
shared between threads. Only the mutex objects will be created outside of
|
||||
block scope and/or shared between threads. Though it's possible to create a
|
||||
lock object outside of block scope and to share it between threads, to do so
|
||||
would not be a typical usage (in fact, to do so would likely be an
|
||||
error). Nor are there any cases when such usage would be required.</para>
|
||||
<para>Lock objects must maintain some state information. In order to allow a
|
||||
program to determine if a try_lock or timed_lock was successful the lock
|
||||
object must retain state indicating the success or failure of the call made
|
||||
in its constructor. If a lock object were to have such state and remain
|
||||
thread-safe it would need to synchronize access to the state information
|
||||
which would result in roughly doubling the time of most operations. Worse,
|
||||
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.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="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.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
|
||||
in this logic.</para>
|
||||
<para>All C types are copyable. It is, in fact, not possible to make a
|
||||
noncopyable type in C. For this reason types that represent system resources
|
||||
in C are often designed to behave very similarly to a pointer to dynamic
|
||||
memory. There's an API for acquiring the resource and an API for releasing
|
||||
the resource. For memory we have pointers as the type and alloc/free for
|
||||
the acquisition and release APIs. For files we have FILE* as the type and
|
||||
fopen/fclose for the acquisition and release APIs. You can freely copy
|
||||
instances of the types but must manually manage the lifetime of the actual
|
||||
resource through the acquisition and release APIs.</para>
|
||||
<para>C++ designs recognize that the acquisition and release APIs are error
|
||||
prone and try to eliminate possible errors by acquiring the resource in the
|
||||
constructor and releasing it in the destructor. The best example of such a
|
||||
design is the std::iostream set of classes which can represent the same
|
||||
resource as the FILE* type in C. A file is opened in the std::fstream's
|
||||
constructor and closed in its destructor. However, if an iostream were
|
||||
copyable it could lead to a file being closed twice, an obvious error, so
|
||||
the std::iostream types are noncopyable by design. This is the same design
|
||||
used by boost::thread, which is a simple and easy to understand design
|
||||
that's consistent with other C++ standard types.</para>
|
||||
<para>During the design of boost::thread it was pointed out that it would be
|
||||
possible to allow it to be a copyable type if some form of "reference
|
||||
management" were used, such as ref-counting or ref-lists, and many argued
|
||||
for a boost::thread_ref design instead. The reasoning was that copying
|
||||
"thread" objects was a typical need in the C libraries, and so presumably
|
||||
would be in the C++ libraries as well. It was also thought that
|
||||
implementations could provide more efficient reference management than
|
||||
wrappers (such as boost::shared_ptr) around a noncopyable thread
|
||||
concept. Analysis of whether or not these arguments would hold true doesn't
|
||||
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="thread.rationale.non-copyable.simple">
|
||||
<title>1. Use case: Simple creation of a thread.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
{
|
||||
create_thread(&bar);
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="thread.rationale.non-copyable.joined">
|
||||
<title>2. Use case: Creation of a thread that's later joined.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
{
|
||||
thread = create_thread(&bar);
|
||||
join(thread);
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="thread.rationale.non-copyable.loop">
|
||||
<title>3. Use case: Simple creation of several threads in a loop.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
{
|
||||
for (int i=0; i<NUM_THREADS; ++i)
|
||||
create_thread(&bar);
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<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()
|
||||
{
|
||||
for (int i=0; i<NUM_THREADS; ++i)
|
||||
threads[i] = create_thread(&bar);
|
||||
for (int i=0; i<NUM_THREADS; ++i)
|
||||
threads[i].join();
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<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()
|
||||
{
|
||||
thread = create_thread(&bar);
|
||||
manager.owns(thread);
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="thread.rationale.non-copyable.shared">
|
||||
<title>6. Use case: Creation of a thread whose ownership is shared between multiple
|
||||
objects.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
{
|
||||
thread = create_thread(&bar);
|
||||
manager1.add(thread);
|
||||
manager2.add(thread);
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<para>Of these usage patterns there's only one that requires reference
|
||||
management (number 6). Hopefully it's fairly obvious that this usage pattern
|
||||
simply won't occur as often as the other usage patterns. So there really
|
||||
isn't a "typical need" for a thread concept, though there is some
|
||||
need.</para>
|
||||
<para>Since the need isn't typical we must use different criteria for
|
||||
deciding on either a thread_ref or thread design. Possible criteria include
|
||||
ease of use and performance. So let's analyze both of these
|
||||
carefully.</para>
|
||||
<para>With ease of use we can look at existing experience. The standard C++
|
||||
objects that represent a system resource, such as std::iostream, are
|
||||
noncopyable, so we know that C++ programmers must at least be experienced
|
||||
with this design. Most C++ developers are also used to smart pointers such
|
||||
as boost::shared_ptr, so we know they can at least adapt to a thread_ref
|
||||
concept with little effort. So existing experience isn't going to lead us to
|
||||
a choice.</para>
|
||||
<para>The other thing we can look at is how difficult it is to use both
|
||||
types for the six usage patterns above. If we find it overly difficult to
|
||||
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="thread.rationale_comparison.non-copyable.simple">
|
||||
<title>1. Comparison: simple creation of a thread.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
{
|
||||
thread thrd(&bar);
|
||||
}
|
||||
void foo()
|
||||
{
|
||||
thread_ref thrd = create_thread(&bar);
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="thread.rationale_comparison.non-copyable.joined">
|
||||
<title>2. Comparison: creation of a thread that's later joined.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
{
|
||||
thread thrd(&bar);
|
||||
thrd.join();
|
||||
}
|
||||
void foo()
|
||||
{
|
||||
thread_ref thrd =
|
||||
create_thread(&bar);thrd->join();
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="thread.rationale_comparison.non-copyable.loop">
|
||||
<title>3. Comparison: simple creation of several threads in a loop.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
{
|
||||
for (int i=0; i<NUM_THREADS; ++i)
|
||||
thread thrd(&bar);
|
||||
}
|
||||
void foo()
|
||||
{
|
||||
for (int i=0; i<NUM_THREADS; ++i)
|
||||
thread_ref thrd = create_thread(&bar);
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<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()
|
||||
{
|
||||
std::auto_ptr<thread> threads[NUM_THREADS];
|
||||
for (int i=0; i<NUM_THREADS; ++i)
|
||||
threads[i] = std::auto_ptr<thread>(new thread(&bar));
|
||||
for (int i= 0; i<NUM_THREADS;
|
||||
++i)threads[i]->join();
|
||||
}
|
||||
void foo()
|
||||
{
|
||||
thread_ref threads[NUM_THREADS];
|
||||
for (int i=0; i<NUM_THREADS; ++i)
|
||||
threads[i] = create_thread(&bar);
|
||||
for (int i= 0; i<NUM_THREADS;
|
||||
++i)threads[i]->join();
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<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()
|
||||
{
|
||||
thread thrd* = new thread(&bar);
|
||||
manager.owns(thread);
|
||||
}
|
||||
void foo()
|
||||
{
|
||||
thread_ref thrd = create_thread(&bar);
|
||||
manager.owns(thrd);
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="thread.rationale_comparison.non-copyable.shared">
|
||||
<title>6. Comparison: creation of a thread whose ownership is shared
|
||||
between multiple objects.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
{
|
||||
boost::shared_ptr<thread> thrd(new thread(&bar));
|
||||
manager1.add(thrd);
|
||||
manager2.add(thrd);
|
||||
}
|
||||
void foo()
|
||||
{
|
||||
thread_ref thrd = create_thread(&bar);
|
||||
manager1.add(thrd);
|
||||
manager2.add(thrd);
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<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="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="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="thread.rationale_comparison.non-copyable.loop-join">(4)</link>
|
||||
down to:</para>
|
||||
<programlisting>
|
||||
void foo()
|
||||
{
|
||||
thread_group threads;
|
||||
for (int i=0; i<NUM_THREADS; ++i)
|
||||
threads.create_thread(&bar);
|
||||
threads.join_all();
|
||||
}
|
||||
</programlisting>
|
||||
<para>So ease of use is really a wash and not much help in picking a
|
||||
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="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="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="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="thread.rationale_comparison.non-copyable.pass">(5)</link> we see
|
||||
the same impact as we do for
|
||||
<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="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="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.Thread; library has gone with a noncopyable design.</para>
|
||||
</section>
|
||||
<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
|
||||
alternative. [Note that Graphical User Interface <emphasis>events</emphasis> are
|
||||
a different concept, and are not what is being discussed here.]</para>
|
||||
<para>Event variables were one of the first synchronization primitives. They
|
||||
are still used today, for example, in the native Windows multithreading
|
||||
API. Yet both respected computer science researchers and experienced
|
||||
multithreading practitioners believe event variables are so inherently
|
||||
error-prone that they should never be used, and thus should not be part of a
|
||||
multithreading library.</para>
|
||||
<para>Per Brinch Hansen &cite.Hansen73; analyzed event variables in some
|
||||
detail, pointing out [emphasis his] that "<emphasis>event operations force
|
||||
the programmer to be aware of the relative speeds of the sending and
|
||||
receiving processes</emphasis>". His summary:</para>
|
||||
<blockquote>
|
||||
<para>We must therefore conclude that event variables of the previous type
|
||||
are impractical for system design. <emphasis>The effect of an interaction
|
||||
between two processes must be independent of the speed at which it is
|
||||
carried out.</emphasis></para>
|
||||
</blockquote>
|
||||
<para>Experienced programmers using the Windows platform today report that
|
||||
event variables are a continuing source of errors, even after previous bad
|
||||
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="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.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
|
||||
events, like gotos, can't be made to work, but rather that virtually all
|
||||
programs using alternatives will be easier to write, debug, read, maintain,
|
||||
and will be less likely to contain latent defects.</para>
|
||||
<para>[Rationale provided by Beman Dawes]</para>
|
||||
</section>
|
||||
</section>
|
||||
462
doc/read_write_mutex-ref.xml
Normal file
462
doc/read_write_mutex-ref.xml
Normal file
@@ -0,0 +1,462 @@
|
||||
<?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 % 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">
|
||||
<namespace name="read_write_scheduling_policy">
|
||||
<enum name="read_write_scheduling_policy">
|
||||
<enumvalue name="writer_priority" />
|
||||
<enumvalue name="reader_priority" />
|
||||
<enumvalue name="alternating_many_reads" />
|
||||
<enumvalue name="alternating_single_read" />
|
||||
|
||||
<purpose>
|
||||
<para>Specifies the
|
||||
<link linkend="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.Thread; is
|
||||
<code>TIME_UTC</code>. The epoch for <code>TIME_UTC</code>
|
||||
is 1970-01-01 00:00:00.</para>
|
||||
</description>
|
||||
</enum>
|
||||
</namespace>
|
||||
|
||||
<class name="read_write_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>read_write_mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.ReadWriteMutex">ReadWriteMutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>read_write_mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.ReadWriteMutex">ReadWriteMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<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="thread.concepts.read-write-lock-models">model</link>
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
<tgroup cols="2" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Lock Name</entry>
|
||||
<entry>Lock Concept</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_read_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_read_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
|
||||
<para>The <classname>read_write_mutex</classname> class uses an
|
||||
<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>.
|
||||
This strategy allows implementations to be as efficient as possible
|
||||
on any given platform. It is, however, recommended that
|
||||
implementations include debugging support to detect misuse when
|
||||
<code>NDEBUG</code> is not defined.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="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="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="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="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
|
||||
lock the same <classname>read_write_mutex</classname> multiple times
|
||||
unless all locks are read-locks (but see below)</note>
|
||||
</description>
|
||||
|
||||
<inherit access="private">
|
||||
<type><classname>boost::noncopyable</classname></type>
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<inherit access="private">
|
||||
<type><classname>boost::noncopyable</classname></type>
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<typedef name="scoped_read_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_read_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<constructor>
|
||||
<parameter name="count">
|
||||
<paramtype>boost::read_write_scheduling_policy</paramtype>
|
||||
</parameter>
|
||||
|
||||
<effects>Constructs a <classname>read_write_mutex</classname> object.
|
||||
</effects>
|
||||
|
||||
<postconditions><code>*this</code> is in an unlocked state.
|
||||
</postconditions>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<effects>Destroys a <classname>read_write_mutex</classname> object.</effects>
|
||||
|
||||
<requires><code>*this</code> is in an unlocked state.</requires>
|
||||
|
||||
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
|
||||
locked mutex is a serious programming error resulting in undefined
|
||||
behavior such as a program crash.</notes>
|
||||
</destructor>
|
||||
</class>
|
||||
|
||||
<class name="try_read_write_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>try_read_write_mutex</classname> class is a model of the
|
||||
<link linkend="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="thread.concepts.TryReadWriteMutex">TryReadWriteMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<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="thread.concepts.read-write-lock-models">model</link>
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
<tgroup cols="2" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Lock Name</entry>
|
||||
<entry>Lock Concept</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_read_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_read_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_read_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_read_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
|
||||
<para>The <classname>try_read_write_mutex</classname> class uses an
|
||||
<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>.
|
||||
This strategy allows implementations to be as efficient as possible
|
||||
on any given platform. It is, however, recommended that
|
||||
implementations include debugging support to detect misuse when
|
||||
<code>NDEBUG</code> is not defined.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="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="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="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="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
|
||||
lock the same <classname>try_read_write_mutex</classname> multiple times
|
||||
unless all locks are read-locks (but see below)</note>
|
||||
</description>
|
||||
|
||||
<inherit access="private">
|
||||
<type><classname>boost::noncopyable</classname></type>
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<typedef name="scoped_read_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_read_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_read_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_read_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<constructor>
|
||||
<parameter name="count">
|
||||
<paramtype>boost::read_write_scheduling_policy</paramtype>
|
||||
</parameter>
|
||||
|
||||
<effects>Constructs a <classname>try_read_write_mutex</classname> object.
|
||||
</effects>
|
||||
|
||||
<postconditions><code>*this</code> is in an unlocked state.
|
||||
</postconditions>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<effects>Destroys a <classname>try_read_write_mutex</classname> object.</effects>
|
||||
|
||||
<requires><code>*this</code> is in an unlocked state.</requires>
|
||||
|
||||
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
|
||||
locked mutex is a serious programming error resulting in undefined
|
||||
behavior such as a program crash.</notes>
|
||||
</destructor>
|
||||
</class>
|
||||
|
||||
<class name="timed_read_write_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>timed_read_write_mutex</classname> class is a model of the
|
||||
<link linkend="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="thread.concepts.TimedReadWriteMutex">TimedReadWriteMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<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="thread.concepts.read-write-lock-models">model</link>
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
<tgroup cols="2" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Lock Name</entry>
|
||||
<entry>Lock Concept</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_read_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_read_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_read_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTimedReadWriteLock">ScopedTimedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_read_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_read_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_read_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
|
||||
<para>The <classname>timed_read_write_mutex</classname> class uses an
|
||||
<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>.
|
||||
This strategy allows implementations to be as efficient as possible
|
||||
on any given platform. It is, however, recommended that
|
||||
implementations include debugging support to detect misuse when
|
||||
<code>NDEBUG</code> is not defined.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="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="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="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="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
|
||||
lock the same <classname>timed_read_write_mutex</classname> multiple times
|
||||
unless all locks are read-locks (but see below)</note>
|
||||
</description>
|
||||
|
||||
<typedef name="scoped_read_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_read_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_timed_read_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_read_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_read_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_timed_read_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_timed_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<constructor>
|
||||
<parameter name="count">
|
||||
<paramtype>boost::read_write_scheduling_policy</paramtype>
|
||||
</parameter>
|
||||
|
||||
<effects>Constructs a <classname>timed_read_write_mutex</classname> object.
|
||||
</effects>
|
||||
|
||||
<postconditions><code>*this</code> is in an unlocked state.
|
||||
</postconditions>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<effects>Destroys a <classname>timed_read_write_mutex</classname> object.</effects>
|
||||
|
||||
<requires><code>*this</code> is in an unlocked state.</requires>
|
||||
|
||||
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
|
||||
locked mutex is a serious programming error resulting in undefined
|
||||
behavior such as a program crash.</notes>
|
||||
</destructor>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
306
doc/recursive_mutex-ref.xml
Normal file
306
doc/recursive_mutex-ref.xml
Normal file
@@ -0,0 +1,306 @@
|
||||
<?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 % 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="thread.concepts.Mutex">Mutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>recursive_mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.Mutex">Mutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<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="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking mechanics, see <classname>mutex</classname>,
|
||||
<classname>try_mutex</classname>, and <classname>timed_mutex</classname>.
|
||||
</para>
|
||||
|
||||
<para>The <classname>recursive_mutex</classname> class supplies the following typedef,
|
||||
which models the specified locking strategy:
|
||||
|
||||
<table>
|
||||
<title>Supported Lock Types</title>
|
||||
<tgroup cols="2" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Lock Name</entry>
|
||||
<entry>Lock Concept</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</para>
|
||||
|
||||
<para>The <classname>recursive_mutex</classname> class uses a
|
||||
<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.
|
||||
Attempts to unlock a <classname>recursive_mutex</classname> object
|
||||
by threads that don't own a lock on it result in
|
||||
<emphasis role="bold">undefined behavior</emphasis>.</para>
|
||||
|
||||
<para>Like all
|
||||
<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>
|
||||
|
||||
<inherit access="private">
|
||||
<type><classname>boost::noncopyable</classname></type>
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<typedef name="scoped_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<constructor>
|
||||
<effects>Constructs a <classname>recursive_mutex</classname> object.
|
||||
</effects>
|
||||
|
||||
<postconditions><code>*this</code> is in an unlocked state.
|
||||
</postconditions>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<effects>Destroys a <classname>recursive_mutex</classname> object.</effects>
|
||||
|
||||
<requires><code>*this</code> is in an unlocked state.</requires>
|
||||
|
||||
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
|
||||
locked mutex is a serious programming error resulting in undefined
|
||||
behavior such as a program crash.</notes>
|
||||
</destructor>
|
||||
</class>
|
||||
|
||||
<class name="recursive_try_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>recursive_try_mutex</classname> class is a model of the
|
||||
<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="thread.concepts.TryMutex">TryMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<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="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking mechanics, see <classname>mutex</classname>,
|
||||
<classname>try_mutex</classname>, and <classname>timed_mutex</classname>.
|
||||
</para>
|
||||
|
||||
<para>The <classname>recursive_try_mutex</classname> class supplies the following typedefs,
|
||||
which model the specified locking strategies:
|
||||
|
||||
<table>
|
||||
<title>Supported Lock Types</title>
|
||||
<tgroup cols="2" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Lock Name</entry>
|
||||
<entry>Lock Concept</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</para>
|
||||
|
||||
<para>The <classname>recursive_try_mutex</classname> class uses a
|
||||
<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.
|
||||
Attempts to unlock a <classname>recursive_mutex</classname> object
|
||||
by threads that don't own a lock on it result in
|
||||
<emphasis role="bold">undefined behavior</emphasis>.</para>
|
||||
|
||||
<para>Like all
|
||||
<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>
|
||||
|
||||
<inherit access="private">
|
||||
<type><classname>boost::noncopyable</classname></type>
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<typedef name="scoped_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<constructor>
|
||||
<effects>Constructs a <classname>recursive_try_mutex</classname> object.
|
||||
</effects>
|
||||
|
||||
<postconditions><code>*this</code> is in an unlocked state.
|
||||
</postconditions>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<effects>Destroys a <classname>recursive_try_mutex</classname> object.
|
||||
</effects>
|
||||
|
||||
<requires><code>*this</code> is in an unlocked state.</requires>
|
||||
|
||||
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
|
||||
locked mutex is a serious programming error resulting in undefined
|
||||
behavior such as a program crash.</notes>
|
||||
</destructor>
|
||||
</class>
|
||||
|
||||
<class name="recursive_timed_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>recursive_timed_mutex</classname> class is a model of the
|
||||
<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="thread.concepts.TimedMutex">TimedMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<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="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking mechanics, see <classname>mutex</classname>,
|
||||
<classname>try_mutex</classname>, and <classname>timed_mutex</classname>.
|
||||
</para>
|
||||
|
||||
<para>The <classname>recursive_timed_mutex</classname> class supplies the following typedefs,
|
||||
which model the specified locking strategies:
|
||||
|
||||
<table>
|
||||
<title>Supported Lock Types</title>
|
||||
<tgroup cols="2" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Lock Name</entry>
|
||||
<entry>Lock Concept</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
</para>
|
||||
|
||||
<para>The <classname>recursive_timed_mutex</classname> class uses a
|
||||
<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.
|
||||
Attempts to unlock a <classname>recursive_mutex</classname> object
|
||||
by threads that don't own a lock on it result in
|
||||
<emphasis role="bold">undefined behavior</emphasis>.</para>
|
||||
|
||||
<para>Like all
|
||||
<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>
|
||||
|
||||
<inherit access="private">
|
||||
<type><classname>boost::noncopyable</classname></type>
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<typedef name="scoped_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_timed_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<constructor>
|
||||
<effects>Constructs a <classname>recursive_timed_mutex</classname> object.
|
||||
</effects>
|
||||
|
||||
<postconditions><code>*this</code> is in an unlocked state.
|
||||
</postconditions>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<effects>Destroys a <classname>recursive_timed_mutex</classname> object.</effects>
|
||||
|
||||
<requires><code>*this</code> is in an unlocked state.</requires>
|
||||
|
||||
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
|
||||
locked mutex is a serious programming error resulting in undefined
|
||||
behavior such as a program crash.</notes>
|
||||
</destructor>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
@@ -1,327 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, BTL, thread library, C++">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<title>Boost.Threads, recursive_mutex</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">recursive_mutex<br>
|
||||
recursive_try_mutex<br>
|
||||
recursive_timed_mutex</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Header">Header</a><br>
|
||||
<a href="#recursive_mutex Synopsis">Class recursive_mutex Synopsis</a><br>
|
||||
<a href="#recursive_mutex Members">Class recursive_mutex Members</a><br>
|
||||
<a href="#recursive_try_mutex Synopsis">Class recursive_try_mutex Synopsis</a><br>
|
||||
<a href="#recursive_try_mutex Members">Class recursive_try_mutex Members</a><br>
|
||||
<a href="#recursive_timed_mutex Synopsis">Class recursive_timed_mutex Synopsis</a><br>
|
||||
<a href="#recursive_timed_mutex Members">Class recursive_timed_mutex Members</a><br>
|
||||
<a href="#Example">Example</a></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>The <code>recursive_mutex</code>, <code>recursive_try_mutex</code> and
|
||||
<code>recursive_timed_mutex</code> classes define full featured models of the
|
||||
<a href="mutex_concept.html#Mutex">Mutex</a>,
|
||||
<a href="mutex_concept.html#TryMutex">TryMutex</a> and
|
||||
<a href="mutex_concept.html#TimedMutex">TimedMutex</a> concepts with recursive locking
|
||||
semantics. These types should be used to synchronize access to shared resources
|
||||
when recursive locking by a single thread is likely to occur. A good example for this
|
||||
is when a class supplies "internal synchronization" to ensure
|
||||
<a href="definitions.html#Thread-safe">thread-safety</a> and a function of the class
|
||||
may have to call other functions of the class which also attempt to lock the mutex.
|
||||
For recursive locking mechanics, see <a href="mutex.html">mutexes</a>.
|
||||
|
||||
<p>Each class supplies one or more typedefs for lock types which model matching
|
||||
lock concepts. For the best possible performance you should use the mutex class that
|
||||
supports the minimum set of lock types that you need.</p>
|
||||
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<td><b>Mutex Class</b></td>
|
||||
<td><b>Lock name</b></td>
|
||||
<td><b>Implementation defined Lock Type</b></td>
|
||||
<td><b>Lock Concept</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><a href="#recursive_mutex Synopsis"><code>recursive_mutex</code></a></td>
|
||||
<td valign="middle"><code>scoped_lock</code></td>
|
||||
<td valign="middle"><a href="scoped_lock.html"><code>detail::thread::scoped_lock<recursive_mutex></code></a></td>
|
||||
<td valign="middle"><a href="lock_concept.html#ScopedLock">ScopedLock</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code><a href="#recursive_try_mutex Synopsis">recursive_try_mutex</a></code></td>
|
||||
<td valign="middle"><code>scoped_lock<br>
|
||||
scoped_try_lock</code></td>
|
||||
<td valign="middle"><a href="scoped_lock.html"><code>detail::thread::scoped_lock<recursive_try_mutex><br>
|
||||
</code></a><code><a href="scoped_try_lock.html">detail::thread::scoped_try_lock<recursive_try_mutex></a></code></td>
|
||||
<td valign="middle"><a href="lock_concept.html#ScopedLock">ScopedLock</a><br>
|
||||
<a href="lock_concept.html#ScopedTryLock">ScopedTryLock</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code><a href="#recursive_timed_mutex Synopsis">recursive_timed_mutex</a></code> </td>
|
||||
<td valign="middle"><code>scoped_lock<br>
|
||||
scoped_try_lock<br>
|
||||
scoped_timed_lock</code></td>
|
||||
<td valign="middle"><a href="scoped_lock.html"><code>detail::thread::scoped_lock<recursive_timed_mutex></code></a><br>
|
||||
<a href="scoped_try_lock.html"><code>detail::thread::scoped_try_lock<recursive_timed_mutex></code></a><br>
|
||||
<a href="scoped_timed_lock.html"><code>detail::thread::scoped_timed_lock<recursive_timed_mutex></code></a></td>
|
||||
<td valign="middle"><a href="lock_concept.html#ScopedLock">ScopedLock</a><br>
|
||||
<a href="lock_concept.html#ScopedTryLock">ScopedTryLock</a><br>
|
||||
<a href="lock_concept.html#ScopedTimedLock">ScopedTimedLock</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>The <code>recursive_mutex</code>, <code>recursive_try_mutex</code> and
|
||||
<code>recursive_timed_mutex</code> employ a <code>Recursive</code>
|
||||
<a href="mutex_concept.html#LockingStrategies">locking strategy</a>, so attempts to
|
||||
recursively lock them succeed and an internal "lock count" is maintained. Attempts
|
||||
to unlock them by a thread that does not own a lock on them will result in a
|
||||
<a href="lock_error.html">lock_error</a> exception being thrown.</p>
|
||||
|
||||
<p>The <code>recursive_mutex</code>, <code>recursive_try_mutex</code> and
|
||||
<code>recursive_timed_mutex</code> leave the
|
||||
<a href="mutex_concept.html#SchedulingPolicies">scheduling policy</a> as
|
||||
<code>Unspecified</code>. Programmers should assume that threads waiting for a lock on
|
||||
objects of these types acquire the lock in a random order, even though the specific
|
||||
behavior for a given platform may be different.</p>
|
||||
|
||||
<h2><a name="Header">Header</a></h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/recursive_mutex.hpp"><boost/thread/recursive_mutex.hpp></a>
|
||||
</pre>
|
||||
|
||||
<h2>Class <a name="recursive_mutex Synopsis"> recursive_mutex Synopsis</a></h2>
|
||||
|
||||
<hr>
|
||||
|
||||
<pre>
|
||||
namespace boost
|
||||
{
|
||||
class recursive_mutex : private <a href="../../utility/utility.htm">boost::noncopyable</a> // Exposition only.
|
||||
// Class recursive_mutex meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
|
||||
{
|
||||
public:
|
||||
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_lock;
|
||||
|
||||
recursive_mutex();
|
||||
~recursive_mutex();
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2>Class <a name="recursive_mutex Members">recursive_mutex Members</a></h2>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Constructor</h3>
|
||||
|
||||
<pre>
|
||||
recursive_mutex();
|
||||
</pre>
|
||||
|
||||
<p><b>Postconditions: </b><code>*this</code> is in the unlocked state.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Destructor</h3>
|
||||
|
||||
<pre>
|
||||
~recursive_mutex();
|
||||
</pre>
|
||||
|
||||
<p><b>Requires:</b> <code>*this</code> is in the unlocked state.</p>
|
||||
|
||||
<p><b>Effects:</b> Destroys <code>*this</code>.</p>
|
||||
|
||||
<p><b>Dangers:</b> Destruction of a locked mutex is a serious programming error
|
||||
resulting in undefined behavior such as a program crash..</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>
|
||||
Class <a name="recursive_try_mutex Synopsis">recursive_try_mutex Synopsis</a>
|
||||
</h2>
|
||||
|
||||
<pre>
|
||||
namespace boost
|
||||
{
|
||||
class recursive_try_mutex : private boost::noncopyable // Exposition only.
|
||||
// Class recursive_try_mutex meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
|
||||
{
|
||||
public:
|
||||
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_lock;
|
||||
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_try_lock;
|
||||
|
||||
recursive_try_mutex();
|
||||
~recursive_try_mutex();
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2>Class <a name="recursive_try_mutex Members">recursive_try_mutex Members</a></h2>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Constructor</h3>
|
||||
|
||||
<pre>
|
||||
recursive_try_mutex();
|
||||
</pre>
|
||||
|
||||
<p><b>Postconditions: </b><code>*this</code> is in the unlocked state.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Destructor</h3>
|
||||
|
||||
<pre>
|
||||
~recursive_try_mutex();
|
||||
</pre>
|
||||
|
||||
<p><b>Requires:</b> <code>*this</code> is in the unlocked state.</p>
|
||||
|
||||
<p><b>Effects:</b> Destroys <code>*this</code>.</p>
|
||||
|
||||
<p><b>Dangers:</b> Destruction of a locked mutex is a serious programming error
|
||||
resulting in undefined behavior such as a program crash..</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>
|
||||
Class <a name="recursive_timed_mutex Synopsis">recursive_timed_mutex Synopsis</a>
|
||||
</h2>
|
||||
|
||||
<pre>
|
||||
namespace boost
|
||||
{
|
||||
class recursive_timed_mutex : private boost::noncopyable // Exposition only.
|
||||
// Class recursive_timed_mutex meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
|
||||
{
|
||||
public:
|
||||
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_lock;
|
||||
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_try_lock;
|
||||
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_timed_lock;
|
||||
|
||||
recursive_timed_mutex();
|
||||
~recursive_timed_mutex();
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2>
|
||||
Class <a name="recursive_timed_mutex Members">recursive_timed_mutex Members</a>
|
||||
</h2>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Constructor</h3>
|
||||
|
||||
<pre>
|
||||
recursive_timed_mutex();
|
||||
</pre>
|
||||
|
||||
<p><b>Postconditions: </b><code>*this</code> is in the unlocked state.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Destructor</h3>
|
||||
|
||||
<pre>
|
||||
~recursive_timed_mutex();
|
||||
</pre>
|
||||
|
||||
<p><b>Requires:</b> <code>*this</code> is in the unlocked state.</p>
|
||||
|
||||
<p><b>Effects:</b> Destroys <code>*this</code>.</p>
|
||||
|
||||
<p><b>Dangers:</b> Destruction of a locked mutex is a serious programming error
|
||||
resulting in undefined behavior such as a program crash..</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="Example">Example</a> Usage</h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/recursive_mutex.hpp"><boost/thread/recursive_mutex.hpp></a>
|
||||
#include <a href="../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
||||
#include <iostream>
|
||||
|
||||
class counter
|
||||
{
|
||||
public:
|
||||
counter() : count(0) { }
|
||||
|
||||
int add(int val) {
|
||||
boost::recursive_mutex::scoped_lock scoped_lock(mutex);
|
||||
count += val;
|
||||
return count;
|
||||
}
|
||||
int increment() {
|
||||
boost::recursive_mutex::scoped_lock scoped_lock(mutex);
|
||||
return add(1);
|
||||
}
|
||||
|
||||
private:
|
||||
boost::recursive_mutex mutex;
|
||||
int count;
|
||||
};
|
||||
|
||||
counter c;
|
||||
|
||||
void change_count(void*)
|
||||
{
|
||||
std::cout << "count == " << c.increment() << std::endl;
|
||||
}
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
const int num_threads=4;
|
||||
|
||||
boost::thread_group threads;
|
||||
for (int i=0; i < num_threads; ++i)
|
||||
threads.create_thread(&change_count, 0);
|
||||
|
||||
threads.join_all();
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The output is:</p>
|
||||
|
||||
<pre>
|
||||
count == 1
|
||||
count == 2
|
||||
count == 3
|
||||
count == 4
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39334" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
24
doc/reference.xml
Normal file
24
doc/reference.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?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 % 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)
|
||||
-->
|
||||
<library-reference id="thread.reference"
|
||||
last-revision="$Date$"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<xi:include href="barrier-ref.xml"/>
|
||||
<xi:include href="condition-ref.xml"/>
|
||||
<xi:include href="exceptions-ref.xml"/>
|
||||
<xi:include href="mutex-ref.xml"/>
|
||||
<xi:include href="once-ref.xml"/>
|
||||
<xi:include href="recursive_mutex-ref.xml"/>
|
||||
<xi:include href="read_write_mutex-ref.xml"/>
|
||||
<xi:include href="thread-ref.xml"/>
|
||||
<xi:include href="tss-ref.xml"/>
|
||||
<xi:include href="xtime-ref.xml"/>
|
||||
</library-reference>
|
||||
148
doc/release_notes.xml
Normal file
148
doc/release_notes.xml
Normal file
@@ -0,0 +1,148 @@
|
||||
<?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 % 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.release_notes" last-revision="$Date$">
|
||||
<title>Release Notes</title>
|
||||
<section id="thread.release_notes.boost_1_32_0">
|
||||
<title>Boost 1.32.0</title>
|
||||
|
||||
<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,
|
||||
and a number of errors and inconsistencies were
|
||||
fixed in the process.
|
||||
Since this was a fairly large task, there are likely to be
|
||||
more errors and inconsistencies remaining. If you find any,
|
||||
please report them!</para>
|
||||
</section>
|
||||
|
||||
<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.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.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.Thread; users, this decision was reversed.</para>
|
||||
|
||||
<para>On non-Win32 platforms:
|
||||
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.
|
||||
If neither symbols is #defined, the default will be chosen.
|
||||
Currently the default is the statically linked version.</para>
|
||||
|
||||
<para>On Win32 platforms using VC++:
|
||||
Use the same #defines as for non-Win32 platforms
|
||||
(BOOST_THREAD_USE_DLL and BOOST_THREAD_USE_LIB).
|
||||
If neither is #defined, the default will be chosen.
|
||||
Currently the default is the statically linked version
|
||||
if the VC++ run-time library is set to
|
||||
"Multi-threaded" or "Multi-threaded Debug", and
|
||||
the dynamically linked version
|
||||
if the VC++ run-time library is set to
|
||||
"Multi-threaded DLL" or "Multi-threaded Debug DLL".</para>
|
||||
|
||||
<para>On Win32 platforms using compilers other than VC++:
|
||||
Use the same #defines as for non-Win32 platforms
|
||||
(BOOST_THREAD_USE_DLL and BOOST_THREAD_USE_LIB).
|
||||
If neither is #defined, the default will be chosen.
|
||||
Currently the default is the dynamically linked version
|
||||
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.Thread;.
|
||||
|
||||
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(),
|
||||
on_thread_enter(), and on_thread_exit(), and are defined
|
||||
in tls_hooks.cpp. See the comments in that file for more
|
||||
information.</para>
|
||||
</section>
|
||||
|
||||
<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="thread.release_notes.boost_1_32_0.change_log.read_write_mutex">
|
||||
<title>Read/write mutex functionality added</title>
|
||||
|
||||
<para>New classes,
|
||||
<classname>boost::read_write_mutex</classname>,
|
||||
<classname>boost::try_read_write_mutex</classname>, and
|
||||
<classname>boost::timed_read_write_mutex</classname>
|
||||
were added.
|
||||
|
||||
<note>Since the read/write mutex and related classes are new,
|
||||
both interface and implementation are liable to change
|
||||
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="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>
|
||||
constructor now takes an optional pointer to a cleanup function that
|
||||
is called to release the thread-specific data that is being pointed
|
||||
to by <classname>boost::thread_specific_ptr</classname> objects.</para>
|
||||
|
||||
<para>Fixed: the number of available thread-specific storage "slots"
|
||||
is too small on some platforms.</para>
|
||||
|
||||
<para>Fixed: <functionname>thread_specific_ptr::reset()</functionname>
|
||||
doesn't check error returned by <functionname>tss::set()</functionname>
|
||||
(the <functionname>tss::set()</functionname> function now throws
|
||||
if it fails instead of returning an error code).</para>
|
||||
|
||||
<para>Fixed: calling
|
||||
<functionname>boost::thread_specific_ptr::reset()</functionname> or
|
||||
<functionname>boost::thread_specific_ptr::release()</functionname>
|
||||
causes double-delete: once when
|
||||
<functionname>boost::thread_specific_ptr::reset()</functionname> or
|
||||
<functionname>boost::thread_specific_ptr::release()</functionname>
|
||||
is called and once when
|
||||
<functionname>boost::thread_specific_ptr::~thread_specific_ptr()</functionname>
|
||||
is called.</para>
|
||||
</section>
|
||||
|
||||
<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>,
|
||||
<classname>boost::try_mutex</classname>, <classname>boost::recursive_mutex</classname>,
|
||||
and <classname>boost::recursive_try_mutex</classname> now use a Win32 critical section
|
||||
whenever possible; otherwise they use a Win32 mutex. As before,
|
||||
<classname>boost::timed_mutex</classname> and
|
||||
<classname>boost::recursive_timed_mutex</classname> use a Win32 mutex.</para>
|
||||
</section>
|
||||
|
||||
<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.Thread work on Windows CE.</para>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
@@ -1,134 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, BTL, thread library, C++">
|
||||
<title>Boost.Threads, atomic_t</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">atomic_t</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>Header</h2>
|
||||
|
||||
<p>The <tt>atomic_t</tt> class defines an "atomic integer" type. This class should be used
|
||||
to perform thread safe operations on an integral type with out the overhead of locks. Only
|
||||
a limited set of integer operations are available with an <tt>atomic_t</tt> instance.</p>
|
||||
|
||||
<pre>
|
||||
#include <boost/thread/atomic.hpp>
|
||||
</pre>
|
||||
|
||||
<h2>Public Interface</h2>
|
||||
|
||||
<pre>
|
||||
class atomic_t
|
||||
{
|
||||
public:
|
||||
typedef <b>implementation defined</b> value_type;
|
||||
|
||||
explicit atomic_t(value_type val=0);
|
||||
};
|
||||
|
||||
atomic_t::value_type read(const atomic_t& x);
|
||||
atomic_t::value_type increment(atomic_t& x);
|
||||
atomic_t::value_type decrement(atomic_t& x);
|
||||
atomic_t::value_type swap(atomic_t& x, atomic_t::value_type y);
|
||||
atomic_t::value_type compare_swap(atomic_t& x, atomic_t::value_type y, atomic_t::value_type z);
|
||||
</pre>
|
||||
|
||||
<h3>Constructor</h3>
|
||||
|
||||
<pre>
|
||||
atomic_t(atomic_t::value_type val=0);
|
||||
</pre>
|
||||
|
||||
<p>Constructs an <tt>atomic_t</tt> and sets its value to <tt>val</tt>.</p>
|
||||
|
||||
<h3>read</h3>
|
||||
|
||||
<pre>
|
||||
atomic_t::value_type read(const atomic_t& x);
|
||||
</pre>
|
||||
|
||||
<p>Gets the current value of <tt>x</tt>.</p>
|
||||
|
||||
<h3>increment</h3>
|
||||
|
||||
<pre>
|
||||
atomic_t::value_type increment(atomic_t& x);
|
||||
</pre>
|
||||
|
||||
<p>Increments <tt>x</tt> and returns a value <tt>< 0</tt> if the result is less than 0,
|
||||
<tt>> 0</tt> if the result is greater than 0 and <tt>== 0</tt> if the result is equal to
|
||||
0.</p>
|
||||
|
||||
<h3>decrement</h3>
|
||||
|
||||
<pre>
|
||||
atomic_t::value_type decrement(atomic_t& x);
|
||||
</pre>
|
||||
|
||||
<p>Decrements <tt>x</tt> and returns a value <tt>< 0</tt> if the result is less than 0,
|
||||
<tt>> 0</tt> if the result is greater than 0 and <tt>== 0</tt> if the result is equal to
|
||||
0.</p>
|
||||
|
||||
<h3>swap</h3>
|
||||
|
||||
<pre>
|
||||
atomic_t::value_type swap(atomic_t& x, atomic_t::value_type y);
|
||||
</pre>
|
||||
|
||||
<p>Assigns the value of <tt>y</tt> to <tt>x</tt> and returns the value of <tt>x</tt> prior
|
||||
to the swap.</p>
|
||||
|
||||
<h3>compare_swap</h3>
|
||||
|
||||
<pre>
|
||||
atomic_t::value_type compare_swap(atomic_t& x, atomic_t::value_type y, atomic_t::value_type z);
|
||||
</pre>
|
||||
|
||||
<p>Compares the value of <tt>z</tt> to the value of <tt>x</tt> and if equal sets the value of
|
||||
<tt>x</tt> to the value of <tt>y</tt> and returns the value of <tt>x</tt> prior to the swap.</p>
|
||||
|
||||
<h2>Example Usage</h2>
|
||||
|
||||
<pre>
|
||||
#include <boost/thread/atomic.hpp>
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
int test_main(int, char*[])
|
||||
{
|
||||
boost::atomic_t a;
|
||||
BOOST_TEST_VERIFY(boost::read(a) == 0);
|
||||
BOOST_TEST_VERIFY(boost::increment(a) > 0);
|
||||
BOOST_TEST_VERIFY(boost::decrement(a) == 0);
|
||||
BOOST_TEST_VERIFY(boost::swap(a, 1) == 0);
|
||||
BOOST_TEST_VERIFY(boost::swap(a, 2, 0) == 1);
|
||||
BOOST_TEST_VERIFY(boost::read(a) == 1);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->06 August, 2001<!--webbot bot="Timestamp" endspan i-checksum="34352" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,213 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, BTL, thread library, C++">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<title>Boost.Threads, scoped_lock</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">scoped_lock</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Header">Header</a><br>
|
||||
<a href="#Synopsis">Synopsis</a><br>
|
||||
<a href="#Members">Members</a><br>
|
||||
<a href="#Example">Example</a></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>This class template defines a generic lock type which meets the
|
||||
<a href="lock_concept.html#ScopedLock">ScopedLock</a> requirements. The
|
||||
<a href="mutex.html">mutex</a>, <a href="mutex.html">try_mutex</a>,
|
||||
<a href="mutex.html">timed_mutex</a>, <a href="recursive_mutex.html">recursive_mutex</a>,
|
||||
<a href="recursive_mutex.html">recursive_try_mutex</a> and
|
||||
<a href="recursive_mutex.html">recursive_timed_mutex</a> classes all use this template
|
||||
to define their <code>scoped_lock</code> types.</p>
|
||||
|
||||
<p>Like all the <b>Boost.Threads</b> <a href="lock_concept.html">lock models</a>,
|
||||
<code>scoped_lock</code> objects are meant to be short-lived. Objects of the class
|
||||
are not <a href="definitions.html#thread-safe">thread-safe</a>, and so should not be
|
||||
shared between threads.</p>
|
||||
|
||||
<p>Class <code> scoped_lock</code> follows the "resource acquisition is
|
||||
initialization" idiom <a href="bibliography.html#Stroustrup-00">[Stroustrup
|
||||
00 14.4.1]</a> and is a realization of the "Scoped Locking Pattern"
|
||||
<a href="bibliography.html#Schmidt-00">[Schmidt-00]</a>. Thus the usage is to let the
|
||||
constructor do the locking, and then let the destructor do the unlocking automatically at
|
||||
the end of the enclosing scope. The lock() and unlock() members are usually not
|
||||
explicitly called, but are provided to allow for complex overlapping locks of multiple
|
||||
mutexes.</p>
|
||||
|
||||
<p>The type used to instantiate the class must meet the
|
||||
<a href="mutex_concept.html#Mutex">Mutex</a> requirements.</p>
|
||||
|
||||
<p>Although this class is an implementation detail, it is publicly documented here because
|
||||
of its importance.</p>
|
||||
|
||||
<h2><a name="Header">Header</a></h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/detail/lock.hpp"><boost/thread/detail/lock.hpp></a>
|
||||
<i>This header is usually not included directly by programmers
|
||||
because it is supplied by <a href="../../../boost/thread/mutex.hpp"><boost/thread/mutex.hpp></a> or
|
||||
<a href="../../../boost/thread/recursive_mutex.hpp"><boost/thread/recursive_mutex.hpp></a></i>
|
||||
</pre>
|
||||
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
|
||||
<pre>
|
||||
namespace boost { namespace detail { namespace thread {
|
||||
template <typename Mutex>
|
||||
class scoped_lock : private <a href="../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
|
||||
// Class scoped_lock meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
|
||||
{
|
||||
public:
|
||||
typedef Mutex mutex_type;
|
||||
|
||||
explicit scoped_lock(Mutex& mx, bool initially_locked=true);
|
||||
~scoped_lock();
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
|
||||
operator const void*() const;
|
||||
bool locked() const;
|
||||
};
|
||||
} // namespace thread
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
</pre>
|
||||
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Constructor</h3>
|
||||
|
||||
<pre>
|
||||
explicit scoped_lock(Mutex& mx, bool initially_locked=true);
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> Associates mutex <code>mx</code> with <code>*this</code>.
|
||||
If <code>initially_locked</code> is <code>true,</code> calls <code>lock()</code>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Destructor</h3>
|
||||
|
||||
<pre>
|
||||
~scoped_lock();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> If <code> locked()</code>, calls <code>unlock()</code>. Destroys
|
||||
<code>*this</code>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>lock</h3>
|
||||
|
||||
<pre>
|
||||
void lock();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> If the associated mutex is already locked by another lock in the
|
||||
current thread, the effects depend on the locking strategy of the associated mutex, as
|
||||
shown in the following table:</p>
|
||||
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<td><i><a href="mutex_concept.html#LockingStrategies">Locking Strategy</a><br>
|
||||
of associated mutex</i></td>
|
||||
<td><i>Effect if associated mutex is already locked by the current thread</i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Recursive</td>
|
||||
<td>As if an additional lock were added to the mutex.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Checked</td>
|
||||
<td>Throws <a href="lock_error.html">lock_error</a>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Unchecked</td>
|
||||
<td>Undefined behavior [<a href="bibliography.html#ISO">ISO</a> 1.3.12] (but
|
||||
typically, <a href="definitions.html#Deadlock">deadlock</a>.)</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>If the associated mutex is already locked by some other thread, places the
|
||||
current thread in the <a href="definitions.html#State">Blocked</a> state until
|
||||
the associated mutex is unlocked, after which the current thread is placed in
|
||||
the <a href="definitions.html#State">Ready</a> state, eventually to be returned
|
||||
to the <a href="definitions.html#State">Running</a> state.
|
||||
|
||||
<p><b>Postcondition:</b> locked()
|
||||
|
||||
<p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>locked()</code> or
|
||||
as indicated in <b>Effects</b>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>unlock</h3>
|
||||
|
||||
<pre>
|
||||
void unlock();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects: </b>Unlocks the associated mutex.</p>
|
||||
|
||||
<p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>!locked()</code>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>const void* Conversion</h3>
|
||||
|
||||
<pre>
|
||||
operator const void*() const;
|
||||
</pre>
|
||||
|
||||
<p><b>Returns:</b> If the associated mutex is currently locked, a value convertible to
|
||||
<code>true</code>, else a value convertible to <code>false</code>.</p>
|
||||
|
||||
<p><b>Rationale:</b> A <code>const void*</code> conversion is considered safer than a
|
||||
conversion to <code>bool</code>.</p>
|
||||
|
||||
<hr>
|
||||
<h3>locked</h3>
|
||||
<pre>
|
||||
bool locked() const;
|
||||
</pre>
|
||||
<p><b>Returns:</b> <code>this->operator const void*() != 0</code>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="Example">Example</a> Usage</h2>
|
||||
|
||||
<p>See the example given in the documentation for the <a href="mutex.html">mutex</a>
|
||||
class.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39334" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,261 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, BTL, thread library, C++">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<title>Boost.Threads, scoped_timed_lock</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">scoped_timed_lock</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Header">Header</a><br>
|
||||
<a href="#Synopsis">Synopsis</a><br>
|
||||
<a href="#Members">Members</a><br>
|
||||
<a href="#Example">Example</a></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>This class template defines a generic lock type which meets the
|
||||
<a href="lock_concept.html#ScopedTimedLock">ScopedTimedLock</a> requirements. The
|
||||
<a href="mutex.html">timed_mutex</a> and
|
||||
<a href="recursive_mutex.html">recursive_timed_mutex</a> classes use this template to
|
||||
define their <code>scoped_timed_lock</code> types.</p>
|
||||
|
||||
<p>Like all the <b>Boost.Threads</b> <a href="lock_concept.html">lock models</a>,
|
||||
<code>scoped_timed_lock</code> objects are meant to be short-lived. Objects of the
|
||||
class are not <a href="definitions.html#thread-safe">thread-safe</a>, and so should
|
||||
not be shared between threads.</p>
|
||||
|
||||
<p>Class <code>scoped_timed_lock</code> follows the "resource acquisition is
|
||||
initialization" idiom <a href="bibliography.html#Stroustrup-00">[Stroustrup
|
||||
00 14.4.1]</a> and is a realization of the "Scoped Locking Pattern"
|
||||
<a href="bibliography.html#Schmidt-00">[Schmidt-00]</a>. Thus the usage is to let the
|
||||
constructor do the locking, and then let the destructor do the unlocking automatically
|
||||
at the end of the enclosing scope. The lock() and unlock() members are usually not
|
||||
explicitly called, but are provided to allow for complex overlapping locks of multiple
|
||||
mutexes.</p>
|
||||
|
||||
<p>The type used to instantiate the class must meet the
|
||||
<a href="mutex_concept.html#TimedMutex">TimedMutex</a> requirements.</p>
|
||||
|
||||
<p>Although this class is an implementation detail, it is publicly documented here because
|
||||
of its importance.</p>
|
||||
|
||||
<h2><a name="Header">Header</a></h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/detail/lock.hpp"><boost/thread/detail/lock.hpp></a>
|
||||
<i>This header is usually not included directly by programmers
|
||||
because it is supplied by <a href="../../../boost/thread/mutex.hpp"><boost/thread/mutex.hpp></a> or
|
||||
<a href="../../../boost/thread/recursive_mutex.hpp"><boost/thread/recursive_mutex.hpp></a></i>
|
||||
</pre>
|
||||
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
|
||||
<pre>
|
||||
namespace boost { namespace detail { namespace thread {
|
||||
template <typename TimedMutex>
|
||||
class scoped_timed_lock : private <a href="../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
|
||||
// Class scoped_timed_lock meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
|
||||
{
|
||||
public:
|
||||
typedef TimedMutex mutex_type;
|
||||
|
||||
scoped_timed_lock(TimedMutex& mx, const boost::xtime& xt);
|
||||
scoped_timed_lock(TimedMutex& mx, bool initially_locked);
|
||||
~scoped_timed_lock();
|
||||
|
||||
void lock();
|
||||
bool timed_lock(const xtime& xt);
|
||||
void unlock();
|
||||
|
||||
operator const void*() const;
|
||||
};
|
||||
} // namespace thread
|
||||
} // namesapce detail
|
||||
} // namespace boost
|
||||
</pre>
|
||||
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Constructor</h3>
|
||||
|
||||
<pre>
|
||||
scoped_timed_lock(TimedMutex& mx, const <a href="xtime.html">xtime</a>& xt);
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> Associates mutex <code>mx</code> with <code>*this</code>.
|
||||
Calls <code>timed_lock</code>( <code>xt</code>)</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<pre>
|
||||
scoped_timed_lock(TimedMutex& mx, bool initially_locked);
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> Associates mutex <code>mx</code> with <code>*this</code>.
|
||||
If <code>initially_locked</code> is <code>true</code>, calls <code>lock()</code>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Destructor</h3>
|
||||
|
||||
<pre>
|
||||
~scoped_timed_lock();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> If <code> locked()</code>, calls <code>unlock()</code>. Destroys
|
||||
<code>*this</code>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>lock</h3>
|
||||
|
||||
<pre>
|
||||
void lock();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> If the associated mutex is already locked by another lock in the
|
||||
current thread, the effects depend on the locking strategy of the associated mutex, as
|
||||
shown in the following table:</p>
|
||||
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<td><i><a href="mutex_concept.html#LockingStrategies">Locking Strategy</a><br>
|
||||
of associated mutex</i></td>
|
||||
<td><i>Effect if associated mutex is already locked by the current thread</i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Recursive</td>
|
||||
<td>As if an additional lock were added to the mutex.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Checked</td>
|
||||
<td>Throws <a href="lock_error.html">lock_error</a>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Unchecked</td>
|
||||
<td>Undefined behavior [<a href="bibliography.html#ISO">ISO</a> 1.3.12] (but
|
||||
typically, <a href="definitions.html#Deadlock">deadlock</a>.)</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>If the associated mutex is already locked by some other thread, places the
|
||||
current thread in the <a href="definitions.html#State">Blocked</a> state until
|
||||
the associated mutex is unlocked, after which the current thread is placed in
|
||||
the <a href="definitions.html#State">Ready</a> state, eventually to be returned
|
||||
to the <a href="definitions.html#State">Running</a> state. Places the associated
|
||||
mutex in the locked state.
|
||||
|
||||
<p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>locked()</code> or
|
||||
as indicated in <b>Effects</b>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>timed_lock</h3>
|
||||
|
||||
<pre>
|
||||
bool timed_lock(const <a href="xtime.html">xtime</a>& xt);
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> Same as <code>lock()</code>, except that if xt is reached,
|
||||
places the current thread in the <a href="definitions.html#State">Ready</a>
|
||||
state without further ado.</p>
|
||||
|
||||
<p><b>Returns:</b> <code>locked()</code>.</p>
|
||||
|
||||
<p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>locked()</code> or
|
||||
as indicated in <b>Effects</b>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>unlock</h3>
|
||||
|
||||
<pre>
|
||||
void unlock();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects: </b>Unlocks the associated mutex.</p>
|
||||
|
||||
<p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>!locked()</code>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>const void* Conversion</h3>
|
||||
|
||||
<pre>
|
||||
operator const void*() const;
|
||||
</pre>
|
||||
|
||||
<p><b>Returns:</b> If the associated mutex is currently locked, a value convertible to
|
||||
<code>true</code>, else a value convertible to <code>false</code>.</p>
|
||||
|
||||
<p><b>Rationale:</b> A <code>const void*</code> conversion is considered safer than a
|
||||
conversion to <code>bool</code>.</p>
|
||||
|
||||
<hr>
|
||||
<h3>locked</h3>
|
||||
|
||||
<pre>
|
||||
bool locked() const;
|
||||
</pre>
|
||||
|
||||
<p><b>Returns:</b> <code>this->operator const void*() != 0</code>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="Example">Example</a> Usage</h2>
|
||||
|
||||
<pre>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <iostream>
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
boost::timed_mutex mutex;
|
||||
boost::xtime xt;
|
||||
boost::get_xtime(&xt, boost::TIME_UTC);
|
||||
xt.sec += 1;
|
||||
boost::mutex::scoped_timed_lock scope_timed_lock(mutex, xt);
|
||||
if (scope_timed_lock.locked())
|
||||
std::cout << "locked" << std::endl;
|
||||
else
|
||||
std::cout << "unlocked" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The output is:</p>
|
||||
|
||||
<pre>
|
||||
locked
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%B %d, %Y" startspan -->September 13, 2001<!--webbot bot="Timestamp" endspan i-checksum="37965" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,282 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, BTL, thread library, C++">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<title>Boost.Threads, scoped_try_lock</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">scoped_try_lock</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Header">Header</a><br>
|
||||
<a href="#Synopsis">Synopsis</a><br>
|
||||
<a href="#Members">Members</a><br>
|
||||
<a href="#Example">Example</a></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>This class template defines a generic lock type which meets the
|
||||
<a href="lock_concept.html#ScopedTryLock">ScopedTryLock</a> requirements. The
|
||||
<a href="mutex.html">try_mutex</a>, <a href="mutex.html">timed_mutex</a>,
|
||||
<a href="recursive_mutex.html">recursive_try_mutex</a> and
|
||||
<a href="recursive_mutex.html">recursive_timed_mutex</a> classes use this template
|
||||
to define their <code>scoped_try_lock</code> types.</p>
|
||||
|
||||
<p>Like all the <b>Boost.Threads</b> <a href="lock_concept.html">lock models</a>,
|
||||
<code>scoped_try_lock</code> objects are meant to be short-lived. Objects of the
|
||||
class are not <a href="definitions.html#thread-safe">thread-safe</a>, and
|
||||
so should not be shared between threads.</p>
|
||||
|
||||
<p>Class <code> scoped_try_lock</code> follows the "resource acquisition is
|
||||
initialization" idiom <a href="bibliography.html#Stroustrup-00">[Stroustrup
|
||||
00 14.4.1]</a> and is a realization of the "Scoped Locking Pattern"
|
||||
<a href="bibliography.html#Schmidt-00">[Schmidt-00]</a>. Thus the usage is to let the
|
||||
constructor do the locking, and then let the destructor do the unlocking automatically at
|
||||
the end of the enclosing scope. The lock() and unlock() members are usually not
|
||||
explicitly called, but are provided to allow for complex overlapping locks of multiple
|
||||
mutexes.</p>
|
||||
|
||||
<p>Although this class is an implementation detail, it is publicly documented here because
|
||||
of its importance.</p>
|
||||
|
||||
<p>The type used to instantiate the class must meet the <a href="mutex_concept.html#TryMutex">TryMutex</a> requirements.</p>
|
||||
|
||||
<h2><a name="Header">Header</a></h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/detail/lock.hpp"><boost/thread/detail/lock.hpp></a>
|
||||
<i>This header is usually not included directly by programmers
|
||||
because it is supplied by <a href="../../../boost/thread/mutex.hpp"><boost/thread/mutex.hpp></a> or
|
||||
<a href="../../../boost/thread/recursive_mutex.hpp"><boost/thread/recursive_mutex.hpp></a></i>
|
||||
</pre>
|
||||
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
|
||||
<pre>
|
||||
namespace boost { namespace detail { namespace thread {
|
||||
template <typename TryMutex>
|
||||
class scoped_try_lock : private <a href="../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
|
||||
// Class scoped_try_lock meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
|
||||
{
|
||||
public:
|
||||
typedef TryMutex mutex_type;
|
||||
|
||||
explicit scoped_try_lock(TryMutex& mx);
|
||||
scoped_try_lock(TryMutex& mx, bool initially_locked);
|
||||
~scoped_try_lock();
|
||||
|
||||
void lock();
|
||||
bool try_lock();
|
||||
void unlock();
|
||||
|
||||
operator const void*() const;
|
||||
};
|
||||
} // namespace thread
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
</pre>
|
||||
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Constructors</h3>
|
||||
|
||||
<pre>
|
||||
explicit scoped_try_lock(TryMutex& mx);
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> Associates mutex <code>mx</code> with <code>*this</code>.
|
||||
Calls <code>try_lock()</code>.</p>
|
||||
|
||||
<hr>
|
||||
<pre>
|
||||
scoped_try_lock(TryMutex& mx, bool initially_locked);
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> Associates mutex <code>mx</code> with <code>*this</code>.
|
||||
If <code>initially_locked</code> is <code>true,</code> calls <code>lock()</code>.</p>
|
||||
<hr>
|
||||
|
||||
<h3>Destructor</h3>
|
||||
|
||||
<pre>
|
||||
~scoped_try_lock();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> If <code>locked()</code>, calls <code>unlock()</code>. Destroys
|
||||
<code>*this</code>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>lock</h3>
|
||||
|
||||
<pre>
|
||||
void lock();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> If the associated mutex is already locked by another lock in the
|
||||
current thread, the effects depend on the locking strategy of the associated mutex, as
|
||||
shown in the following table:</p>
|
||||
|
||||
<table border="1" cellpadding="5" height="147">
|
||||
<tr>
|
||||
<td height="34"><i><a href="mutex_concept.html#LockingStrategies">Locking Strategy</a><br>
|
||||
of associated mutex</i></td>
|
||||
<td height="34"><i>Effect if associated mutex is already locked by the
|
||||
current thread</i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td height="19">Recursive</td>
|
||||
<td height="19">As if an additional lock were added to the mutex.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td height="19">Checked</td>
|
||||
<td height="19">Throws <a href="lock_error.html">lock_error</a>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td height="19">Unchecked</td>
|
||||
<td height="19">Undefined behavior [<a href="bibliography.html#ISO">ISO</a> 1.3.12] (but
|
||||
typically, <a href="definitions.html#Deadlock">deadlock</a>.)</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>If the associated mutex is already locked by some other thread, places the
|
||||
current thread in the <a href="definitions.html#State">Blocked</a> state until
|
||||
the associated mutex is unlocked, after which the current thread is placed in
|
||||
the <a href="definitions.html#State">Ready</a> state, eventually to be returned
|
||||
to the <a href="definitions.html#State">Running</a> state. Places the associated
|
||||
mutex in the locked state.</p>
|
||||
|
||||
<p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>locked()</code> or
|
||||
as indicated in <b>Effects</b>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>try_lock</h3>
|
||||
|
||||
<pre>
|
||||
bool try_lock();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> If the associated mutex is already locked by another lock in the
|
||||
current thread, the effects depend on the locking strategy of the associated mutex, as
|
||||
shown in the following table:</p>
|
||||
|
||||
<table border="1" cellpadding="5" height="147">
|
||||
<tr>
|
||||
<td height="34"><i><a href="mutex_concept.html#LockingStrategies">Locking Strategy</a><br>
|
||||
of associated mutex</i></td>
|
||||
<td height="34"><i>Effect if associated mutex is already locked by the
|
||||
current thread</i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td height="19">Recursive</td>
|
||||
<td height="19">As if an additional lock were added to the mutex.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td height="19">Checked</td>
|
||||
<td height="19">Throws <a href="lock_error.html">lock_error</a>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td height="19">Unspecified</td>
|
||||
<td height="19">Undefined behavior [<a href="bibliography.html#ISO">ISO</a> 1.3.12] (but
|
||||
typically, <a href="definitions.html#Deadlock">deadlock</a>.)</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>If the associated mutex is not already locked by some other thread, locks the
|
||||
associated mutex and returns true, else returns false.</p>
|
||||
|
||||
<p><b>Returns:</b> See effects.</p>
|
||||
|
||||
<p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>locked()</code> or
|
||||
as indicated in <b>Effects</b>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>unlock</h3>
|
||||
|
||||
<pre>
|
||||
void unlock();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects: </b>Unlocks the associated mutex.</p>
|
||||
|
||||
<p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>!locked()</code>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>const void* Conversion</h3>
|
||||
|
||||
<pre>
|
||||
operator const void*() const;
|
||||
</pre>
|
||||
|
||||
<p><b>Returns:</b> If the associated mutex is currently locked, a value convertible to
|
||||
<code>true</code>, else a value convertible to <code>false</code>.</p>
|
||||
|
||||
<p><b>Rationale:</b> A <code>const void*</code> conversion is considered safer
|
||||
than a conversion to <code>bool</code>.</p>
|
||||
|
||||
<hr>
|
||||
<h3>locked</h3>
|
||||
|
||||
<pre>
|
||||
bool locked() const;
|
||||
</pre>
|
||||
|
||||
<p><b>Returns:</b> <code>this->operator const void*() != 0</code>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="Example">Example</a> Usage</h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/mutex.hpp"><boost/thread/mutex.hpp></a>
|
||||
#include <iostream>
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
boost::mutex mutex;
|
||||
boost::mutex::try_lock lock(mutex);
|
||||
if (lock)
|
||||
std::cout << "locked" << std::endl;
|
||||
else
|
||||
std::cout << "unlocked" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The output is:</p>
|
||||
|
||||
<pre>
|
||||
locked
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39334" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,226 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, BTL, thread library, C++">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<title>Boost.Threads, semaphore</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><IMG height=86 alt="C++ Boost" src="../../../c++boost.gif" width=277></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">semaphore</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Header">Header</a><br>
|
||||
<a href="#Synopsis">Synopsis</a><br>
|
||||
<a href="#Members">Members</a><br>
|
||||
<a href="#Example">Example</a></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>The <tt>semaphore</tt> class defines a classic synchronization primitive invented by the
|
||||
Dutch computer scientist Edsger W. Dijkstra. A semaphore manages an internal counter. This
|
||||
counter never goes below zero, or above a specified maximum value. When calling
|
||||
<tt>semaphore::down</tt> the calling thread will block until the value is non-zero and then
|
||||
decrement the value in a single atomic operation. When calling <tt>semaphore::up</tt> the
|
||||
calling thread will increment the value in a single atomic operation, failing if the value has
|
||||
already reached the specified maximum.</p>
|
||||
|
||||
<p><b>Rationale:</b> The semaphore is the simplest synchronization primitive available and is generally the
|
||||
primitive used to build other synchronization concepts at some level of implementation. For this
|
||||
reason <b>Boost.Threads</b> defines the <tt>semaphore</tt> type in the classic form. This simplifies
|
||||
usage and implementation, but it means that the interface is not as safe as other <b>Boost.Threads</b>
|
||||
interfaces.</p>
|
||||
|
||||
<p><b><a name="Danger">Danger</a>:</b> Unlike the <A href="mutex_concept.html">mutex models</a> supplied by <b>Boost.Threads,</b>
|
||||
there is no <A href="lock_concept.html">lock_concept</a> for the semaphore to help ensure proper
|
||||
usage. Great care must be taken when using a <tt>semaphore</tt> object to ensure
|
||||
<a href="definitions.html#Deadlock"> deadlock</a> or <a href="definitions.html#Race condition">race conditions</a> do not occur. </p>
|
||||
|
||||
<p>The dangers are spelled out by <a href="bibliography.html#Andrews-83">[Andrews-83]</a>
|
||||
(function names updated, see historical note below): </p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p>Although semaphores can be used to program almost any kind of synchronization,
|
||||
<b>down()</b> and <b>up()</b> are rather unstructured primitives, and so it is easy to err when using them. Execution of each critical section must begin with a
|
||||
<b>down()</b> and end with a <b>up()</b> (on the same semaphore). Omitting a <b>down()</b>
|
||||
or <b>up()</b>, or accidentally coding a <b>down()</b> on one semaphore and a <b>up()</b>
|
||||
on another can have disastrous effects, since mutually exclusive execution would no longer be ensured. Also, when using semaphores, a programmer can forget to include in critical sections all statements that reference shared objects. This, too, could destroy the mutual exclusion required within critical sections. A second difficulty with using semaphores is that both condition synchronization and mutual exclusion are programmed using the same pair of primitives. This makes it difficult to identify the purpose of a given
|
||||
<b>down()</b> or <b>up()</b> operation without looking at the other operations on the corresponding semaphore. Since mutual exclusion and condition synchronization are distinct concepts, they should have distinct notations.</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<p><b>Historical note: </b>Dijkstra's original name for <b>down()</b> was <b>P</b>
|
||||
(short for the Dutch "passeren", "to pass"), and for <b>up()</b>
|
||||
was <b>V</b> (short for the Dutch "vrygeven", "to release").</p>
|
||||
|
||||
<h2><a name="Header">Header</a></h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/semaphore.hpp"><boost/thread/semaphore.hpp></a>
|
||||
</pre>
|
||||
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
|
||||
<pre>
|
||||
namespace boost
|
||||
{
|
||||
class semaphore : private <a href="../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
|
||||
// Class semaphore meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
|
||||
{
|
||||
public:
|
||||
explicit semaphore(unsigned count=0, unsigned max=0);
|
||||
~semaphore();
|
||||
|
||||
bool up(unsigned count=1, unsigned* prev=0);
|
||||
void down();
|
||||
bool down(const xtime& xt);
|
||||
private:
|
||||
unsigned m_count; <i>exposition only [ISO 17.3.2.3/2]
|
||||
</i> unsigned m_max; <i>exposition only [ISO 17.3.2.3/2]</i>
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Constructor</h3>
|
||||
|
||||
<pre>
|
||||
explicit semaphore(unsigned count=0, unsigned max=0);
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> As if:</p>
|
||||
|
||||
<p><code> m_count = count;<br>
|
||||
m_max = (max == 0 ? std::numeric_limits<unsigned>::max()
|
||||
? max );</code></p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Destructor</h3>
|
||||
|
||||
<pre>
|
||||
~semaphore();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> Destroys <code>*this</code>.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>up</h3>
|
||||
|
||||
<pre>
|
||||
bool up(unsigned count=1, unsigned* prev=0);
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> As if:</p>
|
||||
|
||||
<p><code> unsigned ct;<br>
|
||||
bool ret;<br>
|
||||
{ // as a single atomic operation:<br>
|
||||
ct = m_count;<br>
|
||||
if (m_count == m_max) ret =
|
||||
false;<br>
|
||||
else<br>
|
||||
{<br>
|
||||
ret =
|
||||
true;<br>
|
||||
++m_count;<br>
|
||||
}<br>
|
||||
}<br>
|
||||
if (prev) *prev = m_count;<br>
|
||||
return ret;</code></p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>down</h3>
|
||||
|
||||
<pre>
|
||||
void down();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> If <code>m_count == 0</code>, places the current thread in
|
||||
the <a href="definitions.html#State">blocked</a> state until <code>m_count != 0</code>.
|
||||
Finally, <code>--m_count</code>.<code> </code></p>
|
||||
|
||||
<hr>
|
||||
|
||||
<pre>
|
||||
bool down(const <a href="xtime.html">xtime</a>& xt);
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> If <code>m_count == 0</code>, places the current thread in
|
||||
the <a href="definitions.html#State">blocked</a> state until <code>m_count != 0</code>
|
||||
or <code>xt</code> is reached. Finally, <code>--m_count</code>.<code> </code></p>
|
||||
|
||||
<p><b>Returns:</b> If xt was reached, true, else false.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="Example">Example</a> Usage</h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/semaphore.hpp"><boost/thread/semaphore.hpp></a>
|
||||
#include <a href="../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
||||
#include <iostream>
|
||||
|
||||
int global_data = 0;
|
||||
boost::semaphore global_semaphore(1);
|
||||
|
||||
void change_global_data(void*)
|
||||
{
|
||||
global_semaphore.down();
|
||||
++global_data;
|
||||
std::cout << "global_data == " << global_data << std::endl;
|
||||
global_semaphore.up();
|
||||
}
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
const int num_threads = 4;
|
||||
boost::thread_group thrds;
|
||||
for (int i=0; i < num_threads; ++i)
|
||||
thrds.create_thread(&change_global_data, 0);
|
||||
|
||||
thrds.join_all();
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The output is:</p>
|
||||
|
||||
<pre>
|
||||
global_data == 1
|
||||
global_data == 2
|
||||
global_data == 3
|
||||
global_data == 4
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39334" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <A href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +0,0 @@
|
||||
PRE
|
||||
{
|
||||
BACKGROUND-COLOR: lightcyan
|
||||
}
|
||||
283
doc/thread-ref.xml
Normal file
283
doc/thread-ref.xml
Normal file
@@ -0,0 +1,283 @@
|
||||
<?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 % 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">
|
||||
<class name="thread">
|
||||
<purpose>
|
||||
<para>The <classname>thread</classname> class represents threads of
|
||||
execution, and provides the functionality to create and manage
|
||||
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="thread.glossary.thread-state">blocked</link>.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<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
|
||||
the <classname>thread</classname> object's constructor.</para>
|
||||
|
||||
<para>A thread of execution is said to be "finished"
|
||||
or to have "finished execution" when its initial function returns or
|
||||
is terminated. This includes completion of all thread cleanup
|
||||
handlers, and completion of the normal C++ function return behaviors,
|
||||
such as destruction of automatic storage (stack) objects and releasing
|
||||
any associated implementation resources.</para>
|
||||
|
||||
<para>A thread object has an associated state which is either
|
||||
"joinable" or "non-joinable".</para>
|
||||
|
||||
<para>Except as described below, the policy used by an implementation
|
||||
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
|
||||
lifetime of an <code>iostream</code> object which represents the file, the lifetime
|
||||
of a thread of execution may be different from the
|
||||
<classname>thread</classname> object which represents the thread of
|
||||
execution. In particular, after a call to <code>join()</code>,
|
||||
the thread of execution will no longer exist even though the
|
||||
<classname>thread</classname> object continues to exist until the
|
||||
end of its normal lifetime. The converse is also possible; if
|
||||
a <classname>thread</classname> object is destroyed without
|
||||
<code>join()</code> first having been called, the thread of execution
|
||||
continues until its initial function completes.</note></para>
|
||||
</description>
|
||||
|
||||
<inherit access="private">
|
||||
<type><classname>boost::noncopyable</classname></type>
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<constructor>
|
||||
<effects>Constructs a <classname>thread</classname> object
|
||||
representing the current thread of execution.</effects>
|
||||
|
||||
<postconditions><code>*this</code> is non-joinable.</postconditions>
|
||||
|
||||
<notes><emphasis role="bold">Danger:</emphasis>
|
||||
<code>*this</code> is valid only within the current thread.</notes>
|
||||
</constructor>
|
||||
|
||||
<constructor specifiers="explicit">
|
||||
<parameter name="threadfunc">
|
||||
<paramtype>const boost::function0<void>&</paramtype>
|
||||
</parameter>
|
||||
|
||||
<effects>
|
||||
Starts a new thread of execution and constructs a
|
||||
<classname>thread</classname> object representing it.
|
||||
Copies <code>threadfunc</code> (which in turn copies
|
||||
the function object wrapped by <code>threadfunc</code>)
|
||||
to an internal location which persists for the lifetime
|
||||
of the new thread of execution. Calls <code>operator()</code>
|
||||
on the copy of the <code>threadfunc</code> function object
|
||||
in the new thread of execution.
|
||||
</effects>
|
||||
|
||||
<postconditions><code>*this</code> is joinable.</postconditions>
|
||||
|
||||
<throws><code>boost::thread_resource_error</code> if a new thread
|
||||
of execution cannot be started.</throws>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<effects>Destroys <code>*this</code>. The actual thread of
|
||||
execution may continue to execute after the
|
||||
<classname>thread</classname> object has been destroyed.
|
||||
</effects>
|
||||
|
||||
<notes>If <code>*this</code> is joinable the actual thread
|
||||
of execution becomes "detached". Any resources used
|
||||
by the thread will be reclaimed when the thread of execution
|
||||
completes. To ensure such a thread of execution runs to completion
|
||||
before the <classname>thread</classname> object is destroyed, call
|
||||
<code>join()</code>.</notes>
|
||||
</destructor>
|
||||
|
||||
<method-group name="comparison">
|
||||
<method name="operator==" cv="const">
|
||||
<type>bool</type>
|
||||
|
||||
<parameter name="rhs">
|
||||
<type>const thread&</type>
|
||||
</parameter>
|
||||
|
||||
<requires>The thread is non-terminated or <code>*this</code>
|
||||
is joinable.</requires>
|
||||
|
||||
<returns><code>true</code> if <code>*this</code> and
|
||||
<code>rhs</code> represent the same thread of
|
||||
execution.</returns>
|
||||
</method>
|
||||
|
||||
<method name="operator!=" cv="const">
|
||||
<type>bool</type>
|
||||
|
||||
<parameter name="rhs">
|
||||
<type>const thread&</type>
|
||||
</parameter>
|
||||
|
||||
<requires>The thread is non-terminated or <code>*this</code>
|
||||
is joinable.</requires>
|
||||
|
||||
<returns><code>!(*this==rhs)</code>.</returns>
|
||||
</method>
|
||||
</method-group>
|
||||
|
||||
<method-group name="modifier">
|
||||
<method name="join">
|
||||
<type>void</type>
|
||||
|
||||
<requires><code>*this</code> is joinable.</requires>
|
||||
|
||||
<effects>The current thread of execution blocks until the
|
||||
initial function of the thread of execution represented by
|
||||
<code>*this</code> finishes and all resources are
|
||||
reclaimed.</effects>
|
||||
|
||||
<postcondition><code>*this</code> is non-joinable.</postcondition>
|
||||
|
||||
<notes>If <code>*this == thread()</code> the result is
|
||||
implementation-defined. If the implementation doesn't
|
||||
detect this the result will be
|
||||
<link linkend="thread.glossary.deadlock">deadlock</link>.
|
||||
</notes>
|
||||
</method>
|
||||
</method-group>
|
||||
|
||||
<method-group name="static">
|
||||
<method name="sleep" specifiers="static">
|
||||
<type>void</type>
|
||||
|
||||
<parameter name="xt">
|
||||
<paramtype>const <classname>xtime</classname>&</paramtype>
|
||||
</parameter>
|
||||
|
||||
<effects>The current thread of execution blocks until
|
||||
<code>xt</code> is reached.</effects>
|
||||
</method>
|
||||
|
||||
<method name="yield" specifiers="static">
|
||||
<type>void</type>
|
||||
|
||||
<effects>The current thread of execution is placed in the
|
||||
<link linkend="thread.glossary.thread-state">ready</link>
|
||||
state.</effects>
|
||||
|
||||
<notes>
|
||||
<simpara>Allow the current thread to give up the rest of its
|
||||
time slice (or other scheduling quota) to another thread.
|
||||
Particularly useful in non-preemptive implementations.</simpara>
|
||||
</notes>
|
||||
</method>
|
||||
</method-group>
|
||||
</class>
|
||||
|
||||
<class name="thread_group">
|
||||
<purpose>
|
||||
The <classname>thread_group</classname> class provides a container
|
||||
for easy grouping of threads to simplify several common thread
|
||||
creation and management idioms.
|
||||
</purpose>
|
||||
|
||||
<inherit access="private">
|
||||
<type><classname>boost::noncopyable</classname></type>
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
|
||||
<constructor>
|
||||
<effects>Constructs an empty <classname>thread_group</classname>
|
||||
container.</effects>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<effects>Destroys each contained thread object. Destroys <code>*this</code>.</effects>
|
||||
|
||||
<notes>Behavior is undefined if another thread references
|
||||
<code>*this </code> during the execution of the destructor.
|
||||
</notes>
|
||||
</destructor>
|
||||
|
||||
<method-group name="modifier">
|
||||
<method name="create_thread">
|
||||
<type><classname>thread</classname>*</type>
|
||||
|
||||
<parameter name="threadfunc">
|
||||
<paramtype>const boost::function0<void>&</paramtype>
|
||||
</parameter>
|
||||
|
||||
<effects>Creates a new <classname>thread</classname> object
|
||||
that executes <code>threadfunc</code> and adds it to the
|
||||
<code>thread_group</code> container object's list of managed
|
||||
<classname>thread</classname> objects.</effects>
|
||||
|
||||
<returns>Pointer to the newly created
|
||||
<classname>thread</classname> object.</returns>
|
||||
</method>
|
||||
|
||||
<method name="add_thread">
|
||||
<type>void</type>
|
||||
|
||||
<parameter name="thrd">
|
||||
<paramtype><classname>thread</classname>*</paramtype>
|
||||
</parameter>
|
||||
|
||||
<effects>Adds <code>thrd</code> to the
|
||||
<classname>thread_group</classname> object's list of managed
|
||||
<classname>thread</classname> objects. The <code>thrd</code>
|
||||
object must have been allocated via <code>operator new</code> and will
|
||||
be deleted when the group is destroyed.</effects>
|
||||
</method>
|
||||
|
||||
<method name="remove_thread">
|
||||
<type>void</type>
|
||||
|
||||
<parameter name="thrd">
|
||||
<paramtype><classname>thread</classname>*</paramtype>
|
||||
</parameter>
|
||||
|
||||
<effects>Removes <code>thread</code> from <code>*this</code>'s
|
||||
list of managed <classname>thread</classname> objects.</effects>
|
||||
|
||||
<throws><emphasis role="bold">???</emphasis> if
|
||||
<code>thrd</code> is not in <code>*this</code>'s list
|
||||
of managed <classname>thread</classname> objects.</throws>
|
||||
</method>
|
||||
|
||||
<method name="join_all">
|
||||
<type>void</type>
|
||||
|
||||
<effects>Calls <code>join()</code> on each of the managed
|
||||
<classname>thread</classname> objects.</effects>
|
||||
</method>
|
||||
</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>
|
||||
254
doc/thread.html
254
doc/thread.html
@@ -1,254 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, Boost.Threads, thread library, C++">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<title>Boost.Threads, thread</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><IMG height=86 alt="C++ Boost" src="../../../c++boost.gif" width=277></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">Class thread</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><A href="#Introduction">Introduction</A><br>
|
||||
<A href="#Header">Header</A><br>
|
||||
<A href="#Synopsis">Synopsis</A><br>
|
||||
<A href="#Members">Members</A><br>
|
||||
<A href="#Example">Example</A></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>The <code>thread</code> class represents threads of execution, and provides
|
||||
the functionality to create and manage threads within the <b>Boost.Threads</b>
|
||||
library. See <A href="definitions.html">Definitions</A> for a precise description of
|
||||
"thread of execution", and for definitions of threading related terms and of thread
|
||||
states such as "blocked".</p>
|
||||
|
||||
<p>A thread of execution 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 the class <code>thread</code> constructor.</p>
|
||||
|
||||
<p>A thread of execution is said to be "finished" or "finished execution" when its
|
||||
initial function returns or is terminated. This includes completion of all thread
|
||||
cleanup handlers, and completion of the normal C++ function return behaviors, such
|
||||
as destruction of automatic storage (stack) objects and releasing any associated
|
||||
implementation resources.</p>
|
||||
|
||||
<p>A thread object has an associated state which is either "joinable" or
|
||||
"non-joinable".</p>
|
||||
|
||||
<p>Except as described below, the policy used by an implementation of
|
||||
<b>Boost.Threads</b> to schedule transitions between thread states is unspecified.</p>
|
||||
|
||||
<p><b>Note: </b>Just as the lifetime of a file may be different from the
|
||||
lifetime of an iostream object which represents the file, the lifetime of a
|
||||
thread of execution may be different from the <code>thread</code> object which
|
||||
represents the thread of execution. In particular, after a call to <code>join()</code>,
|
||||
the thread of execution will no longer exist even though the <code>thread</code>
|
||||
object continues to exist until the end of its normal lifetime. The
|
||||
converse is also possible; if a <code>thread</code> object is destroyed without
|
||||
<code>join()</code> having first been called, the thread of execution continues until
|
||||
its initial function completes.</p>
|
||||
|
||||
<h2><a name="Header">Header</a></h2>
|
||||
|
||||
<pre>
|
||||
#include <A href="../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></A>
|
||||
</pre>
|
||||
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
|
||||
<pre>
|
||||
namespace boost {
|
||||
|
||||
class thread : <a href="../../utility/utility.htm#noncopyable">boost::noncopyable</a> // Exposition only.
|
||||
// Class thread meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
|
||||
{
|
||||
public:
|
||||
thread();
|
||||
explicit thread(const boost::function0<void>& threadfunc);
|
||||
~thread();
|
||||
|
||||
bool operator==(const thread& rhs) const;
|
||||
bool operator!=(const thread& rhs) const;
|
||||
|
||||
void join();
|
||||
|
||||
static void sleep(const xtime& xt);
|
||||
static void yield();
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
</pre>
|
||||
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
|
||||
<hr>
|
||||
<h3>Constructors</h3>
|
||||
|
||||
<pre>
|
||||
thread();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> Constructs a <code>thread</code> object representing the current thread
|
||||
of execution.</p>
|
||||
|
||||
<p><b>Postcondition:</b> <code>*this</code> is non-joinable.</p>
|
||||
|
||||
<p><b>Danger:</b> <code>*this</code> is valid only within the current thread.</p>
|
||||
|
||||
<pre>
|
||||
thread(const <A href="../../function/index.html">boost::function0</A><void>& threadfunc);
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> Starts a new thread of execution and constructs a <code>thread</code> object
|
||||
representing it. Copies <code>threadfunc</code>
|
||||
(which in turn copies the function object wrapped by <code>threadfunc</code>) to an
|
||||
internal location which persists for the lifetime of the new thread of execution. Calls
|
||||
<code>operator()</code> on the copy of the <code>threadfunc</code> function object in
|
||||
the new thread of execution.</p>
|
||||
|
||||
<p><b>Postcondition:</b> <code>*this</code> is joinable.</p>
|
||||
|
||||
<p><b>Throws:</b> <code>boost::thread_resource_error</code> if a new thread of execution
|
||||
cannot be started.</p>
|
||||
|
||||
<hr>
|
||||
<h3>Destructor</h3>
|
||||
|
||||
<pre>
|
||||
~thread();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> Destroys <code>*this</code>. The actual thread of execution may
|
||||
continue to execute after the <code>thread</code> object has been destroyed.</p>
|
||||
|
||||
<p><b>Notes:</b> If <code>*this</code> is joinable the actual thread of execution
|
||||
becomes "detached". Any resources used by the thread will be reclaimed when the
|
||||
thread of execution completes. To ensure such a thread of execution runs to completion
|
||||
before the <code>thread</code> object is destroyed, call <code>join()</code>.</p>
|
||||
|
||||
<hr>
|
||||
<h3>Comparison Operators</h3>
|
||||
|
||||
<pre>
|
||||
bool operator==(const thread& rhs);
|
||||
</pre>
|
||||
|
||||
<p><b>Requires:</b> The thread is non-terminated or <code>*this</code> is joinable.</p>
|
||||
|
||||
<p><b>Returns:</b> <code>true</code> if <code>*this</code> and <code>rhs</code>
|
||||
represent the same thread of execution.</p>
|
||||
|
||||
<pre>
|
||||
bool operator!=(const thread& rhs);
|
||||
</pre>
|
||||
|
||||
<p><b>Returns:</b> <code>!(*this==rhs)</code>.</p>
|
||||
|
||||
<hr>
|
||||
<h3>join</h3>
|
||||
|
||||
<pre>
|
||||
void join();
|
||||
</pre>
|
||||
|
||||
<p><b>Requires:</b> <code>*this</code> is joinable.</p>
|
||||
|
||||
<p><b>Effects:</b> The current thread of execution blocks until the initial function of
|
||||
the thread of execution represented by <code>*this</code> finishes and all resources
|
||||
are reclaimed.</p>
|
||||
|
||||
<p><b>Postcondition:</b> <code>*this</code> is non-joinable.</p>
|
||||
|
||||
<p><b>Note:</b></p> If <code>*this == thread()</code> the result is implementation defined.
|
||||
If the implementation doesn't detect this the result will be
|
||||
<a href="definitions.html#Deadlock">deadlock</a>.</p>
|
||||
|
||||
<hr>
|
||||
<h3>sleep</h3>
|
||||
|
||||
<pre>
|
||||
static void sleep(const <a href="xtime.html">xtime</a>& xt);
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> The current thread of execution blocks until <code>xt</code> is
|
||||
reached.</p>
|
||||
|
||||
<hr>
|
||||
<h3>yield</h3>
|
||||
|
||||
<pre>
|
||||
static void yield();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> The current thread of execution is placed in the "ready" state.</p>
|
||||
|
||||
<p><b>Notes:</b> Allow the current thread to give up the rest of its time slice
|
||||
(or other scheduling quota) to another thread. Particularly useful in non-preemptive
|
||||
implementations.</p>
|
||||
|
||||
<hr>
|
||||
<h2><a name="Example">Example Usage</a></h2>
|
||||
|
||||
<pre>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <iostream>
|
||||
|
||||
struct thread_alarm
|
||||
{
|
||||
thread_alarm(int secs) : m_secs(secs) { }
|
||||
void operator()()
|
||||
{
|
||||
boost::xtime xt;
|
||||
boost::xtime_get(&xt, boost::TIME_UTC);
|
||||
xt.sec += m_secs;
|
||||
|
||||
boost::thread::sleep(xt);
|
||||
|
||||
std::cout << "alarm sounded..." << std::endl;
|
||||
}
|
||||
|
||||
int m_secs;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int secs = 5;
|
||||
std::cout << "setting alarm for 5 seconds..." << std::endl;
|
||||
boost::thread thrd(thread_alarm(secs));
|
||||
thrd.join();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The output is:</p>
|
||||
|
||||
<pre>
|
||||
setting alarm for 5 seconds...
|
||||
alarm sounded...
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39334" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <A href="mailto:williamkempf@hotmail.com">William E. Kempf</A>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
48
doc/thread.xml
Normal file
48
doc/thread.xml
Normal file
@@ -0,0 +1,48 @@
|
||||
<?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 % 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)
|
||||
-->
|
||||
<library name="Thread" dirname="thread" id="thread"
|
||||
last-revision="$Date$"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<libraryinfo>
|
||||
<author>
|
||||
<firstname>William</firstname>
|
||||
<othername>E.</othername>
|
||||
<surname>Kempf</surname>
|
||||
</author>
|
||||
<copyright>
|
||||
<year>2001</year>
|
||||
<year>2002</year>
|
||||
<year>2003</year>
|
||||
<holder>William E. Kempf</holder>
|
||||
</copyright>
|
||||
<legalnotice>
|
||||
<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.Thread</title>
|
||||
</libraryinfo>
|
||||
<title>Boost.Thread</title>
|
||||
<xi:include href="overview.xml"/>
|
||||
<xi:include href="design.xml"/>
|
||||
<xi:include href="concepts.xml"/>
|
||||
<xi:include href="rationale.xml"/>
|
||||
<xi:include href="reference.xml"/>
|
||||
<xi:include href="faq.xml"/>
|
||||
<xi:include href="configuration.xml"/>
|
||||
<xi:include href="build.xml"/>
|
||||
<xi:include href="implementation_notes.xml"/>
|
||||
<xi:include href="release_notes.xml"/>
|
||||
<xi:include href="glossary.xml"/>
|
||||
<xi:include href="acknowledgements.xml"/>
|
||||
<xi:include href="bibliography.xml"/>
|
||||
</library>
|
||||
@@ -1,187 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, BTL, thread library, C++">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<title>Boost.Threads, thread_group</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">thread_group</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Header">Header</a><br>
|
||||
<a href="#Synopsis">Synopsis</a><br>
|
||||
<a href="#Members">Members</a><br>
|
||||
<a href="#Example">Example</a></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>The <tt>thread_group</tt> class provides a container for easy grouping of threads to simplify several
|
||||
common thread creation and management idioms.</p>
|
||||
|
||||
<p>All <tt>thread_group</tt> member functions are <a href="definitions.html#thread-safe">thread-safe</a>,
|
||||
except destruction.</p>
|
||||
|
||||
<h2><a name="Header">Header</a></h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
||||
</pre>
|
||||
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
|
||||
<pre>
|
||||
namespace boost
|
||||
{
|
||||
class thread_group : <a href="../../utility/utility.htm#noncopyable">boost::noncopyable</a>
|
||||
{
|
||||
public:
|
||||
thread_group();
|
||||
~thread_group();
|
||||
|
||||
thread* create_thread(const boost::function0<void>& threadfunc);
|
||||
void add_thread(thread* thrd);
|
||||
void remove_thread(thread* thrd);
|
||||
void join_all();
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
<hr>
|
||||
|
||||
<h3>Constructor</h3>
|
||||
|
||||
<pre>
|
||||
thread_group();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> Constructs an empty <tt>thread_group</tt> container.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Destructor</h3>
|
||||
|
||||
<pre>
|
||||
~thread_group();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> Destroys each contained thread object. Destroys <code>*this</code>.</p>
|
||||
|
||||
<p><b>Notes:</b> Behavior is undefined if another thread references *this during
|
||||
the execution of the destructor.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>create_thread</h3>
|
||||
|
||||
<pre>
|
||||
thread* create_thread(const boost::function0<void>& threadfunc);
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> Creates a new <tt>thread</tt> object that executes <tt>threadfunc</tt> and adds it to the
|
||||
<tt>thread_group</tt> container object's list of managed <tt>thread</tt> objects.</p>
|
||||
|
||||
<p><b>Returns:</b> Pointer to the newly created thread.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>add_thread</h3>
|
||||
|
||||
<pre>
|
||||
void add_thread(thread* thrd);
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> Adds <tt>thrd</tt> to the <tt>thread_group</tt> object's list of managed <tt>thread</tt>
|
||||
objects. The <tt>thrd</tt> object must have been allocated via operator new and will
|
||||
be deleted when the group is destroyed.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>remove_thread</h3>
|
||||
|
||||
<pre>
|
||||
void remove_thread(thread* thrd);
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> Removes <code>*this</code>'s list of managed <tt>thread</tt>
|
||||
objects.</p>
|
||||
|
||||
<p><b>Throws: </b>? if <tt>thrd</tt> is not it <code>*this</code>'s list of managed <tt>thread</tt>
|
||||
objects.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>join_all</h3>
|
||||
|
||||
<pre>
|
||||
void join_all();
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> Calls <code> join()</code> on each of the managed <tt>thread</tt> objects.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="Example">Example</a> Usage</h2>
|
||||
|
||||
<pre>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <iostream>
|
||||
|
||||
int count = 0;
|
||||
boost::mutex mutex;
|
||||
|
||||
void increment_count()
|
||||
{
|
||||
boost::mutex::lock lock(mutex);
|
||||
std::cout << "count = " << ++count << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
boost::thread_group threads;
|
||||
for (int i = 0; i < 10; ++i)
|
||||
threads.create_thread(&increment_count);
|
||||
threads.join_all();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The output is:</p>
|
||||
|
||||
<pre>
|
||||
count = 1
|
||||
count = 2
|
||||
count = 3
|
||||
count = 4
|
||||
count = 5
|
||||
count = 6
|
||||
count = 7
|
||||
count = 8
|
||||
count = 9
|
||||
count = 10
|
||||
</pre>
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->06 August, 2001<!--webbot bot="Timestamp" endspan i-checksum="34352" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,80 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, BTL, thread library, C++">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<title>Boost.Threads, thread_resource_error</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">thread_resource_error</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Header">Header</a><br>
|
||||
<a href="#Synopsis">Synopsis</a><br>
|
||||
<a href="#Members">Members</a><br>
|
||||
<a href="#Example">Example</a></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>The <code>thread_resource_error</code> class defines an exception type that is thrown
|
||||
by constructors in the <b>Boost.Threads</b> library when thread related resources
|
||||
can not be
|
||||
acquired. This does not include memory allocation failures which instead throw
|
||||
std::bad_alloc.</p>
|
||||
|
||||
<h2><a name="Header">Header</a></h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/thread.hpp"><boost/thread/exceptions.hpp></a>
|
||||
</pre>
|
||||
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
|
||||
<pre>
|
||||
namespace boost
|
||||
{
|
||||
class thread_resource_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
thread_resource_error();
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
|
||||
<hr>
|
||||
|
||||
<h3>Constructor</h3>
|
||||
|
||||
<pre>
|
||||
thread_resource_error();
|
||||
</pre>
|
||||
|
||||
<p>Constructs a <code>thread_resource_error</code> object.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->04 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39335" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,214 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, Boost.Threads, thread library, C++">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<title>Boost.Threads, thread_specific_ptr</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">thread_specific_ptr</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><A href="#Introduction">Introduction</A><br>
|
||||
<A href="#Header">Header</A><br>
|
||||
<A href="#Synopsis">Synopsis</A><br>
|
||||
<A href="#Members">Members</A><br>
|
||||
<A href="#Example">Example</A></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>The <code>thread_specific_ptr</code> class defines an interface for using thread
|
||||
specific storage. Thread specific storage is data associated with individual threads
|
||||
and is often used to make operations
|
||||
<a href="definitions.html#Thread-safe">thread-safe</a> that rely on global data.</p>
|
||||
|
||||
<p>Template <code>thread_specific_ptr</code> stores a pointer to an object obtained via
|
||||
<code>new</code> on a thread-by-thread basis and calls delete on the contained pointer
|
||||
when the thread terminates. Each thread initially stores the null pointer in each
|
||||
<code>thread_specific_ptr</code> instance.</p>
|
||||
|
||||
<p>The template <code>thread_specific_ptr</code> is useful in the following cases:</p>
|
||||
|
||||
<ul>
|
||||
<li>An interface was original written assuming a single thread of control and is
|
||||
being ported to a multi-threaded environment.</li>
|
||||
<li>Each thread of control invokes sequences of methods that share data that must be
|
||||
logically accessed through a globally visible access point, but are physically
|
||||
unique for each thread, instead of being explicitly passed.</li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="Header">Header</a></h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/tss.hpp"><boost/thread/tss.hpp></a>
|
||||
</pre>
|
||||
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
|
||||
<pre>
|
||||
namespace boost {
|
||||
|
||||
template <typename T>
|
||||
class thread_specific_ptr : private boost::noncopyable // Exposition only.
|
||||
// Class thread_specific_ptr meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
|
||||
{
|
||||
public:
|
||||
thread_specific_ptr();
|
||||
~thread_specific_ptr();
|
||||
|
||||
T* get() const;
|
||||
T* operator->() const;
|
||||
T& operator*() const;
|
||||
T* release();
|
||||
void reset(T* p=0);
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
</pre>
|
||||
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
|
||||
<hr>
|
||||
<h3>Constructor</h3>
|
||||
|
||||
<pre>
|
||||
thread_specific_ptr();
|
||||
</pre>
|
||||
|
||||
<p><b>Postconditions:</b> A thread specific storage has been reserved for use by *this
|
||||
in all threads, with each thread initially storing a null pointer.</p>
|
||||
|
||||
<p><b>Requires:</b> The expression <code>delete get()</code> is well formed.</p>
|
||||
|
||||
<p><b>Throws:</b> <code>boost::thread_resource_error</code> if the necessary resources
|
||||
can not be obtained.</p>
|
||||
|
||||
<p><b>Notes:</b> There is an implementation specific limit to the number of thread
|
||||
specific storage objects that can be created, and this limit may be small.</p>
|
||||
|
||||
<hr>
|
||||
<h3>Destructor</h3>
|
||||
|
||||
<pre>
|
||||
~thread_specific_ptr();
|
||||
</pre>
|
||||
|
||||
<p><b>Notes:</b> Does not destroy any data that may be stored in any thread's thread
|
||||
specific storage. For this reason you should not destroy a
|
||||
<code>thread_specific_ptr</code> object until you are certain there are no threads
|
||||
running that have made use of its thread specific storage.</p>
|
||||
|
||||
<hr>
|
||||
<h3>get</h3>
|
||||
|
||||
<pre>
|
||||
T* get() const;
|
||||
</pre>
|
||||
|
||||
<p><b>Returns:</b> The object stored in thread specific storage for the current thread
|
||||
for *this.</p>
|
||||
|
||||
<p><b>Notes:</b> Each thread initially returns 0.</p>
|
||||
|
||||
<hr>
|
||||
<h3>Smart Pointer Operations</h3>
|
||||
|
||||
<pre>
|
||||
T* operator->() const;
|
||||
</pre>
|
||||
|
||||
<p><b>Returns:</b> <code>get()</code></p>
|
||||
|
||||
<pre>
|
||||
T& operator*() const;
|
||||
</pre>
|
||||
|
||||
<p><b>Returns:</b> <code>get()</code></p>
|
||||
|
||||
<p><b>Requires:</b> <code>get() != 0</code></p>
|
||||
|
||||
<hr>
|
||||
<h3>Release</h3>
|
||||
|
||||
<pre>
|
||||
T* release();
|
||||
</pre>
|
||||
|
||||
<p><b>Returns:</b> <code>get()</code></p>
|
||||
|
||||
<p><b>Postcondition:</b> *this holds the null pointer for the current thread.</p>
|
||||
|
||||
<hr>
|
||||
<h3>Reset</h3>
|
||||
|
||||
<pre>
|
||||
void reset(T* p=0);
|
||||
</pre>
|
||||
|
||||
<p><b>Effects:</b> If <code>get()!= p</code> then <code>delete get()</code>.</p>
|
||||
|
||||
<p><b>Postconditions:</b> <code>*this</code> holds the pointer <code>p</code> for
|
||||
the current thread.</p>
|
||||
|
||||
<p><b>Notes:</b> The pointer will be deleted when the thread terminates.</p>
|
||||
|
||||
<hr>
|
||||
<h2><a name="Example">Example Usage</a></h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
||||
#include <a href="../../../boost/thread/tss.hpp"><boost/thread/tss.hpp></a>
|
||||
#include <cassert>
|
||||
|
||||
boost::thread_specific_ptr<int> value;
|
||||
|
||||
void increment()
|
||||
{
|
||||
int* p = value.get();
|
||||
++*p;
|
||||
}
|
||||
|
||||
void thread_proc()
|
||||
{
|
||||
value.reset(new int(0)); // initialize the thread's storage
|
||||
for (int i=0; i<10; ++i)
|
||||
{
|
||||
increment();
|
||||
int* p = value.get();
|
||||
assert(*p == i+1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
boost::thread_group threads;
|
||||
for (int i=0; i<5; ++i)
|
||||
threads.create_thread(&thread_proc);
|
||||
threads.join_all();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39334" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
206
doc/tss-ref.xml
Normal file
206
doc/tss-ref.xml
Normal file
@@ -0,0 +1,206 @@
|
||||
<?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 % 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">
|
||||
<class name="thread_specific_ptr">
|
||||
<purpose>
|
||||
The <classname>thread_specific_ptr</classname> class defines
|
||||
an interface for using thread specific storage.
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>Thread specific storage is data associated with
|
||||
individual threads and is often used to make operations
|
||||
that rely on global data
|
||||
<link linkend="thread.glossary.thread-safe">thread-safe</link>.
|
||||
</para>
|
||||
|
||||
<para>Template <classname>thread_specific_ptr</classname>
|
||||
stores a pointer to an object obtained on a thread-by-thread
|
||||
basis and calls a specified cleanup handler on the contained
|
||||
pointer when the thread terminates. The cleanup handlers are
|
||||
called in the reverse order of construction of the
|
||||
<classname>thread_specific_ptr</classname>s, and for the
|
||||
initial thread are called by the destructor, providing the
|
||||
same ordering guarantees as for normal declarations. Each
|
||||
thread initially stores the null pointer in each
|
||||
<classname>thread_specific_ptr</classname> instance.</para>
|
||||
|
||||
<para>The template <classname>thread_specific_ptr</classname>
|
||||
is useful in the following cases:
|
||||
<itemizedlist>
|
||||
<listitem>An interface was originally written assuming
|
||||
a single thread of control and it is being ported to a
|
||||
multithreaded environment.</listitem>
|
||||
|
||||
<listitem>Each thread of control invokes sequences of
|
||||
methods that share data that are physically unique
|
||||
for each thread, but must be logically accessed
|
||||
through a globally visible access point instead of
|
||||
being explicitly passed.</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</description>
|
||||
|
||||
<inherit access="private">
|
||||
<type><classname>boost::noncopyable</classname></type>
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<constructor>
|
||||
<requires>The expression <code>delete get()</code> is well
|
||||
formed.</requires>
|
||||
|
||||
<effects>A thread-specific data key is allocated and visible to
|
||||
all threads in the process. Upon creation, the value
|
||||
<code>NULL</code> will be associated with the new key in all
|
||||
active threads. A cleanup method is registered with the key
|
||||
that will call <code>delete</code> on the value associated
|
||||
with the key for a thread when it exits. When a thread exits,
|
||||
if a key has a registered cleanup method and the thread has a
|
||||
non-<code>NULL</code> value associated with that key, the value
|
||||
of the key is set to <code>NULL</code> and then the cleanup
|
||||
method is called with the previously associated value as its
|
||||
sole argument. The order in which registered cleanup methods
|
||||
are called when a thread exits is undefined. If after all the
|
||||
cleanup methods have been called for all non-<code>NULL</code>
|
||||
values, there are still some non-<code>NULL</code> values
|
||||
with associated cleanup handlers the result is undefined
|
||||
behavior.</effects>
|
||||
|
||||
<throws><classname>boost::thread_resource_error</classname> if
|
||||
the necessary resources can not be obtained.</throws>
|
||||
|
||||
<notes>There may be an implementation specific limit to the
|
||||
number of thread specific storage objects that can be created,
|
||||
and this limit may be small.</notes>
|
||||
|
||||
<rationale>The most common need for cleanup will be to call
|
||||
<code>delete</code> on the associated value. If other forms
|
||||
of cleanup are required the overloaded constructor should be
|
||||
called instead.</rationale>
|
||||
</constructor>
|
||||
|
||||
<constructor>
|
||||
<parameter name="cleanup">
|
||||
<paramtype>void (*cleanup)(void*)</paramtype>
|
||||
</parameter>
|
||||
|
||||
<effects>A thread-specific data key is allocated and visible to
|
||||
all threads in the process. Upon creation, the value
|
||||
<code>NULL</code> will be associated with the new key in all
|
||||
active threads. The <code>cleanup</code> method is registered
|
||||
with the key and will be called for a thread with the value
|
||||
associated with the key for that thread when it exits. When a
|
||||
thread exits, if a key has a registered cleanup method and the
|
||||
thread has a non-<code>NULL</code> value associated with that
|
||||
key, the value of the key is set to <code>NULL</code> and then
|
||||
the cleanup method is called with the previously associated
|
||||
value as its sole argument. The order in which registered
|
||||
cleanup methods are called when a thread exits is undefined.
|
||||
If after all the cleanup methods have been called for all
|
||||
non-<code>NULL</code> values, there are still some
|
||||
non-<code>NULL</code> values with associated cleanup handlers
|
||||
the result is undefined behavior.</effects>
|
||||
|
||||
<throws><classname>boost::thread_resource_error</classname> if
|
||||
the necessary resources can not be obtained.</throws>
|
||||
|
||||
<notes>There may be an implementation specific limit to the
|
||||
number of thread specific storage objects that can be created,
|
||||
and this limit may be small.</notes>
|
||||
|
||||
<rationale>There is the occasional need to register
|
||||
specialized cleanup methods, or to register no cleanup method
|
||||
at all (done by passing <code>NULL</code> to this constructor.
|
||||
</rationale>
|
||||
</constructor>
|
||||
|
||||
<destructor>
|
||||
<effects>Deletes the thread-specific data key allocated by the
|
||||
constructor. The thread-specific data values associated with
|
||||
the key need not be <code>NULL</code>. It is the responsibility
|
||||
of the application to perform any cleanup actions for data
|
||||
associated with the key.</effects>
|
||||
|
||||
<notes>Does not destroy any data that may be stored in any
|
||||
thread's thread specific storage. For this reason you should
|
||||
not destroy a <classname>thread_specific_ptr</classname> object
|
||||
until you are certain there are no threads running that have
|
||||
made use of its thread specific storage.</notes>
|
||||
|
||||
<rationale>Associated data is not cleaned up because registered
|
||||
cleanup methods need to be run in the thread that allocated the
|
||||
associated data to be guarranteed to work correctly. There's no
|
||||
safe way to inject the call into another thread's execution
|
||||
path, making it impossible to call the cleanup methods safely.
|
||||
</rationale>
|
||||
</destructor>
|
||||
|
||||
<method-group name="modifier functions">
|
||||
<method name="release">
|
||||
<type>T*</type>
|
||||
|
||||
<postconditions><code>*this</code> holds the null pointer
|
||||
for the current thread.</postconditions>
|
||||
|
||||
<returns><code>this->get()</code> prior to the call.</returns>
|
||||
|
||||
<rationale>This method provides a mechanism for the user to
|
||||
relinquish control of the data associated with the
|
||||
thread-specific key.</rationale>
|
||||
</method>
|
||||
|
||||
<method name="reset">
|
||||
<type>void</type>
|
||||
|
||||
<parameter name="p">
|
||||
<paramtype>T*</paramtype>
|
||||
<default>0</default>
|
||||
</parameter>
|
||||
|
||||
<effects>If <code>this->get() != p &&
|
||||
this->get() != NULL</code> then call the
|
||||
associated cleanup function.</effects>
|
||||
|
||||
<postconditions><code>*this</code> holds the pointer
|
||||
<code>p</code> for the current thread.</postconditions>
|
||||
</method>
|
||||
</method-group>
|
||||
|
||||
<method-group name="observer functions">
|
||||
<method name="get" cv="const">
|
||||
<type>T*</type>
|
||||
|
||||
<returns>The object stored in thread specific storage for
|
||||
the current thread for <code>*this</code>.</returns>
|
||||
|
||||
<notes>Each thread initially returns 0.</notes>
|
||||
</method>
|
||||
|
||||
<method name="operator->" cv="const">
|
||||
<type>T*</type>
|
||||
|
||||
<returns><code>this->get()</code>.</returns>
|
||||
</method>
|
||||
|
||||
<method name="operator*()" cv="const">
|
||||
<type>T&</type>
|
||||
|
||||
<requires><code>this->get() != 0</code></requires>
|
||||
|
||||
<returns><code>this->get()</code>.</returns>
|
||||
</method>
|
||||
</method-group>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
82
doc/xtime-ref.xml
Normal file
82
doc/xtime-ref.xml
Normal file
@@ -0,0 +1,82 @@
|
||||
<?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 % 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">
|
||||
<enum name="xtime_clock_types">
|
||||
<enumvalue name="TIME_UTC" />
|
||||
|
||||
<purpose>
|
||||
<para>Specifies the clock type to use when creating
|
||||
an object of type <classname>xtime</classname>.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<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>
|
||||
</enum>
|
||||
|
||||
<struct name="xtime">
|
||||
<purpose>
|
||||
<simpara>An object of type <classname>xtime</classname>
|
||||
defines a time that is used to perform high-resolution time operations.
|
||||
This is a temporary solution that will be replaced by a more robust time
|
||||
library once available in Boost.</simpara>
|
||||
</purpose>
|
||||
|
||||
<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.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.Thread;
|
||||
will deprecate its own implementation.</simpara>
|
||||
|
||||
<simpara><emphasis role="bold">Note</emphasis> that the resolution is
|
||||
implementation specific. For many implementations the best resolution
|
||||
of time is far more than one nanosecond, and even when the resolution
|
||||
is reasonably good, the latency of a call to <code>xtime_get()</code>
|
||||
may be significant. For maximum portability, avoid durations of less than
|
||||
one second.</simpara>
|
||||
</description>
|
||||
|
||||
<free-function-group name="creation">
|
||||
<function name="xtime_get">
|
||||
<type>int</type>
|
||||
|
||||
<parameter name="xtp">
|
||||
<paramtype><classname>xtime</classname>*</paramtype>
|
||||
</parameter>
|
||||
|
||||
<parameter name="clock_type">
|
||||
<paramtype>int</paramtype>
|
||||
</parameter>
|
||||
|
||||
<postconditions>
|
||||
<simpara><code>xtp</code> represents the current point in
|
||||
time as a duration since the epoch specified by
|
||||
<code>clock_type</code>.</simpara>
|
||||
</postconditions>
|
||||
|
||||
<returns>
|
||||
<simpara><code>clock_type</code> if successful, otherwise 0.</simpara>
|
||||
</returns>
|
||||
</function>
|
||||
</free-function-group>
|
||||
|
||||
<data-member name="sec">
|
||||
<type><emphasis>platform-specific-type</emphasis></type>
|
||||
</data-member>
|
||||
</struct>
|
||||
</namespace>
|
||||
</header>
|
||||
141
doc/xtime.html
141
doc/xtime.html
@@ -1,141 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="keywords" content="threads, Boost.Threads, thread library, C++">
|
||||
<link rel="stylesheet" type="text/css" href="styles.css">
|
||||
<title>Boost.Threads, xtime</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">xtime</h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><A href="#Introduction">Introduction</A><br>
|
||||
<A href="#Header">Header</A><br>
|
||||
<A href="#Synopsis">Synopsis</A><br>
|
||||
<A href="#Reference">Reference</A><br>
|
||||
<A href="#Example">Example</A></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>The <code>xtime</code> 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.
|
||||
<b>Boost.Threads</b> provides only a very minimal implementation of this proposal
|
||||
and it's expected that a full implementation will be provided in Boost as a separate
|
||||
library, at which time <b>Boost.Threads</b> will deprecate its implementation.</p>
|
||||
|
||||
<h2><a name="Header">Header</a></h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/xtime.hpp"><boost/thread/xtime.hpp></a>
|
||||
</pre>
|
||||
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
|
||||
<pre>
|
||||
namespace boost {
|
||||
|
||||
enum
|
||||
{
|
||||
TIME_UTC=1,
|
||||
};
|
||||
|
||||
struct xtime
|
||||
{
|
||||
#if defined(BOOST_NO_INT64_T)
|
||||
int_fast32_t sec;
|
||||
#else
|
||||
int_fast64_t sec;
|
||||
#endif
|
||||
int_fast32_t nsec;
|
||||
};
|
||||
|
||||
int xtime_get(struct xtime* xtp, int clock_type);
|
||||
|
||||
} // namespace boost
|
||||
</pre>
|
||||
|
||||
<h2><a name="Reference">Reference</a></h2>
|
||||
|
||||
<hr>
|
||||
<h3>TIME_UTC</h3>
|
||||
|
||||
<p>The clock type for Coordinated Universal Time (UTC). The epoch for this clock type
|
||||
is 1970-01-01 00:00:00. This is the only clock type supported by <b>Boost.Threads</b>.</p>
|
||||
|
||||
<hr>
|
||||
<h3>xtime</h3>
|
||||
|
||||
<pre>
|
||||
struct xtime
|
||||
{
|
||||
#if defined(BOOST_NO_INT64_T)
|
||||
int_fast32_t sec;
|
||||
#else
|
||||
int_fast64_t sec;
|
||||
#endif
|
||||
int_fast32_t nsec;
|
||||
};
|
||||
</pre>
|
||||
|
||||
<p><b>sec</b> represents the whole seconds that have passed since the epoch.</p>
|
||||
|
||||
<p><b>nsec</b> represents the nanoseconds since <code>sec.</code>
|
||||
|
||||
<hr>
|
||||
<h3>xtime_get</h3>
|
||||
|
||||
<pre>
|
||||
int xtime_get(struct xtime* xtp, int clock_type);
|
||||
</pre>
|
||||
|
||||
<p><b>Postcondition:</b> <code>xtp</code> represents the current point in time
|
||||
as a duration since the epoch specified by the <code>clock_type</code>.</p>
|
||||
|
||||
<p><b>Returns:</b> <code>clock_type</code> if successful, otherwise 0.
|
||||
|
||||
<p><b>Notes:</b> The resolution is implementation specific. For many
|
||||
implementations the best resolution of time is far more than one nanosecond, and
|
||||
even when the resolution is reasonably good, the latency of a call to <code>xtime_get()</code>
|
||||
may be significant. For maximum portability, avoid durations of less than
|
||||
one second.</p>
|
||||
|
||||
<hr>
|
||||
<h2><a name="Example">Example Usage</a></h2>
|
||||
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
||||
#include <a href="../../../boost/thread/tss.hpp"><boost/thread/xtime.hpp></a>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
boost::xtime xt;
|
||||
boost::xtime_get(&xt, boost::TIME_UTC);
|
||||
xt.sec += 1;
|
||||
boost::thread::sleep(xt); // Sleep for 1 second
|
||||
}
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->10 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39328" -->
|
||||
</p>
|
||||
|
||||
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
|
||||
2001 all rights reserved.</i></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
2
example/.cvsignore
Normal file
2
example/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
bin
|
||||
*.pdb
|
||||
@@ -1,66 +0,0 @@
|
||||
# (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.
|
||||
#
|
||||
# Boost.Threads build and test Jamfile
|
||||
#
|
||||
# Declares the following targets:
|
||||
# 1. monitor, an example program.
|
||||
# 2. starvephil, an example program.
|
||||
# 3. tennis, an example program.
|
||||
|
||||
# declare the location of this subproject relative to the root
|
||||
subproject libs/thread/example ;
|
||||
|
||||
# Do some OS-specific setup
|
||||
if $(NT)
|
||||
{
|
||||
BOOST_THREADMON_LIB = <lib>../build/libboost_threadmon ;
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_THREADMON_LIB = ;
|
||||
}
|
||||
|
||||
#######################
|
||||
|
||||
#
|
||||
# Declare the Boost.Threads monitor example program.
|
||||
#
|
||||
|
||||
exe monitor : monitor/monitor.cpp
|
||||
<lib>../build/libboost_thread
|
||||
$(BOOST_THREADMON_LIB)
|
||||
# requirements
|
||||
: <include>$(BOOST_ROOT)
|
||||
<threading>multi
|
||||
: debug release ;
|
||||
|
||||
#######################
|
||||
|
||||
#
|
||||
# Declare the Boost.Threads starvephil example program.
|
||||
#
|
||||
|
||||
exe starvephil : starvephil/starvephil.cpp
|
||||
<lib>../build/libboost_thread
|
||||
$(BOOST_THREADMON_LIB)
|
||||
# requirements
|
||||
: <include>$(BOOST_ROOT)
|
||||
<threading>multi
|
||||
: debug release ;
|
||||
|
||||
#######################
|
||||
|
||||
#
|
||||
# Declare the Boost.Threads tennis example program.
|
||||
#
|
||||
|
||||
exe tennis : tennis/tennis.cpp
|
||||
<lib>../build/libboost_thread
|
||||
$(BOOST_THREADMON_LIB)
|
||||
# requirements
|
||||
: <include>$(BOOST_ROOT)
|
||||
<threading>multi
|
||||
: debug release ;
|
||||
23
example/Jamfile.v2
Normal file
23
example/Jamfile.v2
Normal file
@@ -0,0 +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)
|
||||
|
||||
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 ;
|
||||
|
||||
74
example/condition.cpp
Normal file
74
example/condition.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
// 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)
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
class bounded_buffer : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
typedef boost::mutex::scoped_lock lock;
|
||||
|
||||
bounded_buffer(int n) : begin(0), end(0), buffered(0), circular_buf(n) { }
|
||||
|
||||
void send (int m) {
|
||||
lock lk(monitor);
|
||||
while (buffered == circular_buf.size())
|
||||
buffer_not_full.wait(lk);
|
||||
circular_buf[end] = m;
|
||||
end = (end+1) % circular_buf.size();
|
||||
++buffered;
|
||||
buffer_not_empty.notify_one();
|
||||
}
|
||||
int receive() {
|
||||
lock lk(monitor);
|
||||
while (buffered == 0)
|
||||
buffer_not_empty.wait(lk);
|
||||
int i = circular_buf[begin];
|
||||
begin = (begin+1) % circular_buf.size();
|
||||
--buffered;
|
||||
buffer_not_full.notify_one();
|
||||
return i;
|
||||
}
|
||||
|
||||
private:
|
||||
int begin, end, buffered;
|
||||
std::vector<int> circular_buf;
|
||||
boost::condition buffer_not_full, buffer_not_empty;
|
||||
boost::mutex monitor;
|
||||
};
|
||||
|
||||
bounded_buffer buf(2);
|
||||
|
||||
void sender() {
|
||||
int n = 0;
|
||||
while (n < 100) {
|
||||
buf.send(n);
|
||||
std::cout << "sent: " << n << std::endl;
|
||||
++n;
|
||||
}
|
||||
buf.send(-1);
|
||||
}
|
||||
|
||||
void receiver() {
|
||||
int n;
|
||||
do {
|
||||
n = buf.receive();
|
||||
std::cout << "received: " << n << std::endl;
|
||||
} while (n != -1); // -1 indicates end of buffer
|
||||
}
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
boost::thread thrd1(&sender);
|
||||
boost::thread thrd2(&receiver);
|
||||
thrd1.join();
|
||||
thrd2.join();
|
||||
return 0;
|
||||
}
|
||||
@@ -1,3 +1,9 @@
|
||||
// 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)
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <boost/thread/condition.hpp>
|
||||
@@ -6,21 +12,21 @@
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
namespace {
|
||||
const int ITERS = 100;
|
||||
boost::mutex io_mutex;
|
||||
};
|
||||
const int ITERS = 100;
|
||||
boost::mutex io_mutex;
|
||||
} // namespace
|
||||
|
||||
template <typename M>
|
||||
class buffer_t
|
||||
{
|
||||
public:
|
||||
typedef typename M::scoped_lock scoped_lock;
|
||||
|
||||
|
||||
buffer_t(int n)
|
||||
: p(0), c(0), full(0), buf(n)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void send(int m)
|
||||
{
|
||||
scoped_lock lk(mutex);
|
||||
@@ -29,7 +35,7 @@ public:
|
||||
buf[p] = m;
|
||||
p = (p+1) % buf.size();
|
||||
++full;
|
||||
cond.notify_all();
|
||||
cond.notify_one();
|
||||
}
|
||||
int receive()
|
||||
{
|
||||
@@ -39,41 +45,40 @@ public:
|
||||
int i = buf[c];
|
||||
c = (c+1) % buf.size();
|
||||
--full;
|
||||
cond.notify_all();
|
||||
cond.notify_one();
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
static buffer_t& get_buffer()
|
||||
{
|
||||
static buffer_t buf(2);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
static void do_sender_thread()
|
||||
{
|
||||
for (int n = 0; n < ITERS; ++n)
|
||||
{
|
||||
get_buffer().send(n);
|
||||
{
|
||||
boost::mutex::scoped_lock lock(io_mutex);
|
||||
std::cout << "sent: " << n << std::endl;
|
||||
std::cout << "sending: " << n << std::endl;
|
||||
}
|
||||
get_buffer().send(n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void do_receiver_thread()
|
||||
{
|
||||
int n;
|
||||
do
|
||||
for (int x=0; x < (ITERS/2); ++x)
|
||||
{
|
||||
n = get_buffer().receive();
|
||||
int n = get_buffer().receive();
|
||||
{
|
||||
boost::mutex::scoped_lock lock(io_mutex);
|
||||
std::cout << "received: " << n << std::endl;
|
||||
}
|
||||
} while (n < ITERS - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
M mutex;
|
||||
boost::condition cond;
|
||||
@@ -86,10 +91,12 @@ void do_test(M* dummy=0)
|
||||
{
|
||||
typedef buffer_t<M> buffer_type;
|
||||
buffer_type::get_buffer();
|
||||
boost::thread thrd1(&buffer_type::do_sender_thread);
|
||||
boost::thread thrd1(&buffer_type::do_receiver_thread);
|
||||
boost::thread thrd2(&buffer_type::do_receiver_thread);
|
||||
boost::thread thrd3(&buffer_type::do_sender_thread);
|
||||
thrd1.join();
|
||||
thrd2.join();
|
||||
thrd3.join();
|
||||
}
|
||||
|
||||
void test_buffer()
|
||||
47
example/mutex.cpp
Normal file
47
example/mutex.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <iostream>
|
||||
|
||||
boost::mutex io_mutex; // The iostreams are not guaranteed to be thread-safe!
|
||||
|
||||
class counter
|
||||
{
|
||||
public:
|
||||
counter() : count(0) { }
|
||||
|
||||
int increment() {
|
||||
boost::mutex::scoped_lock scoped_lock(mutex);
|
||||
return ++count;
|
||||
}
|
||||
|
||||
private:
|
||||
boost::mutex mutex;
|
||||
int count;
|
||||
};
|
||||
|
||||
counter c;
|
||||
|
||||
void change_count()
|
||||
{
|
||||
int i = c.increment();
|
||||
boost::mutex::scoped_lock scoped_lock(io_mutex);
|
||||
std::cout << "count == " << i << std::endl;
|
||||
}
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
const int num_threads = 4;
|
||||
boost::thread_group thrds;
|
||||
for (int i=0; i < num_threads; ++i)
|
||||
thrds.create_thread(&change_count);
|
||||
|
||||
thrds.join_all();
|
||||
|
||||
return 0;
|
||||
}
|
||||
31
example/once.cpp
Normal file
31
example/once.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/once.hpp>
|
||||
#include <cassert>
|
||||
|
||||
int value=0;
|
||||
boost::once_flag once = BOOST_ONCE_INIT;
|
||||
|
||||
void init()
|
||||
{
|
||||
++value;
|
||||
}
|
||||
|
||||
void thread_proc()
|
||||
{
|
||||
boost::call_once(&init, once);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
boost::thread_group threads;
|
||||
for (int i=0; i<5; ++i)
|
||||
threads.create_thread(&thread_proc);
|
||||
threads.join_all();
|
||||
assert(value == 1);
|
||||
}
|
||||
49
example/recursive_mutex.cpp
Normal file
49
example/recursive_mutex.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <iostream>
|
||||
|
||||
class counter
|
||||
{
|
||||
public:
|
||||
counter() : count(0) { }
|
||||
|
||||
int add(int val) {
|
||||
boost::recursive_mutex::scoped_lock scoped_lock(mutex);
|
||||
count += val;
|
||||
return count;
|
||||
}
|
||||
int increment() {
|
||||
boost::recursive_mutex::scoped_lock scoped_lock(mutex);
|
||||
return add(1);
|
||||
}
|
||||
|
||||
private:
|
||||
boost::recursive_mutex mutex;
|
||||
int count;
|
||||
};
|
||||
|
||||
counter c;
|
||||
|
||||
void change_count()
|
||||
{
|
||||
std::cout << "count == " << c.increment() << std::endl;
|
||||
}
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
const int num_threads=4;
|
||||
|
||||
boost::thread_group threads;
|
||||
for (int i=0; i < num_threads; ++i)
|
||||
threads.create_thread(&change_count);
|
||||
|
||||
threads.join_all();
|
||||
|
||||
return 0;
|
||||
}
|
||||
185
example/starvephil.cpp
Normal file
185
example/starvephil.cpp
Normal file
@@ -0,0 +1,185 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <iostream>
|
||||
#include <time.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
boost::mutex iomx;
|
||||
} // namespace
|
||||
|
||||
class canteen
|
||||
{
|
||||
public:
|
||||
canteen() : m_chickens(0) { }
|
||||
|
||||
void get(int id)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_mutex);
|
||||
while (m_chickens == 0)
|
||||
{
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock() << ") Phil" << id <<
|
||||
": wot, no chickens? I'll WAIT ..." << std::endl;
|
||||
}
|
||||
m_condition.wait(lock);
|
||||
}
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock() << ") Phil" << id <<
|
||||
": those chickens look good ... one please ..." << std::endl;
|
||||
}
|
||||
m_chickens--;
|
||||
}
|
||||
void put(int value)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_mutex);
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock()
|
||||
<< ") Chef: ouch ... make room ... this dish is "
|
||||
<< "very hot ..." << std::endl;
|
||||
}
|
||||
boost::xtime xt;
|
||||
boost::xtime_get(&xt, boost::TIME_UTC);
|
||||
xt.sec += 3;
|
||||
boost::thread::sleep(xt);
|
||||
m_chickens += value;
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock() <<
|
||||
") Chef: more chickens ... " << m_chickens <<
|
||||
" now available ... NOTIFYING ..." << std::endl;
|
||||
}
|
||||
m_condition.notify_all();
|
||||
}
|
||||
|
||||
private:
|
||||
boost::mutex m_mutex;
|
||||
boost::condition m_condition;
|
||||
int m_chickens;
|
||||
};
|
||||
|
||||
canteen g_canteen;
|
||||
|
||||
void chef()
|
||||
{
|
||||
const int chickens = 4;
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock() << ") Chef: starting ..." << std::endl;
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock() << ") Chef: cooking ..." << std::endl;
|
||||
}
|
||||
boost::xtime xt;
|
||||
boost::xtime_get(&xt, boost::TIME_UTC);
|
||||
xt.sec += 2;
|
||||
boost::thread::sleep(xt);
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock() << ") Chef: " << chickens
|
||||
<< " chickens, ready-to-go ..." << std::endl;
|
||||
}
|
||||
g_canteen.put(chickens);
|
||||
}
|
||||
}
|
||||
|
||||
struct phil
|
||||
{
|
||||
phil(int id) : m_id(id) { }
|
||||
void run() {
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock() << ") Phil" << m_id
|
||||
<< ": starting ..." << std::endl;
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
if (m_id > 0)
|
||||
{
|
||||
boost::xtime xt;
|
||||
boost::xtime_get(&xt, boost::TIME_UTC);
|
||||
xt.sec += 3;
|
||||
boost::thread::sleep(xt);
|
||||
}
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock() << ") Phil" << m_id
|
||||
<< ": gotta eat ..." << std::endl;
|
||||
}
|
||||
g_canteen.get(m_id);
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock() << ") Phil" << m_id
|
||||
<< ": mmm ... that's good ..." << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
static void do_thread(void* param) {
|
||||
static_cast<phil*>(param)->run();
|
||||
}
|
||||
|
||||
int m_id;
|
||||
};
|
||||
|
||||
struct thread_adapt
|
||||
{
|
||||
thread_adapt(void (*func)(void*), void* param)
|
||||
: _func(func), _param(param)
|
||||
{
|
||||
}
|
||||
int operator()() const
|
||||
{
|
||||
_func(_param);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void (*_func)(void*);
|
||||
void* _param;
|
||||
};
|
||||
|
||||
class thread_adapter
|
||||
{
|
||||
public:
|
||||
thread_adapter(void (*func)(void*), void* param)
|
||||
: _func(func), _param(param)
|
||||
{
|
||||
}
|
||||
void operator()() const { _func(_param); }
|
||||
private:
|
||||
void (*_func)(void*);
|
||||
void* _param;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
boost::thread thrd_chef(&chef);
|
||||
phil p[] = { phil(0), phil(1), phil(2), phil(3), phil(4) };
|
||||
boost::thread thrd_phil0(thread_adapter(&phil::do_thread, &p[0]));
|
||||
boost::thread thrd_phil1(thread_adapter(&phil::do_thread, &p[1]));
|
||||
boost::thread thrd_phil2(thread_adapter(&phil::do_thread, &p[2]));
|
||||
boost::thread thrd_phil3(thread_adapter(&phil::do_thread, &p[3]));
|
||||
boost::thread thrd_phil4(thread_adapter(&phil::do_thread, &p[4]));
|
||||
|
||||
thrd_chef.join();
|
||||
thrd_phil0.join();
|
||||
thrd_phil1.join();
|
||||
thrd_phil2.join();
|
||||
thrd_phil3.join();
|
||||
thrd_phil4.join();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <iostream>
|
||||
#include <time.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
boost::mutex iomx;
|
||||
};
|
||||
|
||||
class canteen
|
||||
{
|
||||
public:
|
||||
canteen() : m_chickens(0) { }
|
||||
|
||||
void get(int id)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_mutex);
|
||||
while (m_chickens == 0)
|
||||
{
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock() << ") Phil" << id <<
|
||||
": wot, no chickens? I'll WAIT ..." << std::endl;
|
||||
}
|
||||
m_condition.wait(lock);
|
||||
}
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock() << ") Phil" << id <<
|
||||
": those chickens look good ... one please ..." << std::endl;
|
||||
}
|
||||
m_chickens--;
|
||||
}
|
||||
void put(int value)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_mutex);
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock() <<
|
||||
") Chef: ouch ... make room ... this dish is very hot ..." << std::endl;
|
||||
}
|
||||
boost::xtime xt;
|
||||
boost::xtime_get(&xt, boost::TIME_UTC);
|
||||
xt.sec += 3;
|
||||
boost::thread::sleep(xt);
|
||||
m_chickens += value;
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock() <<
|
||||
") Chef: more chickens ... " << m_chickens <<
|
||||
" now available ... NOTIFYING ..." << std::endl;
|
||||
}
|
||||
m_condition.notify_all();
|
||||
}
|
||||
|
||||
private:
|
||||
boost::mutex m_mutex;
|
||||
boost::condition m_condition;
|
||||
int m_chickens;
|
||||
};
|
||||
|
||||
canteen g_canteen;
|
||||
|
||||
void chef()
|
||||
{
|
||||
const int chickens = 4;
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock() << ") Chef: starting ..." << std::endl;
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock() << ") Chef: cooking ..." << std::endl;
|
||||
}
|
||||
boost::xtime xt;
|
||||
boost::xtime_get(&xt, boost::TIME_UTC);
|
||||
xt.sec += 2;
|
||||
boost::thread::sleep(xt);
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock() << ") Chef: " << chickens
|
||||
<< " chickens, ready-to-go ..." << std::endl;
|
||||
}
|
||||
g_canteen.put(chickens);
|
||||
}
|
||||
}
|
||||
|
||||
struct phil
|
||||
{
|
||||
phil(int id) : m_id(id) { }
|
||||
void run() {
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock() << ") Phil" << m_id << ": starting ..." << std::endl;
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
if (m_id > 0)
|
||||
{
|
||||
boost::xtime xt;
|
||||
boost::xtime_get(&xt, boost::TIME_UTC);
|
||||
xt.sec += 3;
|
||||
boost::thread::sleep(xt);
|
||||
}
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock() << ") Phil" << m_id
|
||||
<< ": gotta eat ..." << std::endl;
|
||||
}
|
||||
g_canteen.get(m_id);
|
||||
{
|
||||
boost::mutex::scoped_lock lock(iomx);
|
||||
std::cout << "(" << clock() << ") Phil" << m_id
|
||||
<< ": mmm ... that's good ..." << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
static void do_thread(void* param) {
|
||||
static_cast<phil*>(param)->run();
|
||||
}
|
||||
|
||||
int m_id;
|
||||
};
|
||||
|
||||
struct thread_adapt
|
||||
{
|
||||
thread_adapt(void (*func)(void*), void* param) : _func(func), _param(param) { }
|
||||
int operator()() const
|
||||
{
|
||||
_func(_param);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void (*_func)(void*);
|
||||
void* _param;
|
||||
};
|
||||
|
||||
class thread_adapter
|
||||
{
|
||||
public:
|
||||
thread_adapter(void (*func)(void*), void* param) : _func(func), _param(param) { }
|
||||
void operator()() const { _func(_param); }
|
||||
private:
|
||||
void (*_func)(void*);
|
||||
void* _param;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
boost::thread thrd_chef(&chef);
|
||||
phil p[] = { phil(0), phil(1), phil(2), phil(3), phil(4) };
|
||||
boost::thread thrd_phil0(thread_adapter(&phil::do_thread, &p[0]));
|
||||
boost::thread thrd_phil1(thread_adapter(&phil::do_thread, &p[1]));
|
||||
boost::thread thrd_phil2(thread_adapter(&phil::do_thread, &p[2]));
|
||||
boost::thread thrd_phil3(thread_adapter(&phil::do_thread, &p[3]));
|
||||
boost::thread thrd_phil4(thread_adapter(&phil::do_thread, &p[4]));
|
||||
|
||||
thrd_chef.join();
|
||||
thrd_phil0.join();
|
||||
thrd_phil1.join();
|
||||
thrd_phil2.join();
|
||||
thrd_phil3.join();
|
||||
thrd_phil4.join();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,13 +1,18 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
#include <boost/thread/semaphore.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
# include <windows.h>
|
||||
# include <process.h>
|
||||
# include <windows.h>
|
||||
# include <process.h>
|
||||
#endif
|
||||
|
||||
enum game_state
|
||||
@@ -50,7 +55,10 @@ void player(void* param)
|
||||
{
|
||||
cond.wait(lock);
|
||||
if (state == other)
|
||||
std::cout << "---" << player_name(active) << ": Spurious wakeup!" << std::endl;
|
||||
{
|
||||
std::cout << "---" << player_name(active)
|
||||
<< ": Spurious wakeup!" << std::endl;
|
||||
}
|
||||
} while (state == other);
|
||||
}
|
||||
|
||||
@@ -61,7 +69,10 @@ void player(void* param)
|
||||
|
||||
struct thread_adapt
|
||||
{
|
||||
thread_adapt(void (*func)(void*), void* param) : _func(func), _param(param) { }
|
||||
thread_adapt(void (*func)(void*), void* param)
|
||||
: _func(func), _param(param)
|
||||
{
|
||||
}
|
||||
int operator()() const
|
||||
{
|
||||
_func(_param);
|
||||
@@ -75,7 +86,10 @@ struct thread_adapt
|
||||
class thread_adapter
|
||||
{
|
||||
public:
|
||||
thread_adapter(void (*func)(void*), void* param) : _func(func), _param(param) { }
|
||||
thread_adapter(void (*func)(void*), void* param)
|
||||
: _func(func), _param(param)
|
||||
{
|
||||
}
|
||||
void operator()() const { _func(_param); }
|
||||
private:
|
||||
void (*_func)(void*);
|
||||
35
example/thread.cpp
Normal file
35
example/thread.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <iostream>
|
||||
|
||||
struct thread_alarm
|
||||
{
|
||||
thread_alarm(int secs) : m_secs(secs) { }
|
||||
void operator()()
|
||||
{
|
||||
boost::xtime xt;
|
||||
boost::xtime_get(&xt, boost::TIME_UTC);
|
||||
xt.sec += m_secs;
|
||||
|
||||
boost::thread::sleep(xt);
|
||||
|
||||
std::cout << "alarm sounded..." << std::endl;
|
||||
}
|
||||
|
||||
int m_secs;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int secs = 5;
|
||||
std::cout << "setting alarm for 5 seconds..." << std::endl;
|
||||
thread_alarm alarm(secs);
|
||||
boost::thread thrd(alarm);
|
||||
thrd.join();
|
||||
}
|
||||
25
example/thread_group.cpp
Normal file
25
example/thread_group.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <iostream>
|
||||
|
||||
int count = 0;
|
||||
boost::mutex mutex;
|
||||
|
||||
void increment_count()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(mutex);
|
||||
std::cout << "count = " << ++count << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
boost::thread_group threads;
|
||||
for (int i = 0; i < 10; ++i)
|
||||
threads.create_thread(&increment_count);
|
||||
threads.join_all();
|
||||
}
|
||||
36
example/tss.cpp
Normal file
36
example/tss.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/tss.hpp>
|
||||
#include <cassert>
|
||||
|
||||
boost::thread_specific_ptr<int> value;
|
||||
|
||||
void increment()
|
||||
{
|
||||
int* p = value.get();
|
||||
++*p;
|
||||
}
|
||||
|
||||
void thread_proc()
|
||||
{
|
||||
value.reset(new int(0)); // initialize the thread's storage
|
||||
for (int i=0; i<10; ++i)
|
||||
{
|
||||
increment();
|
||||
int* p = value.get();
|
||||
assert(*p == i+1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
boost::thread_group threads;
|
||||
for (int i=0; i<5; ++i)
|
||||
threads.create_thread(&thread_proc);
|
||||
threads.join_all();
|
||||
}
|
||||
16
example/xtime.cpp
Normal file
16
example/xtime.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
boost::xtime xt;
|
||||
boost::xtime_get(&xt, boost::TIME_UTC);
|
||||
xt.sec += 1;
|
||||
boost::thread::sleep(xt); // Sleep for 1 second
|
||||
}
|
||||
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
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2001
|
||||
* 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.
|
||||
*
|
||||
* Revision History (excluding minor changes for specific compilers)
|
||||
* 8 Feb 01 Initial version.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_ATOMIC_HPP
|
||||
#define BOOST_ATOMIC_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
# error Thread support is unavailable!
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_HAS_WINTHREADS)
|
||||
# include <boost/thread/mutex.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
class atomic_t
|
||||
{
|
||||
public:
|
||||
typedef long value_type;
|
||||
|
||||
friend value_type read(const atomic_t&);
|
||||
friend value_type increment(atomic_t&);
|
||||
friend value_type decrement(atomic_t&);
|
||||
friend value_type swap(atomic_t&, value_type);
|
||||
friend value_type compare_swap(atomic_t&, value_type, value_type);
|
||||
|
||||
explicit atomic_t(value_type val=0)
|
||||
: _value(val)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
volatile value_type _value;
|
||||
#if !defined(BOOST_HAS_WINTHREADS)
|
||||
mutex _mutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern atomic_t::value_type read(const atomic_t&);
|
||||
extern atomic_t::value_type increment(atomic_t&);
|
||||
extern atomic_t::value_type decrement(atomic_t&);
|
||||
extern atomic_t::value_type swap(atomic_t&, atomic_t::value_type);
|
||||
extern atomic_t::value_type compare_swap(atomic_t&, atomic_t::value_type, atomic_t::value_type);
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_ATOMIC_HPP
|
||||
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
|
||||
@@ -1,48 +1,94 @@
|
||||
// Copyright (C) 2001
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_CONDITION_WEK070601_HPP
|
||||
#define BOOST_CONDITION_WEK070601_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
# error Thread support is unavailable!
|
||||
#endif
|
||||
#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();
|
||||
void notify_all();
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -51,7 +97,7 @@ public:
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
|
||||
while (!pred())
|
||||
do_wait(lock.m_mutex);
|
||||
}
|
||||
@@ -61,7 +107,7 @@ public:
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
|
||||
return do_timed_wait(lock.m_mutex, xt);
|
||||
}
|
||||
|
||||
@@ -70,7 +116,7 @@ public:
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
|
||||
while (!pred())
|
||||
{
|
||||
if (!do_timed_wait(lock.m_mutex, xt))
|
||||
@@ -81,76 +127,74 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
detail::condition_impl m_impl;
|
||||
|
||||
template <typename M>
|
||||
void do_wait(M& mutex)
|
||||
{
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
enter_wait();
|
||||
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
m_impl.enter_wait();
|
||||
#endif
|
||||
|
||||
typename M::cv_state state;
|
||||
mutex.do_unlock(state);
|
||||
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)
|
||||
do_wait(state.pmutex);
|
||||
#elif defined(BOOST_HAS_WINTHREADS)
|
||||
do_wait();
|
||||
m_impl.do_wait(state.pmutex);
|
||||
#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
m_impl.do_wait();
|
||||
#endif
|
||||
|
||||
mutex.do_lock(state);
|
||||
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)
|
||||
enter_wait();
|
||||
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
m_impl.enter_wait();
|
||||
#endif
|
||||
|
||||
typename M::cv_state state;
|
||||
mutex.do_unlock(state);
|
||||
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 = do_timed_wait(xt, state.pmutex);
|
||||
#elif defined(BOOST_HAS_WINTHREADS)
|
||||
ret = do_timed_wait(xt);
|
||||
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
|
||||
|
||||
mutex.do_lock(state);
|
||||
lock_ops::lock(mutex, state);
|
||||
#undef lock_ops
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
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)
|
||||
unsigned long m_gate;
|
||||
unsigned long m_queue;
|
||||
unsigned long m_mutex;
|
||||
unsigned m_gone; // # threads that timed out and never made it to the m_queue
|
||||
unsigned long m_blocked; // # threads m_blocked m_waiting for the condition
|
||||
unsigned m_waiting; // # threads m_waiting no longer m_waiting for the condition but still
|
||||
// m_waiting to be removed from the m_queue
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_cond_t m_condition;
|
||||
#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.
|
||||
// 23 May 01 WEKEMPF Removed "duration" timed_waits, as they are too difficult
|
||||
// to use with spurious wakeups.
|
||||
// 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
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
// Copyright (C) 2001
|
||||
// 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.
|
||||
|
||||
// This file is used to configure Boost.Threads during development
|
||||
// in order to decouple dependency on any Boost release. Once
|
||||
// accepted into Boost these contents will be moved to <boost/config>
|
||||
// or some other appropriate build configuration and all
|
||||
// #include <boost/thread/config.hpp> statements will be changed
|
||||
// accordingly.
|
||||
|
||||
#ifndef BOOST_THREAD_CONFIG_WEK070601_HPP
|
||||
#define BOOST_THREAD_CONFIG_WEK070601_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#error "Included <boost/thread/config.hpp>"
|
||||
|
||||
/*// Define if threading support is enabled for the toolset.
|
||||
#undef BOOST_HAS_THREADS
|
||||
|
||||
// Define if threading should be implemented in terms of Win32 threads.
|
||||
#undef BOOST_HAS_WINTHREADS
|
||||
|
||||
// Define if threading should be implemented in terms of POSIX threads.
|
||||
#undef BOOST_HAS_PTHREADS
|
||||
|
||||
// Define if BOOST_HAS_PTHREADS and pthread_delay_np() exists.
|
||||
#undef BOOST_HAS_PTHREAD_DELAY_NP
|
||||
|
||||
// Define if BOOST_HAS_PTHREADS and not BOOST_HAS_PTHREAD_DELAY_NP
|
||||
// but nanosleep can be used instead.
|
||||
#undef BOOST_HAS_NANOSLEEP
|
||||
|
||||
// Define if BOOST_HAS_PTHREADS and pthread_yield() exists.
|
||||
#undef BOOST_HAS_PTHREAD_YIELD
|
||||
|
||||
// Define if BOOST_HAS_PTHREADS and not BOOST_HAS_PTHREAD_YIELD and
|
||||
// sched_yield() exists.
|
||||
#undef BOOST_HAS_SCHED_YIELD
|
||||
|
||||
// Define if gettimeofday() exists.
|
||||
#undef BOOST_HAS_GETTIMEOFDAY
|
||||
|
||||
// Define if not BOOST_HAS_GETTIMEOFDAY and clock_gettime() exists.
|
||||
#undef BOOST_HAS_CLOCK_GETTIME
|
||||
|
||||
// Define if not BOOST_HAS_GETTIMEOFDAY and not BOOST_HAS_CLOCK_GETTIME and
|
||||
// GetSystemTimeAsFileTime() can be called with an FTIME structure.
|
||||
#undef BOOST_HAS_FTIME
|
||||
|
||||
// Define if pthread_mutexattr_settype and pthread_mutexattr_gettype exist.
|
||||
#undef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
|
||||
|
||||
// Here we'll set up known compiler options.
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# if defined(_MT)
|
||||
# define BOOST_HAS_THREADS
|
||||
# endif
|
||||
# define BOOST_HAS_WINTHREADS // comment out this to test pthreads-win32.
|
||||
# if !defined(BOOST_HAS_WINTHREADS)
|
||||
# define BOOST_HAS_PTHREADS
|
||||
# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
|
||||
# define PtW32NoCatchWarn
|
||||
# pragma comment(lib, "pthreadVCE.lib")
|
||||
# endif
|
||||
# define BOOST_HAS_FTIME
|
||||
// pdm: this is for linux - is there a better #define to #if on?
|
||||
// wek: not sure how else to do this, but GNU CC on Win32 should probably
|
||||
// use BOOST_HAS_WINTHREADS, and I expect there will be other
|
||||
// platform specific variations for this compiler toolset. Need
|
||||
// to decide how to handle this.
|
||||
#elif defined( __GNUC__ )
|
||||
# define BOOST_HAS_THREADS
|
||||
# define BOOST_HAS_PTHREADS
|
||||
# define BOOST_HAS_NANOSLEEP
|
||||
# define BOOST_HAS_GETTIMEOFDAY
|
||||
// pdm: From the pthread.h header, one of these macros
|
||||
// must be defined for this stuff to exist.
|
||||
// wek: This seems like a harmless enough method to determine these
|
||||
// switches, but one should note that some implementations may not
|
||||
// use these. Notably, pthreads-win32 doesn't define either
|
||||
// __USE_UNIX98 or __USE_GNU.
|
||||
# if defined( __USE_UNIX98 )
|
||||
# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
|
||||
# elif defined( __USE_GNU )
|
||||
# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
|
||||
# define BOOST_HAS_PTHREAD_YIELD
|
||||
# endif
|
||||
#endif*/
|
||||
|
||||
#endif // BOOST_THREAD_CONFIG_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
|
||||
@@ -1,17 +1,14 @@
|
||||
// Copyright (C) 2001
|
||||
// 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)
|
||||
|
||||
#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>
|
||||
|
||||
@@ -20,153 +17,193 @@ namespace boost {
|
||||
class condition;
|
||||
struct xtime;
|
||||
|
||||
namespace detail { namespace thread {
|
||||
namespace detail { namespace thread {
|
||||
|
||||
template <typename Mutex>
|
||||
class scoped_lock : private noncopyable
|
||||
template <typename Mutex>
|
||||
class lock_ops : private noncopyable
|
||||
{
|
||||
private:
|
||||
lock_ops() { }
|
||||
|
||||
public:
|
||||
typedef typename Mutex::cv_state lock_state;
|
||||
|
||||
static void lock(Mutex& m)
|
||||
{
|
||||
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();
|
||||
m_mutex.do_lock();
|
||||
m_locked = true;
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if (!m_locked) throw lock_error();
|
||||
m_mutex.do_unlock();
|
||||
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
|
||||
m.do_lock();
|
||||
}
|
||||
static bool trylock(Mutex& m)
|
||||
{
|
||||
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();
|
||||
m_mutex.do_lock();
|
||||
m_locked = true;
|
||||
}
|
||||
bool try_lock()
|
||||
{
|
||||
if (m_locked) throw lock_error();
|
||||
return (m_locked = m_mutex.do_trylock());
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if (!m_locked) throw lock_error();
|
||||
m_mutex.do_unlock();
|
||||
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
|
||||
return m.do_trylock();
|
||||
}
|
||||
static bool timedlock(Mutex& m, const xtime& xt)
|
||||
{
|
||||
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();
|
||||
m_mutex.do_lock();
|
||||
m_locked = true;
|
||||
}
|
||||
bool timed_lock(const xtime& xt)
|
||||
{
|
||||
if (m_locked) throw lock_error();
|
||||
return (m_locked = m_mutex.do_timedlock(xt));
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if (!m_locked) throw lock_error();
|
||||
m_mutex.do_unlock();
|
||||
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;
|
||||
};
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace thread
|
||||
} // namespace detail
|
||||
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.
|
||||
|
||||
#endif // BOOST_XLOCK_WEK070601_HPP
|
||||
// 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)
|
||||
@@ -1,46 +1,94 @@
|
||||
// Copyright (C) 2001
|
||||
// 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.
|
||||
|
||||
// This file is used to configure Boost.Threads during development
|
||||
// in order to decouple dependency on any Boost release. Once
|
||||
// accepted into Boost these contents will be moved to <boost/config>
|
||||
// or some other appropriate build configuration and all
|
||||
// #include <boost/thread/config.hpp> statements will be changed
|
||||
// accordingly.
|
||||
// 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 lock_error : public std::runtime_error
|
||||
class BOOST_THREAD_DECL thread_exception : public std::exception
|
||||
{
|
||||
protected:
|
||||
thread_exception();
|
||||
thread_exception(int sys_err_code);
|
||||
|
||||
public:
|
||||
lock_error() : std::runtime_error("thread lock error") { }
|
||||
~thread_exception() throw();
|
||||
|
||||
int native_error() const;
|
||||
|
||||
private:
|
||||
int m_sys_err;
|
||||
};
|
||||
|
||||
class thread_resource_error : public std::runtime_error
|
||||
class BOOST_THREAD_DECL lock_error : public thread_exception
|
||||
{
|
||||
public:
|
||||
thread_resource_error() : std::runtime_error("thread resource error") { }
|
||||
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.
|
||||
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
// Copyright (C) 2001
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_MUTEX_WEK070601_HPP
|
||||
#define BOOST_MUTEX_WEK070601_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
# error Thread support is unavailable!
|
||||
#endif
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/detail/lock.hpp>
|
||||
@@ -24,22 +16,30 @@
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_MPTASKS)
|
||||
# include "scoped_critical_region.hpp"
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
class condition;
|
||||
struct xtime;
|
||||
|
||||
class mutex : private noncopyable
|
||||
// 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::scoped_lock<mutex>;
|
||||
friend class condition;
|
||||
|
||||
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;
|
||||
@@ -48,6 +48,10 @@ private:
|
||||
{
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
struct cv_state
|
||||
{
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
void do_unlock();
|
||||
@@ -55,25 +59,28 @@ private:
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long m_mutex;
|
||||
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 try_mutex : private noncopyable
|
||||
class BOOST_THREAD_DECL try_mutex
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::scoped_lock<try_mutex>;
|
||||
friend class detail::thread::scoped_try_lock<try_mutex>;
|
||||
friend class condition;
|
||||
|
||||
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;
|
||||
@@ -82,6 +89,10 @@ private:
|
||||
{
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
struct cv_state
|
||||
{
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
@@ -90,27 +101,29 @@ private:
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long m_mutex;
|
||||
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 timed_mutex : private noncopyable
|
||||
class BOOST_THREAD_DECL timed_mutex
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::scoped_lock<timed_mutex>;
|
||||
friend class detail::thread::scoped_try_lock<timed_mutex>;
|
||||
friend class detail::thread::scoped_timed_lock<timed_mutex>;
|
||||
friend class condition;
|
||||
|
||||
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;
|
||||
@@ -119,6 +132,10 @@ private:
|
||||
{
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
struct cv_state
|
||||
{
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
@@ -126,21 +143,27 @@ private:
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long m_mutex;
|
||||
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
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
// Copyright (C) 2001
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_ONCE_WEK080101_HPP
|
||||
#define BOOST_ONCE_WEK080101_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
# error Thread support is unavailable!
|
||||
#endif
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
@@ -26,16 +18,16 @@ namespace boost {
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
|
||||
typedef pthread_once_t once_flag;
|
||||
const once_flag once_init = PTHREAD_ONCE_INIT;
|
||||
#define BOOST_ONCE_INIT PTHREAD_ONCE_INIT
|
||||
|
||||
#elif defined(BOOST_HAS_WINTHREADS)
|
||||
#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
|
||||
typedef bool once_flag;
|
||||
const once_flag once_init = false;
|
||||
typedef long once_flag;
|
||||
#define BOOST_ONCE_INIT 0
|
||||
|
||||
#endif
|
||||
|
||||
void call_once(void (*func)(), once_flag& flag);
|
||||
void BOOST_THREAD_DECL call_once(void (*func)(), once_flag& flag);
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
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.
|
||||
@@ -1,21 +1,13 @@
|
||||
// Copyright (C) 2001
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_RECURSIVE_MUTEX_WEK070601_HPP
|
||||
#define BOOST_RECURSIVE_MUTEX_WEK070601_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
# error Thread support is unavailable!
|
||||
#endif
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/detail/lock.hpp>
|
||||
@@ -24,24 +16,32 @@
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_MPTASKS)
|
||||
# include "scoped_critical_region.hpp"
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
class condition;
|
||||
struct xtime;
|
||||
|
||||
class recursive_mutex : private noncopyable
|
||||
// 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::scoped_lock<recursive_mutex>;
|
||||
friend class condition;
|
||||
|
||||
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)
|
||||
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
typedef std::size_t cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
@@ -56,7 +56,8 @@ private:
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long m_mutex;
|
||||
void* m_mutex;
|
||||
bool m_critical_section;
|
||||
unsigned long m_count;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
@@ -66,24 +67,28 @@ private:
|
||||
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 recursive_try_mutex : private noncopyable
|
||||
class BOOST_THREAD_DECL recursive_try_mutex
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::scoped_lock<recursive_try_mutex>;
|
||||
friend class detail::thread::scoped_try_lock<recursive_try_mutex>;
|
||||
friend class condition;
|
||||
|
||||
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;
|
||||
|
||||
typedef detail::thread::scoped_try_lock<
|
||||
recursive_try_mutex> scoped_try_lock;
|
||||
|
||||
recursive_try_mutex();
|
||||
~recursive_try_mutex();
|
||||
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
typedef std::size_t cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
@@ -97,9 +102,10 @@ private:
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long m_mutex;
|
||||
void* m_mutex;
|
||||
bool m_critical_section;
|
||||
unsigned long m_count;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
@@ -109,26 +115,30 @@ private:
|
||||
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 recursive_timed_mutex : private noncopyable
|
||||
class BOOST_THREAD_DECL recursive_timed_mutex
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::scoped_lock<recursive_timed_mutex>;
|
||||
friend class detail::thread::scoped_try_lock<recursive_timed_mutex>;
|
||||
friend class detail::thread::scoped_timed_lock<recursive_timed_mutex>;
|
||||
friend class condition;
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
typedef std::size_t cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
@@ -143,9 +153,9 @@ private:
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long m_mutex;
|
||||
void* m_mutex;
|
||||
unsigned long m_count;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
@@ -153,15 +163,22 @@ private:
|
||||
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.
|
||||
|
||||
#endif // BOOST_RECURSIVE_MUTEX_WEK070601_HPP
|
||||
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
// Copyright (C) 2001
|
||||
// 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.
|
||||
|
||||
#ifndef BOOST_SEMAPHORE_WEK070601_HPP
|
||||
#define BOOST_SEMAPHORE_WEK070601_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
# error Thread support is unavailable!
|
||||
#endif
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct xtime;
|
||||
|
||||
class semaphore : private noncopyable
|
||||
{
|
||||
public:
|
||||
explicit semaphore(unsigned count=0, unsigned max=0);
|
||||
~semaphore();
|
||||
|
||||
bool up(unsigned count=1, unsigned* prev=0);
|
||||
void down();
|
||||
bool down(const xtime& xt);
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long m_sema;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
pthread_cond_t m_condition;
|
||||
unsigned m_available;
|
||||
unsigned m_max;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
|
||||
|
||||
#endif // BOOST_SEMAPHORE_WEK070601_HPP
|
||||
@@ -1,21 +1,13 @@
|
||||
// Copyright (C) 2001
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_THREAD_WEK070601_HPP
|
||||
#define BOOST_THREAD_WEK070601_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
# error Thread support is unavailable!
|
||||
#endif
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/function.hpp>
|
||||
@@ -26,13 +18,20 @@
|
||||
#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;
|
||||
|
||||
class thread : private noncopyable
|
||||
// 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();
|
||||
@@ -49,16 +48,19 @@ public:
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long m_thread;
|
||||
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 thread_group : private noncopyable
|
||||
class BOOST_THREAD_DECL thread_group : private noncopyable
|
||||
{
|
||||
public:
|
||||
thread_group();
|
||||
@@ -68,12 +70,15 @@ public:
|
||||
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:
|
||||
|
||||
@@ -1,72 +1,127 @@
|
||||
// Copyright (C) 2001
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_TSS_WEK070601_HPP
|
||||
#define BOOST_TSS_WEK070601_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
# error Thread support is unavailable!
|
||||
#endif
|
||||
#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 {
|
||||
|
||||
namespace detail {
|
||||
class tss : private noncopyable
|
||||
// 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
|
||||
{
|
||||
public:
|
||||
tss(void (*cleanup)(void*)=0);
|
||||
~tss();
|
||||
|
||||
void* get() const;
|
||||
bool set(void* value);
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
unsigned long m_key;
|
||||
void (*m_cleanup)(void*);
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_key_t m_key;
|
||||
#endif
|
||||
};
|
||||
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(&thread_specific_ptr<T>::cleanup) { }
|
||||
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(); m_tss.set(0); return temp; }
|
||||
void reset(T* p=0) { T* cur = get(); if (cur == p) return; delete cur; m_tss.set(p); }
|
||||
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(void* p) { delete static_cast<T*>(p); }
|
||||
|
||||
mutable detail::tss m_tss;
|
||||
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.
|
||||
|
||||
#endif // BOOST_TSS_WEK070601_HPP
|
||||
|
||||
// 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().
|
||||
|
||||
@@ -1,50 +1,54 @@
|
||||
// Copyright (C) 2001
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_XTIME_WEK070601_HPP
|
||||
#define BOOST_XTIME_WEK070601_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
enum
|
||||
enum xtime_clock_types
|
||||
{
|
||||
TIME_UTC=1,
|
||||
TIME_TAI,
|
||||
TIME_MONOTONIC,
|
||||
TIME_PROCESS,
|
||||
TIME_THREAD,
|
||||
TIME_LOCAL,
|
||||
TIME_SYNC,
|
||||
TIME_RESOLUTION
|
||||
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)
|
||||
int_fast32_t sec;
|
||||
typedef int_fast32_t xtime_sec_t; //INT_FAST32_MIN <= sec <= INT_FAST32_MAX
|
||||
#else
|
||||
int_fast64_t sec;
|
||||
typedef int_fast64_t xtime_sec_t; //INT_FAST64_MIN <= sec <= INT_FAST64_MAX
|
||||
#endif
|
||||
int_fast32_t nsec;
|
||||
|
||||
typedef int_fast32_t xtime_nsec_t; //0 <= xtime.nsec < NANOSECONDS_PER_SECOND
|
||||
|
||||
xtime_sec_t sec;
|
||||
xtime_nsec_t nsec;
|
||||
};
|
||||
|
||||
int xtime_get(struct xtime* xtp, int clock_type);
|
||||
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
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
|
||||
#endif // BOOST_XTIME_WEK070601_HPP
|
||||
|
||||
#endif //BOOST_XTIME_WEK070601_HPP
|
||||
|
||||
13
index.html
Normal file
13
index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!-- 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">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to <a href="doc/index.html">doc/index.html</a>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2001
|
||||
* 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.
|
||||
*
|
||||
* Revision History (excluding minor changes for specific compilers)
|
||||
* 8 Feb 01 Initial version.
|
||||
*/
|
||||
|
||||
#include <boost/thread/atomic.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
atomic_t::value_type read(const atomic_t& x)
|
||||
{
|
||||
return x._value;
|
||||
}
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
atomic_t::value_type increment(atomic_t& x)
|
||||
{
|
||||
return InterlockedIncrement(const_cast<long*>(&x._value));
|
||||
}
|
||||
|
||||
atomic_t::value_type decrement(atomic_t& x)
|
||||
{
|
||||
return InterlockedDecrement(const_cast<long*>(&x._value));
|
||||
}
|
||||
|
||||
atomic_t::value_type swap(atomic_t& x, atomic_t::value_type y)
|
||||
{
|
||||
return InterlockedExchange(const_cast<long*>(&x._value), y);
|
||||
}
|
||||
|
||||
atomic_t::value_type compare_swap(atomic_t& x, atomic_t::value_type y, atomic_t::value_type z)
|
||||
{
|
||||
return InterlockedCompareExchange(const_cast<long*>(&x._value), y, z);
|
||||
}
|
||||
#else
|
||||
atomic_t::value_type increment(atomic_t& x)
|
||||
{
|
||||
mutex::lock lock(x._mutex);
|
||||
return ++x._value;
|
||||
}
|
||||
|
||||
atomic_t::value_type decrement(atomic_t& x)
|
||||
{
|
||||
mutex::lock lock(x._mutex);
|
||||
return --x._value;
|
||||
}
|
||||
|
||||
atomic_t::value_type swap(atomic_t& x, atomic_t::value_type y)
|
||||
{
|
||||
mutex::lock lock(x._mutex);
|
||||
atomic_t::value_type temp = x._value;
|
||||
x._value = y;
|
||||
return temp;
|
||||
}
|
||||
|
||||
atomic_t::value_type compare_swap(atomic_t& x, atomic_t::value_type y, atomic_t::value_type z)
|
||||
{
|
||||
mutex::lock lock(x._mutex);
|
||||
atomic_t::value_type temp = x._value;
|
||||
if (temp == z)
|
||||
x._value = y;
|
||||
return temp;
|
||||
}
|
||||
#endif
|
||||
} // namespace boost
|
||||
42
src/barrier.cpp
Normal file
42
src/barrier.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/barrier.hpp>
|
||||
#include <string> // see http://article.gmane.org/gmane.comp.lib.boost.devel/106981
|
||||
|
||||
namespace boost {
|
||||
|
||||
barrier::barrier(unsigned int count)
|
||||
: m_threshold(count), m_count(count), m_generation(0)
|
||||
{
|
||||
if (count == 0)
|
||||
throw std::invalid_argument("count cannot be zero.");
|
||||
}
|
||||
|
||||
barrier::~barrier()
|
||||
{
|
||||
}
|
||||
|
||||
bool barrier::wait()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_mutex);
|
||||
unsigned int gen = m_generation;
|
||||
|
||||
if (--m_count == 0)
|
||||
{
|
||||
m_generation++;
|
||||
m_count = m_threshold;
|
||||
m_cond.notify_all();
|
||||
return true;
|
||||
}
|
||||
|
||||
while (gen == m_generation)
|
||||
m_cond.wait(lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
@@ -1,63 +1,69 @@
|
||||
// Copyright (C) 2001
|
||||
// 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/condition.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <cassert>
|
||||
#include "timeconv.inl"
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
# define NOMINMAX
|
||||
# ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
# endif
|
||||
# include <windows.h>
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
# include <errno.h>
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
# include <MacErrors.h>
|
||||
# include "mac/init.hpp"
|
||||
# include "mac/safe.hpp"
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
condition::condition()
|
||||
condition_impl::condition_impl()
|
||||
: m_gone(0), m_blocked(0), m_waiting(0)
|
||||
{
|
||||
m_gate = reinterpret_cast<unsigned long>(CreateSemaphore(0, 1, 1, 0));
|
||||
m_queue = reinterpret_cast<unsigned long>(CreateSemaphore(0, 0, std::numeric_limits<long>::max(), 0));
|
||||
m_mutex = reinterpret_cast<unsigned long>(CreateMutex(0, 0, 0));
|
||||
m_gate = reinterpret_cast<void*>(CreateSemaphore(0, 1, 1, 0));
|
||||
m_queue = reinterpret_cast<void*>(
|
||||
CreateSemaphore(0, 0, (std::numeric_limits<long>::max)(), 0));
|
||||
m_mutex = reinterpret_cast<void*>(CreateMutex(0, 0, 0));
|
||||
|
||||
if (!m_gate || !m_queue || !m_mutex)
|
||||
{
|
||||
int res = 0;
|
||||
if (m_gate)
|
||||
{
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(m_gate));
|
||||
assert(res);
|
||||
}
|
||||
if (m_queue)
|
||||
{
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(m_queue));
|
||||
assert(res);
|
||||
}
|
||||
if (m_mutex)
|
||||
{
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
}
|
||||
if (m_gate)
|
||||
{
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(m_gate));
|
||||
assert(res);
|
||||
}
|
||||
if (m_queue)
|
||||
{
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(m_queue));
|
||||
assert(res);
|
||||
}
|
||||
if (m_mutex)
|
||||
{
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
}
|
||||
|
||||
throw thread_resource_error();
|
||||
}
|
||||
}
|
||||
|
||||
condition::~condition()
|
||||
condition_impl::~condition_impl()
|
||||
{
|
||||
int res = 0;
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(m_gate));
|
||||
@@ -68,7 +74,7 @@ condition::~condition()
|
||||
assert(res);
|
||||
}
|
||||
|
||||
void condition::notify_one()
|
||||
void condition_impl::notify_one()
|
||||
{
|
||||
unsigned signals = 0;
|
||||
|
||||
@@ -87,6 +93,7 @@ void condition::notify_one()
|
||||
|
||||
++m_waiting;
|
||||
--m_blocked;
|
||||
signals = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -107,19 +114,19 @@ void condition::notify_one()
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
|
||||
assert(res);
|
||||
}
|
||||
}
|
||||
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
|
||||
if (signals)
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0);
|
||||
assert(res);
|
||||
|
||||
if (signals)
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0);
|
||||
assert(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void condition::notify_all()
|
||||
void condition_impl::notify_all()
|
||||
{
|
||||
unsigned signals = 0;
|
||||
|
||||
@@ -158,19 +165,19 @@ void condition::notify_all()
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
|
||||
assert(res);
|
||||
}
|
||||
}
|
||||
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
|
||||
if (signals)
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0);
|
||||
assert(res);
|
||||
|
||||
if (signals)
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0);
|
||||
assert(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void condition::enter_wait()
|
||||
void condition_impl::enter_wait()
|
||||
{
|
||||
int res = 0;
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
|
||||
@@ -180,12 +187,12 @@ void condition::enter_wait()
|
||||
assert(res);
|
||||
}
|
||||
|
||||
void condition::do_wait()
|
||||
void condition_impl::do_wait()
|
||||
{
|
||||
int res = 0;
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
|
||||
|
||||
unsigned was_waiting=0;
|
||||
unsigned was_gone=0;
|
||||
|
||||
@@ -199,7 +206,8 @@ void condition::do_wait()
|
||||
{
|
||||
if (m_blocked != 0)
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0); // open m_gate
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1,
|
||||
0); // open m_gate
|
||||
assert(res);
|
||||
was_waiting = 0;
|
||||
}
|
||||
@@ -207,7 +215,7 @@ void condition::do_wait()
|
||||
m_gone = 0;
|
||||
}
|
||||
}
|
||||
else if (++m_gone == (std::numeric_limits<unsigned>::max() / 2))
|
||||
else if (++m_gone == ((std::numeric_limits<unsigned>::max)() / 2))
|
||||
{
|
||||
// timeout occured, normalize the m_gone count
|
||||
// this may occur if many calls to wait with a timeout are made and
|
||||
@@ -227,7 +235,8 @@ void condition::do_wait()
|
||||
for (/**/ ; was_gone; --was_gone)
|
||||
{
|
||||
// better now than spurious later
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), INFINITE);
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue),
|
||||
INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
}
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
|
||||
@@ -235,17 +244,32 @@ void condition::do_wait()
|
||||
}
|
||||
}
|
||||
|
||||
bool condition::do_timed_wait(const xtime& xt)
|
||||
bool condition_impl::do_timed_wait(const xtime& xt)
|
||||
{
|
||||
unsigned milliseconds;
|
||||
to_duration(xt, milliseconds);
|
||||
bool ret = false;
|
||||
unsigned int res = 0;
|
||||
|
||||
int res = 0;
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), milliseconds);
|
||||
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
|
||||
for (;;)
|
||||
{
|
||||
int milliseconds;
|
||||
to_duration(xt, milliseconds);
|
||||
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue),
|
||||
milliseconds);
|
||||
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
|
||||
ret = (res == WAIT_OBJECT_0);
|
||||
|
||||
if (res == WAIT_TIMEOUT)
|
||||
{
|
||||
xtime cur;
|
||||
xtime_get(&cur, TIME_UTC);
|
||||
if (xtime_cmp(xt, cur) > 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
bool ret = (res == WAIT_OBJECT_0);
|
||||
|
||||
unsigned was_waiting=0;
|
||||
unsigned was_gone=0;
|
||||
|
||||
@@ -266,7 +290,8 @@ bool condition::do_timed_wait(const xtime& xt)
|
||||
{
|
||||
if (m_blocked != 0)
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0); // open m_gate
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1,
|
||||
0); // open m_gate
|
||||
assert(res);
|
||||
was_waiting = 0;
|
||||
}
|
||||
@@ -274,7 +299,7 @@ bool condition::do_timed_wait(const xtime& xt)
|
||||
m_gone = 0;
|
||||
}
|
||||
}
|
||||
else if (++m_gone == (std::numeric_limits<unsigned>::max() / 2))
|
||||
else if (++m_gone == ((std::numeric_limits<unsigned>::max)() / 2))
|
||||
{
|
||||
// timeout occured, normalize the m_gone count
|
||||
// this may occur if many calls to wait with a timeout are made and
|
||||
@@ -294,7 +319,8 @@ bool condition::do_timed_wait(const xtime& xt)
|
||||
for (/**/ ; was_gone; --was_gone)
|
||||
{
|
||||
// better now than spurious later
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), INFINITE);
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue),
|
||||
INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
}
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
|
||||
@@ -304,7 +330,7 @@ bool condition::do_timed_wait(const xtime& xt)
|
||||
return ret;
|
||||
}
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
condition::condition()
|
||||
condition_impl::condition_impl()
|
||||
{
|
||||
int res = 0;
|
||||
res = pthread_cond_init(&m_condition, 0);
|
||||
@@ -312,35 +338,35 @@ condition::condition()
|
||||
throw thread_resource_error();
|
||||
}
|
||||
|
||||
condition::~condition()
|
||||
condition_impl::~condition_impl()
|
||||
{
|
||||
int res = 0;
|
||||
res = pthread_cond_destroy(&m_condition);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void condition::notify_one()
|
||||
void condition_impl::notify_one()
|
||||
{
|
||||
int res = 0;
|
||||
res = pthread_cond_signal(&m_condition);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void condition::notify_all()
|
||||
void condition_impl::notify_all()
|
||||
{
|
||||
int res = 0;
|
||||
res = pthread_cond_broadcast(&m_condition);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void condition::do_wait(pthread_mutex_t* pmutex)
|
||||
void condition_impl::do_wait(pthread_mutex_t* pmutex)
|
||||
{
|
||||
int res = 0;
|
||||
res = pthread_cond_wait(&m_condition, pmutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
bool condition::do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex)
|
||||
bool condition_impl::do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex)
|
||||
{
|
||||
timespec ts;
|
||||
to_timespec(xt, ts);
|
||||
@@ -351,10 +377,296 @@ bool condition::do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex)
|
||||
|
||||
return res != ETIMEDOUT;
|
||||
}
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
|
||||
using threads::mac::detail::safe_enter_critical_region;
|
||||
using threads::mac::detail::safe_wait_on_semaphore;
|
||||
|
||||
condition_impl::condition_impl()
|
||||
: m_gone(0), m_blocked(0), m_waiting(0)
|
||||
{
|
||||
threads::mac::detail::thread_init();
|
||||
|
||||
OSStatus lStatus = noErr;
|
||||
|
||||
lStatus = MPCreateSemaphore(1, 1, &m_gate);
|
||||
if(lStatus == noErr)
|
||||
lStatus = MPCreateSemaphore(ULONG_MAX, 0, &m_queue);
|
||||
|
||||
if(lStatus != noErr || !m_gate || !m_queue)
|
||||
{
|
||||
if (m_gate)
|
||||
{
|
||||
lStatus = MPDeleteSemaphore(m_gate);
|
||||
assert(lStatus == noErr);
|
||||
}
|
||||
if (m_queue)
|
||||
{
|
||||
lStatus = MPDeleteSemaphore(m_queue);
|
||||
assert(lStatus == noErr);
|
||||
}
|
||||
|
||||
throw thread_resource_error();
|
||||
}
|
||||
}
|
||||
|
||||
condition_impl::~condition_impl()
|
||||
{
|
||||
OSStatus lStatus = noErr;
|
||||
lStatus = MPDeleteSemaphore(m_gate);
|
||||
assert(lStatus == noErr);
|
||||
lStatus = MPDeleteSemaphore(m_queue);
|
||||
assert(lStatus == noErr);
|
||||
}
|
||||
|
||||
void condition_impl::notify_one()
|
||||
{
|
||||
unsigned signals = 0;
|
||||
|
||||
OSStatus lStatus = noErr;
|
||||
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
|
||||
m_mutex_mutex);
|
||||
assert(lStatus == noErr);
|
||||
|
||||
if (m_waiting != 0) // the m_gate is already closed
|
||||
{
|
||||
if (m_blocked == 0)
|
||||
{
|
||||
lStatus = MPExitCriticalRegion(m_mutex);
|
||||
assert(lStatus == noErr);
|
||||
return;
|
||||
}
|
||||
|
||||
++m_waiting;
|
||||
--m_blocked;
|
||||
}
|
||||
else
|
||||
{
|
||||
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
|
||||
assert(lStatus == noErr);
|
||||
if (m_blocked > m_gone)
|
||||
{
|
||||
if (m_gone != 0)
|
||||
{
|
||||
m_blocked -= m_gone;
|
||||
m_gone = 0;
|
||||
}
|
||||
signals = m_waiting = 1;
|
||||
--m_blocked;
|
||||
}
|
||||
else
|
||||
{
|
||||
lStatus = MPSignalSemaphore(m_gate);
|
||||
assert(lStatus == noErr);
|
||||
}
|
||||
|
||||
lStatus = MPExitCriticalRegion(m_mutex);
|
||||
assert(lStatus == noErr);
|
||||
|
||||
while (signals)
|
||||
{
|
||||
lStatus = MPSignalSemaphore(m_queue);
|
||||
assert(lStatus == noErr);
|
||||
--signals;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void condition_impl::notify_all()
|
||||
{
|
||||
unsigned signals = 0;
|
||||
|
||||
OSStatus lStatus = noErr;
|
||||
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
|
||||
m_mutex_mutex);
|
||||
assert(lStatus == noErr);
|
||||
|
||||
if (m_waiting != 0) // the m_gate is already closed
|
||||
{
|
||||
if (m_blocked == 0)
|
||||
{
|
||||
lStatus = MPExitCriticalRegion(m_mutex);
|
||||
assert(lStatus == noErr);
|
||||
return;
|
||||
}
|
||||
|
||||
m_waiting += (signals = m_blocked);
|
||||
m_blocked = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
|
||||
assert(lStatus == noErr);
|
||||
if (m_blocked > m_gone)
|
||||
{
|
||||
if (m_gone != 0)
|
||||
{
|
||||
m_blocked -= m_gone;
|
||||
m_gone = 0;
|
||||
}
|
||||
signals = m_waiting = m_blocked;
|
||||
m_blocked = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
lStatus = MPSignalSemaphore(m_gate);
|
||||
assert(lStatus == noErr);
|
||||
}
|
||||
|
||||
lStatus = MPExitCriticalRegion(m_mutex);
|
||||
assert(lStatus == noErr);
|
||||
|
||||
while (signals)
|
||||
{
|
||||
lStatus = MPSignalSemaphore(m_queue);
|
||||
assert(lStatus == noErr);
|
||||
--signals;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void condition_impl::enter_wait()
|
||||
{
|
||||
OSStatus lStatus = noErr;
|
||||
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
|
||||
assert(lStatus == noErr);
|
||||
++m_blocked;
|
||||
lStatus = MPSignalSemaphore(m_gate);
|
||||
assert(lStatus == noErr);
|
||||
}
|
||||
|
||||
void condition_impl::do_wait()
|
||||
{
|
||||
OSStatus lStatus = noErr;
|
||||
lStatus = safe_wait_on_semaphore(m_queue, kDurationForever);
|
||||
assert(lStatus == noErr);
|
||||
|
||||
unsigned was_waiting=0;
|
||||
unsigned was_gone=0;
|
||||
|
||||
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
|
||||
m_mutex_mutex);
|
||||
assert(lStatus == noErr);
|
||||
was_waiting = m_waiting;
|
||||
was_gone = m_gone;
|
||||
if (was_waiting != 0)
|
||||
{
|
||||
if (--m_waiting == 0)
|
||||
{
|
||||
if (m_blocked != 0)
|
||||
{
|
||||
lStatus = MPSignalSemaphore(m_gate); // open m_gate
|
||||
assert(lStatus == noErr);
|
||||
was_waiting = 0;
|
||||
}
|
||||
else if (m_gone != 0)
|
||||
m_gone = 0;
|
||||
}
|
||||
}
|
||||
else if (++m_gone == ((std::numeric_limits<unsigned>::max)() / 2))
|
||||
{
|
||||
// timeout occured, normalize the m_gone count
|
||||
// this may occur if many calls to wait with a timeout are made and
|
||||
// no call to notify_* is made
|
||||
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
|
||||
assert(lStatus == noErr);
|
||||
m_blocked -= m_gone;
|
||||
lStatus = MPSignalSemaphore(m_gate);
|
||||
assert(lStatus == noErr);
|
||||
m_gone = 0;
|
||||
}
|
||||
lStatus = MPExitCriticalRegion(m_mutex);
|
||||
assert(lStatus == noErr);
|
||||
|
||||
if (was_waiting == 1)
|
||||
{
|
||||
for (/**/ ; was_gone; --was_gone)
|
||||
{
|
||||
// better now than spurious later
|
||||
lStatus = safe_wait_on_semaphore(m_queue, kDurationForever);
|
||||
assert(lStatus == noErr);
|
||||
}
|
||||
lStatus = MPSignalSemaphore(m_gate);
|
||||
assert(lStatus == noErr);
|
||||
}
|
||||
}
|
||||
|
||||
bool condition_impl::do_timed_wait(const xtime& xt)
|
||||
{
|
||||
int milliseconds;
|
||||
to_duration(xt, milliseconds);
|
||||
|
||||
OSStatus lStatus = noErr;
|
||||
lStatus = safe_wait_on_semaphore(m_queue, milliseconds);
|
||||
assert(lStatus == noErr || lStatus == kMPTimeoutErr);
|
||||
|
||||
bool ret = (lStatus == noErr);
|
||||
|
||||
unsigned was_waiting=0;
|
||||
unsigned was_gone=0;
|
||||
|
||||
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
|
||||
m_mutex_mutex);
|
||||
assert(lStatus == noErr);
|
||||
was_waiting = m_waiting;
|
||||
was_gone = m_gone;
|
||||
if (was_waiting != 0)
|
||||
{
|
||||
if (!ret) // timeout
|
||||
{
|
||||
if (m_blocked != 0)
|
||||
--m_blocked;
|
||||
else
|
||||
++m_gone; // count spurious wakeups
|
||||
}
|
||||
if (--m_waiting == 0)
|
||||
{
|
||||
if (m_blocked != 0)
|
||||
{
|
||||
lStatus = MPSignalSemaphore(m_gate); // open m_gate
|
||||
assert(lStatus == noErr);
|
||||
was_waiting = 0;
|
||||
}
|
||||
else if (m_gone != 0)
|
||||
m_gone = 0;
|
||||
}
|
||||
}
|
||||
else if (++m_gone == ((std::numeric_limits<unsigned>::max)() / 2))
|
||||
{
|
||||
// timeout occured, normalize the m_gone count
|
||||
// this may occur if many calls to wait with a timeout are made and
|
||||
// no call to notify_* is made
|
||||
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
|
||||
assert(lStatus == noErr);
|
||||
m_blocked -= m_gone;
|
||||
lStatus = MPSignalSemaphore(m_gate);
|
||||
assert(lStatus == noErr);
|
||||
m_gone = 0;
|
||||
}
|
||||
lStatus = MPExitCriticalRegion(m_mutex);
|
||||
assert(lStatus == noErr);
|
||||
|
||||
if (was_waiting == 1)
|
||||
{
|
||||
for (/**/ ; was_gone; --was_gone)
|
||||
{
|
||||
// better now than spurious later
|
||||
lStatus = safe_wait_on_semaphore(m_queue, kDurationForever);
|
||||
assert(lStatus == noErr);
|
||||
}
|
||||
lStatus = MPSignalSemaphore(m_gate);
|
||||
assert(lStatus == noErr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
|
||||
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
|
||||
|
||||
124
src/exceptions.cpp
Normal file
124
src/exceptions.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
// 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)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
|
||||
thread_exception::thread_exception()
|
||||
: m_sys_err(0)
|
||||
{
|
||||
}
|
||||
|
||||
thread_exception::thread_exception(int sys_err_code)
|
||||
: m_sys_err(sys_err_code)
|
||||
{
|
||||
}
|
||||
|
||||
thread_exception::~thread_exception() throw()
|
||||
{
|
||||
}
|
||||
|
||||
int thread_exception::native_error() const
|
||||
{
|
||||
return m_sys_err;
|
||||
}
|
||||
|
||||
lock_error::lock_error()
|
||||
{
|
||||
}
|
||||
|
||||
lock_error::lock_error(int sys_err_code)
|
||||
: thread_exception(sys_err_code)
|
||||
{
|
||||
}
|
||||
|
||||
lock_error::~lock_error() throw()
|
||||
{
|
||||
}
|
||||
|
||||
const char* lock_error::what() const throw()
|
||||
{
|
||||
return "boost::lock_error";
|
||||
}
|
||||
|
||||
thread_resource_error::thread_resource_error()
|
||||
{
|
||||
}
|
||||
|
||||
thread_resource_error::thread_resource_error(int sys_err_code)
|
||||
: thread_exception(sys_err_code)
|
||||
{
|
||||
}
|
||||
|
||||
thread_resource_error::~thread_resource_error() throw()
|
||||
{
|
||||
}
|
||||
|
||||
const char* thread_resource_error::what() const throw()
|
||||
{
|
||||
return "boost::thread_resource_error";
|
||||
}
|
||||
|
||||
unsupported_thread_option::unsupported_thread_option()
|
||||
{
|
||||
}
|
||||
|
||||
unsupported_thread_option::unsupported_thread_option(int sys_err_code)
|
||||
: thread_exception(sys_err_code)
|
||||
{
|
||||
}
|
||||
|
||||
unsupported_thread_option::~unsupported_thread_option() throw()
|
||||
{
|
||||
}
|
||||
|
||||
const char* unsupported_thread_option::what() const throw()
|
||||
{
|
||||
return "boost::unsupported_thread_option";
|
||||
}
|
||||
|
||||
invalid_thread_argument::invalid_thread_argument()
|
||||
{
|
||||
}
|
||||
|
||||
invalid_thread_argument::invalid_thread_argument(int sys_err_code)
|
||||
: thread_exception(sys_err_code)
|
||||
{
|
||||
}
|
||||
|
||||
invalid_thread_argument::~invalid_thread_argument() throw()
|
||||
{
|
||||
}
|
||||
|
||||
const char* invalid_thread_argument::what() const throw()
|
||||
{
|
||||
return "boost::invalid_thread_argument";
|
||||
}
|
||||
|
||||
thread_permission_error::thread_permission_error()
|
||||
{
|
||||
}
|
||||
|
||||
thread_permission_error::thread_permission_error(int sys_err_code)
|
||||
: thread_exception(sys_err_code)
|
||||
{
|
||||
}
|
||||
|
||||
thread_permission_error::~thread_permission_error() throw()
|
||||
{
|
||||
}
|
||||
|
||||
const char* thread_permission_error::what() const throw()
|
||||
{
|
||||
return "boost::thread_permission_error";
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
8
src/mac/debug_prefix.hpp
Normal file
8
src/mac/debug_prefix.hpp
Normal file
@@ -0,0 +1,8 @@
|
||||
// (C) Copyright Mac Murrett 2001.
|
||||
// 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)
|
||||
|
||||
// See http://www.boost.org for most recent version.
|
||||
|
||||
#define TARGET_CARBON 1
|
||||
66
src/mac/delivery_man.cpp
Normal file
66
src/mac/delivery_man.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
// (C) Copyright Mac Murrett 2001.
|
||||
// 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)
|
||||
|
||||
// See http://www.boost.org for most recent version.
|
||||
|
||||
#include "delivery_man.hpp"
|
||||
|
||||
#include "os.hpp"
|
||||
#include "execution_context.hpp"
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace threads {
|
||||
|
||||
namespace mac {
|
||||
|
||||
namespace detail {
|
||||
|
||||
|
||||
delivery_man::delivery_man():
|
||||
m_pPackage(NULL),
|
||||
m_pSemaphore(kInvalidID),
|
||||
m_bPackageWaiting(false)
|
||||
{
|
||||
assert(at_st());
|
||||
|
||||
OSStatus lStatus = MPCreateSemaphore(1UL, 0UL, &m_pSemaphore);
|
||||
// TODO - throw on error here
|
||||
assert(lStatus == noErr);
|
||||
}
|
||||
|
||||
delivery_man::~delivery_man()
|
||||
{
|
||||
assert(m_bPackageWaiting == false);
|
||||
|
||||
OSStatus lStatus = MPDeleteSemaphore(m_pSemaphore);
|
||||
assert(lStatus == noErr);
|
||||
}
|
||||
|
||||
|
||||
void delivery_man::accept_deliveries()
|
||||
{
|
||||
if(m_bPackageWaiting)
|
||||
{
|
||||
assert(m_pPackage != NULL);
|
||||
m_pPackage->accept();
|
||||
m_pPackage = NULL;
|
||||
m_bPackageWaiting = false;
|
||||
|
||||
// signal to the thread making the call that we're done
|
||||
OSStatus lStatus = MPSignalSemaphore(m_pSemaphore);
|
||||
assert(lStatus == noErr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace mac
|
||||
|
||||
} // namespace threads
|
||||
|
||||
} // namespace boost
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user