mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 21:52:07 +00:00
Compare commits
318 Commits
svn-branch
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab1c01b17a | ||
|
|
bb06946bf1 | ||
|
|
68a7a469ca | ||
|
|
b2a095098d | ||
|
|
b5ac347a0b | ||
|
|
cf15597a9e | ||
|
|
ab0e9930c5 | ||
|
|
d0d1db2feb | ||
|
|
89348a9569 | ||
|
|
f260fd62d4 | ||
|
|
e2550db927 | ||
|
|
0d763fe627 | ||
|
|
9895e74560 | ||
|
|
82aa808b3b | ||
|
|
fb683c8d95 | ||
|
|
819c67d52b | ||
|
|
95a476a4cc | ||
|
|
c4625de938 | ||
|
|
eeb77fdd87 | ||
|
|
7aed765a77 | ||
|
|
5a4f798320 | ||
|
|
8f611e4d19 | ||
|
|
a646f1c818 | ||
|
|
3d4743972e | ||
|
|
553aad753b | ||
|
|
f8a08dfaad | ||
|
|
956ed86655 | ||
|
|
e258fb3fe9 | ||
|
|
676eb029b8 | ||
|
|
6459de79c3 | ||
|
|
af774310ef | ||
|
|
b1c5977064 | ||
|
|
d92430c8ee | ||
|
|
ce384ef3d8 | ||
|
|
c2cfd16c6c | ||
|
|
fcfd30f124 | ||
|
|
20cc8e6c30 | ||
|
|
4bff122033 | ||
|
|
49e437f11e | ||
|
|
63bad0ad64 | ||
|
|
33ff838081 | ||
|
|
5328b43191 | ||
|
|
7aac1e69af | ||
|
|
94207924ad | ||
|
|
3671f1792d | ||
|
|
3da29cb470 | ||
|
|
4448aa7fb9 | ||
|
|
71358d8842 | ||
|
|
5366b629d3 | ||
|
|
01b2d5c088 | ||
|
|
8d22f58bc3 | ||
|
|
be64ba98b3 | ||
|
|
ad551dd333 | ||
|
|
1e055e618d | ||
|
|
46064d1b20 | ||
|
|
08cf6a81a5 | ||
|
|
8ce25c6ecd | ||
|
|
01f93931cb | ||
|
|
0d3f4a0b7c | ||
|
|
29a1903c4b | ||
|
|
08041bf58e | ||
|
|
781794aa2d | ||
|
|
36c1198113 | ||
|
|
552dfff988 | ||
|
|
6efc06f50c | ||
|
|
e72cb93fe0 | ||
|
|
d57be95047 | ||
|
|
1d1989bbfe | ||
|
|
11178cdc84 | ||
|
|
54d37cd6af | ||
|
|
ede873549b | ||
|
|
83a2a4ec38 | ||
|
|
29e3665ead | ||
|
|
acd9b9db7e | ||
|
|
71c652dd9f | ||
|
|
6afcf7615d | ||
|
|
70302577f9 | ||
|
|
b5fdb39877 | ||
|
|
26f3f0fd2d | ||
|
|
562a748bc6 | ||
|
|
45ca67ec26 | ||
|
|
65f466c813 | ||
|
|
2b37cee9e5 | ||
|
|
ad33e705b2 | ||
|
|
a639fe4dbe | ||
|
|
8806d38775 | ||
|
|
ba49aaa0f7 | ||
|
|
1a92100467 | ||
|
|
ef6dc83fa8 | ||
|
|
48f550d403 | ||
|
|
3c9be720b8 | ||
|
|
b3ba8802bf | ||
|
|
0fddf00c8f | ||
|
|
bb7976f666 | ||
|
|
3ad4fb38b5 | ||
|
|
deaccce853 | ||
|
|
6aabcaac5c | ||
|
|
d07407306f | ||
|
|
4231423773 | ||
|
|
46b66d5268 | ||
|
|
9c439a73db | ||
|
|
cdd57f50ef | ||
|
|
8c2ded3235 | ||
|
|
d3b590f213 | ||
|
|
7fcdd5d9e2 | ||
|
|
9ceee4b030 | ||
|
|
50f8f34ab8 | ||
|
|
d76e67ffe2 | ||
|
|
617729f2ae | ||
|
|
e8363511d0 | ||
|
|
4749f47f00 | ||
|
|
07af8a5605 | ||
|
|
cc89b8d2c6 | ||
|
|
946d45ee70 | ||
|
|
8a3b5145ac | ||
|
|
1af9fb7267 | ||
|
|
6fe2e36fb0 | ||
|
|
e5ada85386 | ||
|
|
a9760cd2e6 | ||
|
|
3e0ce8d25a | ||
|
|
7d59bbbad5 | ||
|
|
c7a85f366c | ||
|
|
8b3773f157 | ||
|
|
cb27585fa2 | ||
|
|
d3ee1b804a | ||
|
|
48ff760e18 | ||
|
|
ba0bdc6489 | ||
|
|
953461904c | ||
|
|
c956bc9ad7 | ||
|
|
91d88bb24a | ||
|
|
545a0f5c86 | ||
|
|
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 |
@@ -1,3 +1,2 @@
|
||||
bin*
|
||||
*.pdb
|
||||
bjam.log
|
||||
228
build/Jamfile
228
build/Jamfile
@@ -1,132 +1,122 @@
|
||||
# Copyright (C) 2001-2003
|
||||
# William E. Kempf
|
||||
# Copyright 2006 Roland Schwarz.
|
||||
# Distributed under the Boost Software License, Version 1.0. (See
|
||||
# accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# Permission to use, copy, modify, distribute and sell this software
|
||||
# and its documentation for any purpose is hereby granted without fee,
|
||||
# provided that the above copyright notice appear in all copies and
|
||||
# that both that copyright notice and this permission notice appear
|
||||
# in supporting documentation. William E. Kempf makes no representations
|
||||
# about the suitability of this software for any purpose.
|
||||
# It is provided "as is" without express or implied warranty.
|
||||
#
|
||||
# Boost.Threads build Jamfile
|
||||
#
|
||||
# Additional configuration variables used:
|
||||
# 1. PTW32 may be used on Win32 platforms to specify that the pthreads-win32
|
||||
# library should be used instead of "native" threads. This feature is
|
||||
# mostly used for testing and it's generally recommended you use the
|
||||
# native threading libraries instead. PTW32 should be set to be a list
|
||||
# of two strings, the first specifying the installation path of the
|
||||
# pthreads-win32 library and the second specifying which library
|
||||
# variant to link against (see the pthreads-win32 documentation).
|
||||
# Example: jam -sPTW32="c:\pthreads-win32 pthreadVCE.lib"
|
||||
# This work is a reimplementation along the design and ideas
|
||||
# of William E. Kempf.
|
||||
|
||||
# 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 ;
|
||||
|
||||
{
|
||||
CPP_SOURCES =
|
||||
barrier
|
||||
condition
|
||||
exceptions
|
||||
mutex
|
||||
named
|
||||
once
|
||||
recursive_mutex
|
||||
read_write_mutex
|
||||
shared_memory
|
||||
thread
|
||||
threadmon
|
||||
thread_pool
|
||||
tss
|
||||
xtime
|
||||
;
|
||||
# pthreads is compiled on all platforms when available
|
||||
if [ threads::is-pthread-available ] {
|
||||
|
||||
template pthread_base
|
||||
: ## sources ##
|
||||
[ threads::cpp_source ../src/pthread :
|
||||
thread
|
||||
mutex
|
||||
recursive_mutex
|
||||
condition
|
||||
exceptions
|
||||
xtime
|
||||
once
|
||||
tss
|
||||
]
|
||||
: ## requirements ##
|
||||
threads::lib-pthread
|
||||
<sysinclude>$(BOOST_ROOT)
|
||||
<threading>multi
|
||||
<define>BOOST_THREAD_POSIX
|
||||
common-variant-tag
|
||||
<borland><*><cxxflags>-w-8004
|
||||
<borland><*><cxxflags>-w-8057
|
||||
;
|
||||
|
||||
template boost_thread_lib_base
|
||||
: ## sources ##
|
||||
<template>thread_base
|
||||
../src/$(CPP_SOURCES).cpp
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_BUILD_LIB=1
|
||||
<runtime-link>static
|
||||
# the common names rule ensures that the library will
|
||||
# be named according to the rules used by the install
|
||||
# and auto-link features:
|
||||
common-variant-tag
|
||||
: ## default build ##
|
||||
;
|
||||
lib boost_thread_pthread
|
||||
: <template>pthread_base
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_BUILD_LIB=1
|
||||
;
|
||||
|
||||
template thread_dll_base
|
||||
: ## sources ##
|
||||
<template>thread_base
|
||||
../src/$(CPP_SOURCES).cpp
|
||||
: ## requirements ##
|
||||
<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 ##
|
||||
;
|
||||
dll boost_thread_pthread
|
||||
: <template>pthread_base
|
||||
: ## requirements ##
|
||||
<runtime-link>dynamic
|
||||
<define>BOOST_THREAD_BUILD_DLL=1
|
||||
;
|
||||
|
||||
lib $(boost_thread_lib_name)
|
||||
: ## sources ##
|
||||
<template>boost_thread_lib_base
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name)
|
||||
: ## default build ##
|
||||
;
|
||||
stage bin-stage
|
||||
: <dll>boost_thread_pthread
|
||||
<lib>boost_thread_pthread
|
||||
;
|
||||
|
||||
dll $(boost_thread_lib_name)
|
||||
: ## sources ##
|
||||
<template>thread_dll_base
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name)
|
||||
: ## default build ##
|
||||
;
|
||||
install thread_pthread lib
|
||||
: <dll>boost_thread_pthread
|
||||
<lib>boost_thread_pthread
|
||||
;
|
||||
|
||||
stage bin-stage
|
||||
: <dll>$(boost_thread_lib_name)
|
||||
<lib>$(boost_thread_lib_name)
|
||||
;
|
||||
# the next is true on platforms where pthreads is native threading lib
|
||||
if [ threads::is-native-on-build-os pthread ] {
|
||||
|
||||
lib boost_thread
|
||||
: <template>pthread_base
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_BUILD_LIB=1
|
||||
;
|
||||
|
||||
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)
|
||||
$(pthreads-win32)
|
||||
;
|
||||
|
||||
dll $(boost_thread_lib_name_ptw32)
|
||||
: ## sources ##
|
||||
<template>thread_dll_base
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name_ptw32)
|
||||
$(pthreads-win32)
|
||||
;
|
||||
|
||||
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)
|
||||
;
|
||||
}
|
||||
dll boost_thread
|
||||
: <template>pthread_base
|
||||
: ## requirements ##
|
||||
<runtime-link>dynamic
|
||||
<define>BOOST_THREAD_BUILD_DLL=1
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
if [ threads::is-native-on-build-os win32 ] {
|
||||
|
||||
template win32_base
|
||||
: ## sources ##
|
||||
[ threads::cpp_source ../src/win32 :
|
||||
thread
|
||||
exceptions
|
||||
xtime
|
||||
tss
|
||||
tss_hooks
|
||||
tss_dll
|
||||
tss_pe
|
||||
]
|
||||
: ## requirements ##
|
||||
<sysinclude>$(BOOST_ROOT)
|
||||
<threading>multi
|
||||
common-variant-tag
|
||||
<borland><*><cxxflags>-w-8004
|
||||
<borland><*><cxxflags>-w-8057
|
||||
;
|
||||
|
||||
lib boost_thread
|
||||
: <template>win32_base
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_BUILD_LIB=1
|
||||
;
|
||||
|
||||
dll boost_thread
|
||||
: <template>win32_base
|
||||
: ## requirements ##
|
||||
<runtime-link>dynamic
|
||||
<define>BOOST_THREAD_BUILD_DLL=1
|
||||
;
|
||||
}
|
||||
|
||||
stage bin-stage
|
||||
: <dll>boost_thread
|
||||
<lib>boost_thread
|
||||
;
|
||||
|
||||
install thread lib
|
||||
: <dll>boost_thread
|
||||
<lib>boost_thread
|
||||
;
|
||||
|
||||
@@ -1,12 +1,61 @@
|
||||
# Copyright 2006 Roland Schwarz.
|
||||
# Distributed under the Boost Software License, Version 1.0. (See
|
||||
# accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# This work is a reimplementation along the design and ideas
|
||||
# of William E. Kempf.
|
||||
|
||||
# Declare the uses system library
|
||||
lib pthread : : <name>pthread ;
|
||||
import thread ;
|
||||
|
||||
project boost/thread
|
||||
: source-location ../src
|
||||
: usage-requirements <library>pthread
|
||||
: source-location ../src
|
||||
: requirements <threading>multi
|
||||
<link>static:<define>BOOST_THREAD_BUILD_LIB=1
|
||||
<link>shared:<define>BOOST_THREAD_BUILD_DLL=1
|
||||
: default-build <threading>multi [ thread.default-api ]
|
||||
;
|
||||
|
||||
CPP_SOURCES = condition mutex recursive_mutex thread tss xtime once exceptions ;
|
||||
# build the pthread based variant
|
||||
lib boost_thread_pthread
|
||||
: ## sources ##
|
||||
pthread/thread.cpp
|
||||
pthread/mutex.cpp
|
||||
pthread/recursive_mutex.cpp
|
||||
pthread/condition.cpp
|
||||
pthread/exceptions.cpp
|
||||
pthread/xtime.cpp
|
||||
pthread/tss.cpp
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_POSIX
|
||||
<thrd-api>pthread
|
||||
;
|
||||
|
||||
# use pthread on platforms where pthread is considered native
|
||||
lib boost_thread
|
||||
: ## sources ##
|
||||
pthread/thread.cpp
|
||||
pthread/mutex.cpp
|
||||
pthread/recursive_mutex.cpp
|
||||
pthread/condition.cpp
|
||||
pthread/exceptions.cpp
|
||||
pthread/xtime.cpp
|
||||
pthread/tss.cpp
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_POSIX
|
||||
<thrd-api>pthread
|
||||
;
|
||||
# the win32 native variant
|
||||
lib boost_thread
|
||||
: ## sources ##
|
||||
win32/thread.cpp
|
||||
win32/exceptions.cpp
|
||||
win32/xtime.cpp
|
||||
win32/tss.cpp
|
||||
win32/tss_hooks.cpp
|
||||
win32/tss_dll.cpp
|
||||
win32/tss_pe.cpp
|
||||
: ## requirements ##
|
||||
<thrd-api>win32
|
||||
;
|
||||
|
||||
lib boost_thread : $(CPP_SOURCES).cpp ;
|
||||
|
||||
70
build/thread.jam
Normal file
70
build/thread.jam
Normal file
@@ -0,0 +1,70 @@
|
||||
# Copyright 2006 Roland Schwarz.
|
||||
# Distributed under the Boost Software License, Version 1.0. (See
|
||||
# accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# This work is a reimplementation along the design and ideas
|
||||
# of William E. Kempf.
|
||||
|
||||
import modules ;
|
||||
import os ;
|
||||
import feature ;
|
||||
import property ;
|
||||
|
||||
# supported threading api's
|
||||
feature.feature thrd-api : pthread win32 : symmetric ;
|
||||
|
||||
# save a reference to the original lib rule
|
||||
IMPORT : lib : $(__name__) : type.lib ;
|
||||
|
||||
# local override of the global lib rule
|
||||
rule lib ( name : sources * : requirements * : default-build * : usage-requirements * )
|
||||
{
|
||||
if <thrd-api>pthread in $(requirements)
|
||||
{
|
||||
if [ os.name ] = "NT"
|
||||
{
|
||||
local PTW32_INCLUDE = [ modules.peek : PTW32_INCLUDE ] ;
|
||||
local PTW32_LIB = [ modules.peek : PTW32_LIB ] ;
|
||||
if $(PTW32_INCLUDE) && $(PTW32_LIB)
|
||||
{
|
||||
requirements =
|
||||
[ property.refine $(requirements) :
|
||||
<define>BOOST_HAS_PTHREADS
|
||||
<include>$(PTW32_INCLUDE)
|
||||
<library>$(PTW32_LIB)
|
||||
] ;
|
||||
}
|
||||
else
|
||||
{
|
||||
requirements += <build>no ;
|
||||
# it would be nice if this message appears only once ...
|
||||
# but I cannot figure out how to detectd the second phase.
|
||||
echo "******************************************************" ;
|
||||
echo "Building Boost.Thread without pthread support" ;
|
||||
echo "If you need pthread you should specify the paths." ;
|
||||
echo "For example:" ;
|
||||
echo "PTW32_INCLUDE=C:\\Program Files\\ptw32\\Pre-built2\\include" ;
|
||||
echo "PTW32_LIB=C:\\Program Files\\ptw32\\Pre-built2\\lib\\pthreadVC2.lib" ;
|
||||
echo "******************************************************" ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [ type.lib $(name) : $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ] ;
|
||||
}
|
||||
|
||||
# auto export of rule lib to calling module only
|
||||
IMPORT $(__name__) : lib : [ CALLER_MODULE 1 ] : lib ;
|
||||
|
||||
rule default-api
|
||||
{
|
||||
if [ os.name ] = "NT"
|
||||
{
|
||||
return <thrd-api>win32 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
return <thrd-api>pthread ;
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,65 @@
|
||||
# Copyright (C) 2001-2003
|
||||
# William E. Kempf
|
||||
# Copyright 2006 Roland Schwarz.
|
||||
# Distributed under the Boost Software License, Version 1.0. (See
|
||||
# accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# 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 work is a reimplementation along the design and ideas
|
||||
# of William E. Kempf.
|
||||
|
||||
# Do some OS-specific setup
|
||||
# find out if pthread is available on current build platform
|
||||
rule threads::is-pthread-available
|
||||
{
|
||||
#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 ##
|
||||
;
|
||||
if $(OS) = "NT" {
|
||||
if $(PTW32_INCLUDE) && $(PTW32_LIB) {
|
||||
return true ;
|
||||
}
|
||||
else {
|
||||
ECHO "******************************************************" ;
|
||||
ECHO "Building Boost.Thread without pthread support" ;
|
||||
ECHO "If you need pthread you should specify the paths." ;
|
||||
ECHO "For example:" ;
|
||||
ECHO "PTW32_INCLUDE=C:\\Program Files\\ptw32\\Pre-built2\\include" ;
|
||||
ECHO "PTW32_LIB=C:\\Program Files\\ptw32\\Pre-built2\\lib\\pthreadVC2.lib" ;
|
||||
ECHO "******************************************************" ;
|
||||
}
|
||||
}
|
||||
else if $(OS) = "LINUX" {
|
||||
return true ;
|
||||
}
|
||||
else { ## assume pthread is available on unknown os for now
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
# find the native library variant for current build os
|
||||
rule threads::is-native-on-build-os ( libvariant )
|
||||
{
|
||||
if $(OS) = "NT" {
|
||||
if $(libvariant) = win32 { return true ; }
|
||||
}
|
||||
else if $(OS) = "LINUX" {
|
||||
if $(libvariant) = pthread { return true ; }
|
||||
}
|
||||
else { ## assume pthread is native on others for now
|
||||
if $(libvariant) = pthread { return true ; }
|
||||
}
|
||||
}
|
||||
|
||||
# utility to prepend the source path to the cpp sources
|
||||
rule threads::cpp_source ( path : sources * )
|
||||
{
|
||||
return $(path)/$(sources).cpp ;
|
||||
}
|
||||
|
||||
# impose the pthread library and include path on the requirements
|
||||
rule threads::lib-pthread ( toolset variant : subvariant-path properties * )
|
||||
{
|
||||
if $(OS) = "NT" && $(PTW32_INCLUDE) && $(PTW32_LIB) {
|
||||
properties = [ impose-requirements $(properties) :
|
||||
<define>BOOST_HAS_PTHREADS
|
||||
<include>$(PTW32_INCLUDE)
|
||||
<library-file>$(PTW32_LIB) ] ;
|
||||
}
|
||||
|
||||
return $(subvariant-path) $(properties) ;
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -1,3 +0,0 @@
|
||||
bin
|
||||
html
|
||||
catalog.xml
|
||||
@@ -1,5 +1,6 @@
|
||||
project boost/doc ;
|
||||
import boostbook : boostbook ;
|
||||
|
||||
boostbook doc : thread.xml ;
|
||||
import toolset ;
|
||||
toolset.using doxygen ;
|
||||
|
||||
boostbook thread : thread.xml ;
|
||||
|
||||
|
||||
@@ -75,4 +75,4 @@
|
||||
</method-group>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
</header>
|
||||
|
||||
@@ -54,7 +54,7 @@ last-revision="$Date$">
|
||||
<title>ACM Computing Surveys</title>
|
||||
<volumenum>Vol. 5</volumenum>
|
||||
<issuenum>No. 4</issuenum>
|
||||
<date>December, 1983</date>
|
||||
<date>December, 1973</date>
|
||||
</biblioset>
|
||||
<biblioset relation="article">
|
||||
<author>0-201-63392-2
|
||||
|
||||
@@ -55,4 +55,4 @@
|
||||
<programlisting>bjam -sTOOLS=<emphasis>toolset</emphasis> test</programlisting>
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
147
doc/concepts.xml
147
doc/concepts.xml
@@ -18,6 +18,12 @@
|
||||
|
||||
<section id="threads.concepts.mutexes">
|
||||
<title>Mutexes</title>
|
||||
|
||||
<note>Certain changes to the mutexes and lock concepts are
|
||||
currently under discussion. In particular, the combination of
|
||||
the multiple lock concepts into a single lock concept
|
||||
is likely, and the combination of the multiple mutex
|
||||
concepts into a single mutex concept is also possible.</note>
|
||||
|
||||
<para>A mutex (short for mutual-exclusion) object is used to serialize
|
||||
access to a resource shared between multiple threads. The
|
||||
@@ -189,7 +195,7 @@
|
||||
and constructed for the Mutex object.</para>
|
||||
|
||||
<para>A Mutex is
|
||||
<ulink url="../../utility/utility.htm#Class%20noncopyable">
|
||||
<ulink url="../../libs/utility/utility.htm#Class%20noncopyable">
|
||||
NonCopyable</ulink>.</para>
|
||||
<para>For a Mutex type <code>M</code>
|
||||
and an object <code>m</code> of that type,
|
||||
@@ -729,6 +735,11 @@
|
||||
|
||||
<section id="threads.concepts.read-write-mutexes">
|
||||
<title>Read/Write Mutexes</title>
|
||||
<note>Since the read/write mutex and related classes are new,
|
||||
both interface and implementation are liable to change
|
||||
in future releases of &Boost.Threads;.
|
||||
The lock concepts and lock promotion and demotion in particular
|
||||
are still under discussion and very likely to change.</note>
|
||||
|
||||
<para>A read/write mutex (short for reader/writer mutual-exclusion) object
|
||||
is used to serialize access to a resource shared between multiple
|
||||
@@ -1086,12 +1097,9 @@
|
||||
both threads will be waiting for the other to release their read-lock.
|
||||
</para>
|
||||
|
||||
<para>Currently, &Boost.Threads; supports lock promotion only
|
||||
through <code>try_promote()</code> and <code>timed_promote()</code>
|
||||
operations. <note>Note that, with <code>timed_promote()</code>,
|
||||
temporary deadlock can still occur, but since the promotion
|
||||
attempt will eventually time out the deadlock will eventually
|
||||
end.</note></para>
|
||||
<para>Currently, &Boost.Threads; supports lock promotion
|
||||
through <code>promote()</code>, <code>try_promote()</code>,
|
||||
and <code>timed_promote()</code> operations.</para>
|
||||
</section>
|
||||
|
||||
<section id="threads.concepts.read-write-locking-strategies.demotion">
|
||||
@@ -1172,7 +1180,7 @@
|
||||
the specified time, if any). A
|
||||
read-lock will be granted to all pending readers
|
||||
before any other thread can acquire a write-lock.
|
||||
<p>TODO: try-lock, timed-lock.</p>
|
||||
<para>TODO: try-lock, timed-lock.</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
@@ -1180,7 +1188,7 @@
|
||||
<entry>write-lock</entry>
|
||||
<entry>Grant the write-lock immediately, if and
|
||||
only if there are no pending read-lock requests.
|
||||
<p>TODO: try-lock, timed-lock.</p>
|
||||
<para>TODO: try-lock, timed-lock.</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
@@ -1192,7 +1200,7 @@
|
||||
for read-locks exist. If other write-lock
|
||||
requests exist, the lock is granted in accordance
|
||||
with the intra-class scheduling policy.
|
||||
<p>TODO: try-lock, timed-lock.</p>
|
||||
<para>TODO: try-lock, timed-lock.</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
@@ -1204,18 +1212,18 @@
|
||||
for read-locks exist. If other write-lock
|
||||
requests exist, the lock is granted in accordance
|
||||
with the intra-class scheduling policy.
|
||||
<p>TODO: try-lock, timed-lock.</p>
|
||||
<para>TODO: try-lock, timed-lock.</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>read-locked</entry>
|
||||
<entry>promote</entry>
|
||||
<entry><p>TODO</p></entry>
|
||||
<entry><para>TODO</para></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>write-locked</entry>
|
||||
<entry>demote</entry>
|
||||
<entry><p>TODO</p></entry>
|
||||
<entry><para>TODO</para></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -1253,7 +1261,7 @@
|
||||
<entry>Grant the additional read-lock immediately,
|
||||
<emphasis role="bold">IF</emphasis> no outstanding
|
||||
requests for a write-lock exist; otherwise TODO.
|
||||
<p>TODO: try-lock, timed-lock.</p>
|
||||
<para>TODO: try-lock, timed-lock.</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
@@ -1264,7 +1272,7 @@
|
||||
releases its lock. The read lock will be granted
|
||||
once no other outstanding write-lock requests
|
||||
exist.
|
||||
<p>TODO: try-lock, timed-lock.</p>
|
||||
<para>TODO: try-lock, timed-lock.</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
@@ -1281,7 +1289,7 @@
|
||||
is granted in accordance with the intra-class
|
||||
scheduling policy. This request will be granted
|
||||
before any new read-lock requests are granted.
|
||||
<p>TODO: try-lock, timed-lock.</p>
|
||||
<para>TODO: try-lock, timed-lock.</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
@@ -1293,18 +1301,18 @@
|
||||
granted in accordance with the intra-class
|
||||
scheduling policy. This request will be granted
|
||||
before any new read-lock requests are granted.
|
||||
<p>TODO: try-lock, timed-lock.</p>
|
||||
<para>TODO: try-lock, timed-lock.</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>read-locked</entry>
|
||||
<entry>promote</entry>
|
||||
<entry><p>TODO</p></entry>
|
||||
<entry><para>TODO</para></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>write-locked</entry>
|
||||
<entry>demote</entry>
|
||||
<entry><p>TODO</p></entry>
|
||||
<entry><para>TODO</para></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -1347,7 +1355,7 @@
|
||||
write-locks is granted and released. If other
|
||||
read-lock requests exist, all read-locks will be
|
||||
granted as a group.
|
||||
<p>TODO: try-lock, timed-lock.</p>
|
||||
<para>TODO: try-lock, timed-lock.</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
@@ -1358,7 +1366,7 @@
|
||||
outstanding write-lock requests exist, they will
|
||||
have to wait until all current read-lock requests
|
||||
are serviced.
|
||||
<p>TODO: try-lock, timed-lock.</p>
|
||||
<para>TODO: try-lock, timed-lock.</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
@@ -1377,7 +1385,7 @@
|
||||
lock will be granted to one of them in accordance
|
||||
with the intra-class scheduling policy.</para>
|
||||
|
||||
<p>TODO: try-lock, timed-lock.</p>
|
||||
<para>TODO: try-lock, timed-lock.</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
@@ -1391,18 +1399,18 @@
|
||||
released. If other write-lock requests exist,
|
||||
this lock will be granted in accordance with the
|
||||
intra-class scheduling policy.
|
||||
<p>TODO: try-lock, timed-lock.</p>
|
||||
<para>TODO: try-lock, timed-lock.</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>read-locked</entry>
|
||||
<entry>promote</entry>
|
||||
<entry><p>TODO</p></entry>
|
||||
<entry><para>TODO</para></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>write-locked</entry>
|
||||
<entry>demote</entry>
|
||||
<entry><p>TODO</p></entry>
|
||||
<entry><para>TODO</para></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -1443,7 +1451,7 @@
|
||||
write-lock requests exist, this lock will not
|
||||
be granted until at least one of the write-locks
|
||||
is granted and released.
|
||||
<p>TODO: try-lock, timed-lock.</p>
|
||||
<para>TODO: try-lock, timed-lock.</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
@@ -1456,7 +1464,7 @@
|
||||
exist, exactly one read-lock request will be
|
||||
granted before the next write-lock is granted.
|
||||
</para>
|
||||
<p>TODO: try-lock, timed-lock.</p>
|
||||
<para>TODO: try-lock, timed-lock.</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
@@ -1477,7 +1485,7 @@
|
||||
in accordance with the intra-class
|
||||
scheduling policy.</para></entry>
|
||||
|
||||
<p>TODO: try-lock, timed-lock.</p>
|
||||
<para>TODO: try-lock, timed-lock.</para>
|
||||
</row>
|
||||
<row>
|
||||
<entry>write-locked</entry>
|
||||
@@ -1490,18 +1498,18 @@
|
||||
released. If other write-lock requests exist,
|
||||
this lock will be granted in accordance with
|
||||
the intra-class scheduling policy.
|
||||
<p>TODO: try-lock, timed-lock.</p>
|
||||
<para>TODO: try-lock, timed-lock.</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>read-locked</entry>
|
||||
<entry>promote</entry>
|
||||
<entry><p>TODO</p></entry>
|
||||
<entry><para>TODO</para></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>write-locked</entry>
|
||||
<entry>demote</entry>
|
||||
<entry><p>TODO</p></entry>
|
||||
<entry><para>TODO</para></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -1545,7 +1553,7 @@
|
||||
requirements and constructed for the ReadWriteMutex object.</para>
|
||||
|
||||
<para>A ReadWriteMutex is
|
||||
<ulink url="../../utility/utility.htm#Class%20noncopyable">NonCopyable</ulink>.
|
||||
<ulink url="../../libs/utility/utility.htm#Class%20noncopyable">NonCopyable</ulink>.
|
||||
</para>
|
||||
|
||||
<para>For a ReadWriteMutex type <code>M</code>,
|
||||
@@ -1577,9 +1585,21 @@
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>M::scoped_lock</code></entry>
|
||||
<entry><code>M::scoped_read_write_lock</code></entry>
|
||||
<entry>A type meeting the
|
||||
<link linkend="threads.concepts.ScopedReadWriteMutex">ScopedReadWriteLock</link>
|
||||
<link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link>
|
||||
requirements. </entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>M::scoped_read_lock</code></entry>
|
||||
<entry>A type meeting the
|
||||
<link linkend="threads.concepts.ScopedLock">ScopedLock</link>
|
||||
requirements. </entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>M::scoped_write_lock</code></entry>
|
||||
<entry>A type meeting the
|
||||
<link linkend="threads.concepts.ScopedLock">ScopedLock</link>
|
||||
requirements. </entry>
|
||||
</row>
|
||||
</tbody>
|
||||
@@ -1610,9 +1630,21 @@
|
||||
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><code>M::scoped_try_lock</code></entry>
|
||||
<entry><code>M::scoped_try_read_write_lock</code></entry>
|
||||
<entry>A type meeting the
|
||||
<link linkend="threads.concepts.ScopedReadWriteMutex">ScopedTryReadWriteLock</link>
|
||||
<link linkend="threads.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link>
|
||||
requirements.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>M::scoped_try_read_lock</code></entry>
|
||||
<entry>A type meeting the
|
||||
<link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link>
|
||||
requirements.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>M::scoped_try_write_lock</code></entry>
|
||||
<entry>A type meeting the
|
||||
<link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link>
|
||||
requirements.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
@@ -1643,9 +1675,21 @@
|
||||
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><code>M::scoped_timed_lock</code></entry>
|
||||
<entry><code>M::scoped_timed_read_write_lock</code></entry>
|
||||
<entry>A type meeting the
|
||||
<link linkend="threads.concepts.ScopedReadWriteMutex">ScopedTimedReadWriteLock</link>
|
||||
<link linkend="threads.concepts.ScopedTimedReadWriteLock">ScopedTimedReadWriteLock</link>
|
||||
requirements.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>M::scoped_timed_read_lock</code></entry>
|
||||
<entry>A type meeting the
|
||||
<link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link>
|
||||
requirements.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>M::scoped_timed_write_lock</code></entry>
|
||||
<entry>A type meeting the
|
||||
<link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link>
|
||||
requirements.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
@@ -1863,6 +1907,19 @@
|
||||
<para>Postcondition: <code>state() == read_write_lock_state::read_locked</code></para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>lk.promote()</code></entry>
|
||||
<entry>
|
||||
<para>Throws <classname>boost::lock_error</classname>
|
||||
if <code>state() != read_write_lock_state::read_locked</code>
|
||||
or if the lock cannot be promoted because another lock
|
||||
on the same mutex is already waiting to be promoted.</para>
|
||||
|
||||
<para>Makes a blocking attempt to convert the lock held on the associated
|
||||
read/write mutex object from a read-lock to a write-lock without releasing
|
||||
the lock.</para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><code>lk.unlock()</code></entry>
|
||||
<entry>
|
||||
@@ -2191,9 +2248,9 @@
|
||||
<entry><link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
<entry><link linkend="threads.concepts.ReadWriteLock">ReadWriteLock</link></entry>
|
||||
<entry>
|
||||
<para><classname>boost::read_write_mutex::scoped_lock</classname></para>
|
||||
<para><classname>boost::try_read_write_mutex::scoped_lock</classname></para>
|
||||
<para><classname>boost::timed_read_write_mutex::scoped_lock</classname></para>
|
||||
<para><classname>boost::read_write_mutex::scoped_read_write_lock</classname></para>
|
||||
<para><classname>boost::try_read_write_mutex::scoped_read_write_lock</classname></para>
|
||||
<para><classname>boost::timed_read_write_mutex::scoped_read_write_lock</classname></para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
@@ -2205,8 +2262,8 @@
|
||||
<entry><link linkend="threads.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
|
||||
<entry><link linkend="threads.concepts.TryReadWriteLock">TryReadWriteLock</link></entry>
|
||||
<entry>
|
||||
<para><classname>boost::try_read_write_mutex::scoped_try_lock</classname></para>
|
||||
<para><classname>boost::timed_read_write_mutex::scoped_try_lock</classname></para>
|
||||
<para><classname>boost::try_read_write_mutex::scoped_try_read_write_lock</classname></para>
|
||||
<para><classname>boost::timed_read_write_mutex::scoped_try_read_write_lock</classname></para>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
@@ -2218,7 +2275,7 @@
|
||||
<entry><link linkend="threads.concepts.ScopedTimedReadWriteLock">ScopedTimedReadWriteLock</link></entry>
|
||||
<entry><link linkend="threads.concepts.TimedReadWriteLock">TimedReadWriteLock</link></entry>
|
||||
<entry>
|
||||
<para><classname>boost::timed_read_write_mutex::scoped_timed_lock</classname></para>
|
||||
<para><classname>boost::timed_read_write_mutex::scoped_timed_read_write_lock</classname></para>
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
@@ -2226,4 +2283,4 @@
|
||||
</table>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -89,4 +89,4 @@
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -55,4 +55,4 @@
|
||||
</constructor>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
</header>
|
||||
|
||||
8
doc/index.html
Normal file
8
doc/index.html
Normal file
@@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=../../../doc/html/threads.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to <a href="../../../doc/html/threads.html">../../../doc/html/threads.html</a>
|
||||
</body>
|
||||
</html>
|
||||
@@ -33,7 +33,6 @@
|
||||
the specified locking strategy:
|
||||
|
||||
<informaltable>
|
||||
<title>Supported Lock Types</title>
|
||||
<tgroup cols="2" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
@@ -124,7 +123,6 @@
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
<title>Supported Lock Types</title>
|
||||
<tgroup cols="2" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
@@ -224,7 +222,6 @@
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
<title>Supported Lock Types</title>
|
||||
<tgroup cols="2" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
@@ -305,4 +302,4 @@
|
||||
</destructor>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
</header>
|
||||
|
||||
@@ -83,4 +83,4 @@ void thread_proc()
|
||||
</postconditions>
|
||||
</function>
|
||||
</namespace>
|
||||
</header>
|
||||
</header>
|
||||
|
||||
@@ -431,4 +431,4 @@
|
||||
and will be less likely to contain latent defects.</para>
|
||||
<para>[Rationale provided by Beman Dawes]</para>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -45,9 +45,9 @@
|
||||
<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 typedef,
|
||||
which <link linkend="threads.concepts.read-write-lock-models">models</link>
|
||||
the specified locking strategy:
|
||||
<para>The <classname>read_write_mutex</classname> class supplies the following typedefs,
|
||||
which <link linkend="threads.concepts.read-write-lock-models">model</link>
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
<tgroup cols="2" align="left">
|
||||
@@ -59,9 +59,17 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry>scoped_read_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_read_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
@@ -109,7 +117,15 @@
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<typedef name="scoped_lock">
|
||||
<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>
|
||||
|
||||
@@ -154,7 +170,7 @@
|
||||
|
||||
<para>The <classname>try_read_write_mutex</classname> class supplies the following typedefs,
|
||||
which <link linkend="threads.concepts.read-write-lock-models">model</link>
|
||||
the specified locking strategy:
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
<tgroup cols="2" align="left">
|
||||
@@ -166,13 +182,29 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry>scoped_read_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_lock</entry>
|
||||
<entry>scoped_try_read_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_read_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_read_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
@@ -215,11 +247,27 @@
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<typedef name="scoped_lock">
|
||||
<typedef name="scoped_read_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_lock">
|
||||
<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>
|
||||
|
||||
@@ -264,7 +312,7 @@
|
||||
|
||||
<para>The <classname>timed_read_write_mutex</classname> class supplies the following typedefs,
|
||||
which <link linkend="threads.concepts.read-write-lock-models">model</link>
|
||||
the specified locking strategy:
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
<tgroup cols="2" align="left">
|
||||
@@ -276,17 +324,41 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry>scoped_read_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_lock</entry>
|
||||
<entry>scoped_try_read_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_lock</entry>
|
||||
<entry>scoped_timed_read_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTimedReadWriteLock">ScopedTimedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_read_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_read_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_read_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_write_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
@@ -324,15 +396,39 @@
|
||||
unless all locks are read-locks (but see below)</note>
|
||||
</description>
|
||||
|
||||
<typedef name="scoped_lock">
|
||||
<typedef name="scoped_read_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_lock">
|
||||
<typedef name="scoped_try_read_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_timed_lock">
|
||||
<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>
|
||||
|
||||
@@ -359,4 +455,4 @@
|
||||
</destructor>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
</header>
|
||||
|
||||
@@ -299,4 +299,4 @@
|
||||
</destructor>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
</header>
|
||||
|
||||
@@ -21,38 +21,57 @@
|
||||
</section>
|
||||
|
||||
<section id="threads.release_notes.boost_1_32_0.change_log.static_link">
|
||||
<title>Static-link build option added</title>
|
||||
<title>Statically-link build option added</title>
|
||||
|
||||
<para>The option to link &Boost.Threads; as a static
|
||||
library has been added back with some limitations.
|
||||
This feature was originally removed because
|
||||
<classname>boost::thread_specific_ptr</classname> required
|
||||
that &Boost.Threads; be dynamically linked in order for its
|
||||
cleanup functionality to work on Win32 platforms.
|
||||
Several options are currently being explored to resolve
|
||||
this issue. In the meantime, the ability to link
|
||||
&Boost.Threads; statically has been added back
|
||||
<emphasis>with <classname>boost::thread_specific_ptr</classname>
|
||||
support removed</emphasis> from the statically linked version.
|
||||
The decision to add it back was made because its lack is
|
||||
one of the most frequent complaints about &Boost.Threads;
|
||||
and because the other approaches that are being investigated
|
||||
to deal with <classname>boost::thread_specific_ptr</classname>
|
||||
cleanup look fairly promising.
|
||||
<note>&Boost.Threads; is still dynamically linked by default.
|
||||
In order to force it to be statically linked, it is necessary to
|
||||
#define BOOST_THREAD_USE_LIB before any of the &Boost.Threads;
|
||||
header files are #included.</note>
|
||||
<note>If the <classname>boost::thread_specific_ptr</classname> cleanup
|
||||
issue cannot be resolved by some other means, it is highly
|
||||
likely that the option to statically link &Boost.Threads;
|
||||
will be removed again in a future version of Boost, at least
|
||||
for Win32 platforms. This is because the
|
||||
<classname>boost::thread_specific_ptr</classname> functionality
|
||||
will be increasingly used by &Boost.Threads; itself,
|
||||
so that proper cleanup will become essential
|
||||
in future versions of &Boost.Threads;.</note>
|
||||
</para>
|
||||
library has been added (with some limitations on Win32 platforms).
|
||||
This feature was originally removed from an earlier version
|
||||
of Boost because <classname>boost::thread_specific_ptr</classname>
|
||||
required that &Boost.Threads; be dynamically linked in order
|
||||
for its cleanup functionality to work on Win32 platforms.
|
||||
Because this limitation never applied to non-Win32 platforms,
|
||||
because significant progress has been made in removing
|
||||
the limitation on Win32 platforms (many thanks to
|
||||
Aaron LaFramboise and Roland Scwarz!), and because the lack
|
||||
of static linking is one of the most common complaints of
|
||||
&Boost.Threads; users, this decision was reversed.</para>
|
||||
|
||||
<para>On non-Win32 platforms:
|
||||
To choose the dynamically linked version of &Boost.Threads;
|
||||
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.Threads;.
|
||||
|
||||
Note for advanced users: &Boost.Threads; 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="threads.release_notes.boost_1_32_0.change_log.barrier">
|
||||
@@ -68,7 +87,14 @@
|
||||
<classname>boost::read_write_mutex</classname>,
|
||||
<classname>boost::try_read_write_mutex</classname>, and
|
||||
<classname>boost::timed_read_write_mutex</classname>
|
||||
were added.</para>
|
||||
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.Threads;.
|
||||
The lock concepts and lock promotion in particular are
|
||||
still under discussion and very likely to change.</note>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="threads.release_notes.boost_1_32_0.change_log.thread_specific_ptr">
|
||||
@@ -108,5 +134,11 @@
|
||||
<classname>boost::timed_mutex</classname> and
|
||||
<classname>boost::recursive_timed_mutex</classname> use a Win32 mutex.</para>
|
||||
</section>
|
||||
|
||||
<section id="threads.release_notes.boost_1_32_0.change_log.wince">
|
||||
<title>Windows CE support improved</title>
|
||||
|
||||
<para>Minor changes were made to make Boost.Threads work on Windows CE.</para>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -263,4 +263,4 @@
|
||||
</method-group>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
</header>
|
||||
|
||||
@@ -13,14 +13,12 @@ xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<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>Permission to use, copy, modify, distribute and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
@@ -30,14 +28,11 @@ xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
representations about the suitability of this software for any purpose.
|
||||
It is provided "as is" without express or implied warranty.</para>
|
||||
</legalnotice>
|
||||
|
||||
<librarypurpose>Portable C++ multi-threading</librarypurpose>
|
||||
|
||||
<librarycategory name="category:concurrent" />
|
||||
|
||||
<title>Boost.Threads</title>
|
||||
</libraryinfo>
|
||||
<title>&Boost.Threads;</title>
|
||||
<title>Boost.Threads</title>
|
||||
<xi:include href="overview.xml"/>
|
||||
<xi:include href="design.xml"/>
|
||||
<xi:include href="concepts.xml"/>
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<header name="boost/thread/thread_pool.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
<class name="thread_pool">
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
@@ -1,207 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link rel="stylesheet" type="text/css" href="../../../boost.css">
|
||||
<title>Boost.Threads - Header <boost/thread/thread_pool.hpp></title>
|
||||
</head>
|
||||
<body link="#0000ff" vlink="#800080">
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
|
||||
"header">
|
||||
<tr>
|
||||
<td valign="top" width="300">
|
||||
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<h1 align="center">Boost.Threads</h1>
|
||||
<h2 align="center">Header <<a href="../../../boost/thread/thread_pool.hpp">boost/thread/thread_pool.hpp</a>></h2>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<h2>Contents</h2>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#introduction">Introduction</a></dt>
|
||||
<dt><a href="#classes">Classes</a></dt>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#class-thread_pool">Class <code>thread_pool</code></a></dt>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#class-thread_pool-synopsis">Class <code>thread_pool</code> synopsis</a></dt>
|
||||
<dt><a href="#class-thread_pool-ctors">Class <code>thread_pool</code> constructors and destructor</a></dt>
|
||||
<dt><a href="#class-thread_pool-modifiers">Class <code>thread_pool</code> modifier functions</a></dt>
|
||||
</dl>
|
||||
</dl>
|
||||
<dt><a href="#examples">Example(s)</a></dt>
|
||||
</dl>
|
||||
<hr>
|
||||
<h2><a name="introduction"></a>Introduction</h2>
|
||||
<p>Include the header <<a href="../../../boost/thread/thread_pool.hpp">boost/thread/thread_pool.hpp</a>>
|
||||
to define the <a href="#class-thread_pool">thread_pool</a> class.</p>
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
<h3><a name="class-thread_pool"></a>Class <code>thread_pool</code></h3>
|
||||
|
||||
<p>The <tt>thread_pool</tt> class provides an interface for running
|
||||
jobs on a dynamically managed set of worker threads called a pool.
|
||||
When a job is added, it can execute on any available thread in the pool.
|
||||
This class controls both the maximum and minimum number of threads in
|
||||
the pool. If a thread in the pool is sitting idle for a period of
|
||||
time, it will exit unless by exiting the number of threads would dip below
|
||||
the minimum. Thread pools provide an optimization over creating a new thread
|
||||
for each job since the pool can often remove the overhead of thread creation.</p>
|
||||
<h4><a name="class-thread_pool-synopsis"></a>Class <code>thread_pool</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost
|
||||
{
|
||||
class thread_pool : <a href="../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
|
||||
// Class thread meets the <a href="overview.html#non-copyable">NonCopyable</a> requirement.
|
||||
{
|
||||
public:
|
||||
thread_pool(int max_threads=std::numeric_limits<int>::max(),
|
||||
int min_threads=0,
|
||||
int timeout_secs=5);
|
||||
~thread_pool();
|
||||
|
||||
void add(const boost::function0<void> &job);
|
||||
void join();
|
||||
void cancel();
|
||||
void detach();
|
||||
};
|
||||
};
|
||||
</pre>
|
||||
<h4><a name="class-spec-ctors"></a>Class <code>thread_pool</code> constructors and destructor</h4>
|
||||
<pre>
|
||||
thread_pool(int max_threads=std::numeric_limits<int>::max(),
|
||||
int min_threads=0,
|
||||
int timeout_secs=5);
|
||||
</pre>
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> Constructs a thread pool object and starts min_threads threads
|
||||
running in the pool.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
~thread_pool();
|
||||
</pre>
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> Calls join() if neither join() nor detach() were called
|
||||
previously for this thread_pool. If detach() was not called, destroys all
|
||||
resources associated with the threads in the pool and with the queue of jobs
|
||||
still waiting to be executed.</dt>
|
||||
</dl>
|
||||
<h4><a name="class-spec-modifiers"></a>Class <code>thread_pool</code> modifier
|
||||
functions</h4>
|
||||
<pre>
|
||||
void add(const boost::function0<void>& job);
|
||||
</pre>
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> Adds <tt>job</tt> to the <tt>thread_pool</tt> object's list of
|
||||
jobs waiting to be executed. If any threads in the pool are idle, the job
|
||||
will be execute as soon as the idle thread is scheduled by the operating
|
||||
system. If no threads are idle and the number of threads in the pool is
|
||||
less than the maximum number provided to the constructor, an additional thread
|
||||
is created and added to the pool. That new thread will execute this job
|
||||
as soon as it is scheduled by the operating system. If no threads are
|
||||
idle and the thread count is at the maximum, this job will be queued until
|
||||
a thread becomes available. Currently, queued jobs are processed in FIFO
|
||||
order.</dt>
|
||||
<dt><b>Throws:</b> std::runtime_error if join() or detach() have
|
||||
previously been called for this thread_pool object.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
void detach();
|
||||
</pre>
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> Relinquishes control of the pool of threads by this thread_pool
|
||||
object. Any threads in the pool will continue to run and continue to
|
||||
process any queued jobs, but no new threads will be created, and any subsequent
|
||||
attempts to add new jobs will result in an exception.</dt>
|
||||
<dt><b>Throws:</b> std::runtime_error if join() has previously
|
||||
been called for this thread_pool object.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
void cancel();
|
||||
</pre>
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> Removes all queued jobs from the thread_pool's internal queue,
|
||||
and calls cancel() on all boost::thread objects in the pool. The specific
|
||||
behavior of those threads will be dictated by their cancellation behavior - the
|
||||
pool threads may be executing a user's job that deferrs cancellation, for
|
||||
example.</dt>
|
||||
<dt><b>Throws:</b> std::runtime_error if join() or detach() have
|
||||
previously been called for this thread_pool object.</dt>
|
||||
<dt><b>Note:</b> for the current version (1.27.0) of Boost.Threads, thread::cancel() is
|
||||
not provided. This function -will- clear out all queued jobs, but any
|
||||
currently executing jobs will not be cancelled.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
void join();
|
||||
</pre>
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> Waits until all queued jobs are completed by the thread pool,
|
||||
and then join()s will all of the threads in the pool. When join()
|
||||
returns, no running threads will remain in the pool, and this object is invalid
|
||||
for anything except destruction. Any calls to cancel(), join(), detach(),
|
||||
or add() will result in an exception.</dt>
|
||||
</dl>
|
||||
<h2><a name="examples"></a>Example(s)</h2>
|
||||
<pre>
|
||||
#include <boost/thread/thread_pool.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <iostream>
|
||||
|
||||
boost::mutex io_mutex;
|
||||
|
||||
class job_adapter {
|
||||
public:
|
||||
job_adapter(void (*func)(int), int param) :
|
||||
_func(func), _param(param){ }
|
||||
void operator()() const { _func(_param); }
|
||||
private:
|
||||
void (*_func)(int);
|
||||
int _param;
|
||||
};
|
||||
|
||||
void simple_job(int param)
|
||||
{
|
||||
boost::mutex::scoped_lock l(io_mutex);
|
||||
std::cout << param << " squared is " << (param*param) << "\n";
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
boost::thread_pool tp;
|
||||
for (int i = 1; i <= 10; ++i)
|
||||
tp.add(simple_job);
|
||||
tp.join();
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
<p>Typical output would be:</p>
|
||||
<pre>
|
||||
1 squared is 1
|
||||
2 squared is 4
|
||||
3 squared is 9
|
||||
4 squared is 16
|
||||
5 squared is 25
|
||||
7 squared is 49
|
||||
6 squared is 36
|
||||
8 squared is 64
|
||||
10 squared is 100
|
||||
9 squared is 81
|
||||
</pre>
|
||||
<P>While the jobs are dispatched in the order they are received, the scheduling of
|
||||
the individual threads in the pool is platform-dependent.</P>
|
||||
<P>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
05 November, 2001
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="mailto:wekempf@cox.net">William E. Kempf</a>, David Moore 2001-2002.
|
||||
All Rights Reserved.</i></p>
|
||||
<p>Permission to use, copy, modify, distribute and sell this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided that the
|
||||
above copyright notice appear in all copies and that both that copyright notice
|
||||
and this permission notice appear in supporting documentation. William E. Kempf
|
||||
makes no representations about the suitability of this software for any purpose.
|
||||
It is provided "as is" without express or implied warranty.</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -199,4 +199,4 @@
|
||||
</method-group>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
</header>
|
||||
|
||||
@@ -75,4 +75,4 @@
|
||||
</data-member>
|
||||
</struct>
|
||||
</namespace>
|
||||
</header>
|
||||
</header>
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
bin
|
||||
*.pdb
|
||||
*.pdb
|
||||
|
||||
@@ -1,54 +1,52 @@
|
||||
# Copyright (C) 2001-2003
|
||||
# William E. Kempf
|
||||
# Copyright (C) 2006 Roland Schwarz.
|
||||
# Distributed under the Boost Software License, Version 1.0. (See
|
||||
# accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# 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 work is a reimplementation along the design and ideas
|
||||
# of William E. Kempf.
|
||||
#
|
||||
# Boost.Threads example Jamfile
|
||||
#
|
||||
# Additional configuration variables used:
|
||||
# 1. PTW32 may be used on Win32 platforms to specify that the pthreads-win32
|
||||
# library should be used instead of "native" threads. This feature is
|
||||
# mostly used for testing and it's generally recommended you use the
|
||||
# native threading libraries instead. PTW32 should be set to be a list
|
||||
# of two strings, the first specifying the installation path of the
|
||||
# pthreads-win32 library and the second specifying which library
|
||||
# variant to link against (see the pthreads-win32 documentation).
|
||||
# Example: jam -sPTW32="c:\pthreads-win32 pthreadVCE.lib"
|
||||
|
||||
# Declare the location of this subproject relative to the root.
|
||||
subproject libs/thread/example ;
|
||||
# The threading library is available in two versions.
|
||||
# Native to the environment or based ontop pthread.
|
||||
# To select which version to use you need to define
|
||||
# BOOST_THREAD_POSIX when compiling your sources.
|
||||
# If BOOST_THREAD_POSIX is defined this will choose
|
||||
# pthread implementation.
|
||||
# You also need to specify the correct library version by
|
||||
# specifying the the <lib> or <dll> tags.
|
||||
# <lib>@boost/libs/thread/build/boost_thread for static native and
|
||||
# <lib>@boost/libs/thread/build/boost_thread_pthread static pthread.
|
||||
# If your compiler does not have the pthread lib in a standard
|
||||
# include path, you need to specify that too, with <include> and
|
||||
# <library-file>.
|
||||
|
||||
# Include threads.jam for Boost.Threads global build information.
|
||||
# This greatly simplifies the Jam code needed to configure the build
|
||||
# for the various Win32 build types.
|
||||
import ../build/threads ;
|
||||
project-root ;
|
||||
|
||||
{
|
||||
template example
|
||||
## sources ##
|
||||
: <template>thread_base
|
||||
<dll>../build/boost_thread
|
||||
## requirements ##
|
||||
:
|
||||
## default build ##
|
||||
:
|
||||
;
|
||||
template example
|
||||
: ## sources ##
|
||||
<lib>@boost/libs/thread/build/boost_thread
|
||||
#<lib>@boost/libs/thread/build/boost_thread_pthread
|
||||
#<dll>@boost/libs/thread/build/boost_thread
|
||||
#<dll>@boost/libs/thread/build/boost_thread_pthread
|
||||
: ## requirements ##
|
||||
<include>$(BOOST_ROOT)
|
||||
# uncomment below to get pthread on windows
|
||||
#<define>BOOST_THREAD_POSIX
|
||||
#<include>$(PTW32_INCLUDE)
|
||||
#<library-file>$(PTW32_LIB)
|
||||
: ## default build ##
|
||||
<threading>multi
|
||||
;
|
||||
|
||||
exe monitor : <template>example monitor.cpp ;
|
||||
exe starvephil : <template>example starvephil.cpp ;
|
||||
exe tennis : <template>example tennis.cpp ;
|
||||
exe condition : <template>example condition.cpp ;
|
||||
exe mutex : <template>example mutex.cpp ;
|
||||
exe once : <template>example once.cpp ;
|
||||
exe recursive_mutex : <template>example recursive_mutex.cpp ;
|
||||
exe thread : <template>example thread.cpp ;
|
||||
exe thread_group : <template>example thread_group.cpp ;
|
||||
exe tss : <template>example tss.cpp ;
|
||||
exe xtime : <template>example xtime.cpp ;
|
||||
}
|
||||
exe monitor : <template>example monitor.cpp ;
|
||||
exe starvephil : <template>example starvephil.cpp ;
|
||||
exe tennis : <template>example tennis.cpp ;
|
||||
exe condition : <template>example condition.cpp ;
|
||||
exe mutex : <template>example mutex.cpp ;
|
||||
exe once : <template>example once.cpp ;
|
||||
exe recursive_mutex : <template>example recursive_mutex.cpp ;
|
||||
exe thread : <template>example thread.cpp ;
|
||||
exe thread_group : <template>example thread_group.cpp ;
|
||||
exe tss : <template>example tss.cpp ;
|
||||
exe xtime : <template>example xtime.cpp ;
|
||||
|
||||
53
example/Jamrules
Normal file
53
example/Jamrules
Normal file
@@ -0,0 +1,53 @@
|
||||
# Copyright 2003 William E. Kempf
|
||||
# Copyright 2006 Roland Schwarz
|
||||
# Distributed under the Boost Software License, Version 1.0. (See
|
||||
# accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# This work is a reimplementation along the design and ideas
|
||||
# of William E. Kempf.
|
||||
|
||||
project example ;
|
||||
|
||||
# If you move this example from its place in the Boost tree, edit this
|
||||
# path to point at the root directory of your Boost installation (the
|
||||
# one containing a subdirectory called "boost/".
|
||||
path-global BOOST_ROOT : ../../.. ;
|
||||
|
||||
# Makes a project id for boost so that other Boost.Build projects can
|
||||
# refer to it by name.
|
||||
#
|
||||
project boost : $(BOOST_ROOT) ;
|
||||
|
||||
# Attn: path-global was broken in my version of bbv1, which prevented specifying
|
||||
# BOOST_ROOT as a relative path. So I needed to apply
|
||||
# the below fix in allyourbase.jam as shown below:
|
||||
#
|
||||
#rule project ( name : location ? )
|
||||
#{
|
||||
# if ! $(location)
|
||||
# {
|
||||
# gPROJECT($(name)) = $(gPROJECT($(PROJECT))) ;
|
||||
# PROJECT($(gPROJECT($(name)))) = $(name) ;
|
||||
# PROJECT = $(name) ;
|
||||
# }
|
||||
# else
|
||||
# {
|
||||
# gPROJECT($(name)) = [ root-paths $(location) : [ root-paths $($(gTOP)) : [ PWD ] ] ] ;
|
||||
# # speedsnail
|
||||
# # Root the path globals to fix a bug which prevented to use them from an external
|
||||
# # project. The fix is as as uninvasive as possible, as it will only trigger when
|
||||
# # an external project is declared. So it will not interfere with the build of the
|
||||
# # boost library. I took this route, as at the time of this fix, the bbv1 is expected
|
||||
# # to be retired soon.
|
||||
# # N.B.: The path-globals rule is expected to be invoked from Jamrules files only.
|
||||
# local val ;
|
||||
# for val in $(gPATH_GLOBALS) {
|
||||
# gPATH_GLOBAL_VALUE($(val)) = [ root-paths $(gPATH_GLOBAL_VALUE($(val))) :
|
||||
# [ root-paths $($(gTOP)) : [ PWD ] ]
|
||||
# ] ;
|
||||
# }
|
||||
# local [ protect-subproject ] ;
|
||||
# enter-subproject @$(name) ;
|
||||
# }
|
||||
#}
|
||||
22
example/boost-build.jam
Executable file
22
example/boost-build.jam
Executable file
@@ -0,0 +1,22 @@
|
||||
# Copyright 2006 Roland Schwarz.
|
||||
# Distributed under the Boost Software License, Version 1.0. (See
|
||||
# accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# This work is a reimplementation along the design and ideas
|
||||
# of William E. Kempf.
|
||||
#
|
||||
|
||||
# Edit this path to point at the tools/build/v1 subdirectory of your
|
||||
# Boost installation.
|
||||
|
||||
if --v2 in $(ARGV)
|
||||
{
|
||||
JAMFILE = [Bb]uild.jam [Jj]amfile.v2 ;
|
||||
boost-build ../../../tools/build/v2 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
boost-build ../../../tools/build/v1 ;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// 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
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
@@ -43,7 +38,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
int begin, end, buffered;
|
||||
int begin, end;
|
||||
std::vector<int>::size_type buffered;
|
||||
std::vector<int> circular_buf;
|
||||
boost::condition buffer_not_full, buffer_not_empty;
|
||||
boost::mutex monitor;
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// 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
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// 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
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// 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
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/once.hpp>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// 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
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// 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
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
@@ -19,7 +14,7 @@
|
||||
namespace
|
||||
{
|
||||
boost::mutex iomx;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class canteen
|
||||
{
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// 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
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// 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
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <iostream>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// 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
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/tss.hpp>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// 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
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
|
||||
@@ -9,30 +9,16 @@
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#ifndef BOOST_NAMED_WEK031703_HPP
|
||||
#define BOOST_NAMED_WEK031703_HPP
|
||||
#if !defined(BOOST_THREAD_WEK01082003_HPP)
|
||||
#define BOOST_THREAD_WEK01082003_HPP
|
||||
|
||||
#include <boost/thread/detail/config.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>
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
|
||||
class named_object
|
||||
{
|
||||
protected:
|
||||
named_object(const char* name=0);
|
||||
~named_object();
|
||||
|
||||
public:
|
||||
const char* name() const;
|
||||
const char* effective_name() const;
|
||||
|
||||
protected:
|
||||
char* m_name;
|
||||
char* m_ename;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_NAMED_WEK031703_HPP
|
||||
#endif
|
||||
@@ -1,40 +1,64 @@
|
||||
// Copyright (C) 2002-2003
|
||||
// David Moore, William E. Kempf
|
||||
#ifndef BOOST_THREAD_BARRIER_HPP
|
||||
#define BOOST_THREAD_BARRIER_HPP
|
||||
|
||||
// barrier.hpp
|
||||
//
|
||||
// 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_BARRIER_JDM030602_HPP
|
||||
#define BOOST_BARRIER_JDM030602_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
// (C) Copyright 2006 Anthony Williams
|
||||
//
|
||||
// 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 <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <boost/thread/detail/platform.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
class BOOST_THREAD_DECL barrier
|
||||
#ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std
|
||||
{
|
||||
public:
|
||||
barrier(unsigned int count);
|
||||
~barrier();
|
||||
using ::size_t;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool wait();
|
||||
namespace boost
|
||||
{
|
||||
class barrier
|
||||
{
|
||||
boost::mutex m;
|
||||
boost::condition cond;
|
||||
|
||||
const std::size_t max_count;
|
||||
std::size_t current_count;
|
||||
public:
|
||||
barrier(std::size_t count):
|
||||
max_count(count),current_count(0)
|
||||
{
|
||||
if(!max_count)
|
||||
{
|
||||
throw std::invalid_argument("You must specify a non-zero count");
|
||||
}
|
||||
}
|
||||
|
||||
bool wait()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m);
|
||||
if(++current_count==max_count)
|
||||
{
|
||||
current_count=0;
|
||||
cond.notify_all();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
cond.wait(lock);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
private:
|
||||
mutex m_mutex;
|
||||
condition m_cond;
|
||||
unsigned int m_threshold;
|
||||
unsigned int m_count;
|
||||
unsigned int m_generation;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,198 +1,16 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// 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 work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_CONDITION_WEK070601_HPP
|
||||
#define BOOST_CONDITION_WEK070601_HPP
|
||||
#ifndef BOOST_THREAD_RS06040706_HPP
|
||||
#define BOOST_THREAD_RS06040706_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/platform.hpp>
|
||||
#include BOOST_THREAD_PLATFORM(condition.hpp)
|
||||
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/detail/lock.hpp>
|
||||
#endif // BOOST_THREAD_RS06040706_HPP
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
# include "scoped_critical_region.hpp"
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct xtime;
|
||||
|
||||
namespace detail {
|
||||
|
||||
class BOOST_THREAD_DECL condition_impl : private noncopyable
|
||||
{
|
||||
friend class condition;
|
||||
|
||||
public:
|
||||
condition_impl();
|
||||
~condition_impl();
|
||||
|
||||
void notify_one();
|
||||
void notify_all();
|
||||
|
||||
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
void enter_wait();
|
||||
void do_wait();
|
||||
bool do_timed_wait(const xtime& xt);
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
void do_wait(pthread_mutex_t* pmutex);
|
||||
bool do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex);
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
void* m_gate;
|
||||
void* m_queue;
|
||||
void* m_mutex;
|
||||
unsigned m_gone; // # threads that timed out and never made it to m_queue
|
||||
unsigned long m_blocked; // # threads blocked on the condition
|
||||
unsigned m_waiting; // # threads no longer waiting for the condition but
|
||||
// still waiting to be removed from m_queue
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_cond_t m_condition;
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
MPSemaphoreID m_gate;
|
||||
MPSemaphoreID m_queue;
|
||||
threads::mac::detail::scoped_critical_region m_mutex;
|
||||
threads::mac::detail::scoped_critical_region m_mutex_mutex;
|
||||
unsigned m_gone; // # threads that timed out and never made it to m_queue
|
||||
unsigned long m_blocked; // # threads blocked on the condition
|
||||
unsigned m_waiting; // # threads no longer waiting for the condition but
|
||||
// still waiting to be removed from m_queue
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class condition : private noncopyable
|
||||
{
|
||||
public:
|
||||
condition() { }
|
||||
~condition() { }
|
||||
|
||||
void notify_one() { m_impl.notify_one(); }
|
||||
void notify_all() { m_impl.notify_all(); }
|
||||
|
||||
template <typename L>
|
||||
void wait(L& lock)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
do_wait(lock.m_mutex);
|
||||
}
|
||||
|
||||
template <typename L, typename Pr>
|
||||
void wait(L& lock, Pr pred)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
while (!pred())
|
||||
do_wait(lock.m_mutex);
|
||||
}
|
||||
|
||||
template <typename L>
|
||||
bool timed_wait(L& lock, const xtime& xt)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
return do_timed_wait(lock.m_mutex, xt);
|
||||
}
|
||||
|
||||
template <typename L, typename Pr>
|
||||
bool timed_wait(L& lock, const xtime& xt, Pr pred)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
while (!pred())
|
||||
{
|
||||
if (!do_timed_wait(lock.m_mutex, xt))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
detail::condition_impl m_impl;
|
||||
|
||||
template <typename M>
|
||||
void do_wait(M& mutex)
|
||||
{
|
||||
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
m_impl.enter_wait();
|
||||
#endif
|
||||
|
||||
typedef detail::thread::lock_ops<M>
|
||||
#if defined(__HP_aCC) && __HP_aCC <= 33900 && !defined(BOOST_STRICT_CONFIG)
|
||||
# define lock_ops lock_ops_ // HP confuses lock_ops witht the template
|
||||
#endif
|
||||
lock_ops;
|
||||
|
||||
typename lock_ops::lock_state state;
|
||||
lock_ops::unlock(mutex, state);
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
m_impl.do_wait(state.pmutex);
|
||||
#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
m_impl.do_wait();
|
||||
#endif
|
||||
|
||||
lock_ops::lock(mutex, state);
|
||||
#undef lock_ops
|
||||
}
|
||||
|
||||
template <typename M>
|
||||
bool do_timed_wait(M& mutex, const xtime& xt)
|
||||
{
|
||||
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
m_impl.enter_wait();
|
||||
#endif
|
||||
|
||||
typedef detail::thread::lock_ops<M>
|
||||
#if defined(__HP_aCC) && __HP_aCC <= 33900 && !defined(BOOST_STRICT_CONFIG)
|
||||
# define lock_ops lock_ops_ // HP confuses lock_ops witht the template
|
||||
#endif
|
||||
lock_ops;
|
||||
|
||||
typename lock_ops::lock_state state;
|
||||
lock_ops::unlock(mutex, state);
|
||||
|
||||
bool ret = false;
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
ret = m_impl.do_timed_wait(xt, state.pmutex);
|
||||
#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
ret = m_impl.do_timed_wait(xt);
|
||||
#endif
|
||||
|
||||
lock_ops::lock(mutex, state);
|
||||
#undef lock_ops
|
||||
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
|
||||
// 23 May 01 WEKEMPF Removed "duration" timed_waits, as they are too
|
||||
// difficult to use with spurious wakeups.
|
||||
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
|
||||
|
||||
#endif // BOOST_CONDITION_WEK070601_HPP
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#ifndef BOOST_THREAD_CONFIG_WEK01032003_HPP
|
||||
#define BOOST_THREAD_CONFIG_WEK01032003_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
// insist on threading support being available:
|
||||
#include <boost/config/requires_threads.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
# if defined(BOOST_THREAD_BUILD_DLL) //Build dll
|
||||
# define BOOST_THREAD_DECL __declspec(dllexport)
|
||||
# elif defined(BOOST_THREAD_BUILD_LIB) //Build lib
|
||||
# define BOOST_THREAD_DECL
|
||||
# elif defined(BOOST_THREAD_USE_LIB) //Use lib
|
||||
# define BOOST_THREAD_DECL
|
||||
# else //Use dll
|
||||
# define BOOST_THREAD_DECL __declspec(dllimport)
|
||||
# define BOOST_DYN_LINK
|
||||
# endif
|
||||
#else
|
||||
# define BOOST_THREAD_DECL
|
||||
# if defined(BOOST_THREAD_USE_LIB) //Use lib
|
||||
# else //Use dll
|
||||
# define BOOST_DYN_LINK
|
||||
# endif
|
||||
#endif // BOOST_HAS_WINTHREADS
|
||||
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
// 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
|
||||
@@ -1,43 +0,0 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// Mac Murrett
|
||||
//
|
||||
// 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. Mac Murrett makes no representations
|
||||
// about the suitability of this software for any purpose. It is
|
||||
// provided "as is" without express or implied warranty.
|
||||
//
|
||||
// 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
|
||||
72
include/boost/thread/detail/platform.hpp
Normal file
72
include/boost/thread/detail/platform.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_THREAD_RS06040501_HPP
|
||||
#define BOOST_THREAD_RS06040501_HPP
|
||||
|
||||
// fetch compiler and platform configuration
|
||||
#include <boost/config.hpp>
|
||||
|
||||
// insist on threading support being available:
|
||||
#include <boost/config/requires_threads.hpp>
|
||||
|
||||
// choose platform
|
||||
#if defined(linux) || defined(__linux) || defined(__linux__)
|
||||
# define BOOST_THREAD_LINUX
|
||||
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
# define BOOST_THREAD_BSD
|
||||
#elif defined(sun) || defined(__sun)
|
||||
# define BOOST_THREAD_SOLARIS
|
||||
#elif defined(__sgi)
|
||||
# define BOOST_THREAD_IRIX
|
||||
#elif defined(__hpux)
|
||||
# define BOOST_THREAD_HPUX
|
||||
#elif defined(__CYGWIN__)
|
||||
# define BOOST_THREAD_CYGWIN
|
||||
#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
|
||||
# define BOOST_THREAD_WIN32
|
||||
#elif defined(__BEOS__)
|
||||
# define BOOST_THREAD_BEOS
|
||||
#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
|
||||
# define BOOST_THREAD_MACOS
|
||||
#elif defined(__IBMCPP__) || defined(_AIX)
|
||||
# define BOOST_THREAD_AIX
|
||||
#elif defined(__amigaos__)
|
||||
# define BOOST_THREAD_AMIGAOS
|
||||
#elif defined(__QNXNTO__)
|
||||
# define BOOST_THREAD_QNXNTO
|
||||
#elif defined(unix) || defined(__unix) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE)
|
||||
# if defined(BOOST_HAS_PTHREADS) && !defined(BOOST_THREAD_POSIX)
|
||||
# define BOOST_THREAD_POSIX
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// For every supported platform add a new entry into the dispatch table below.
|
||||
// BOOST_THREAD_POSIX is tested first, so on platforms where posix and native
|
||||
// threading is available, the user may choose, by defining BOOST_THREAD_POSIX
|
||||
// in her source. If a platform is known to support pthreads and no native
|
||||
// port of boost_thread is available just specify "pthread" in the
|
||||
// dispatcher table. If there is no entry for a platform but pthreads is
|
||||
// available on the platform, pthread is choosen as default. If nothing is
|
||||
// available the preprocessor will fail with a diagnostic message.
|
||||
|
||||
#if defined(BOOST_THREAD_POSIX)
|
||||
# define BOOST_THREAD_PPFX pthread
|
||||
#else
|
||||
# if defined(BOOST_THREAD_WIN32)
|
||||
# define BOOST_THREAD_PPFX win32
|
||||
# elif defined(BOOST_HAS_PTHREADS)
|
||||
# define BOOST_THREAD_PPFX pthread
|
||||
# else
|
||||
# error "Sorry, no boost threads are available for this platform."
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define BOOST_THREAD_PLATFORM(header) <boost/thread/BOOST_THREAD_PPFX/header>
|
||||
|
||||
#endif // BOOST_THREAD_RS06040501_HPP
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,63 +0,0 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// Mac Murrett
|
||||
//
|
||||
// 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. Mac Murrett makes no representations
|
||||
// about the suitability of this software for any purpose. It is
|
||||
// provided "as is" without express or implied warranty.
|
||||
//
|
||||
// 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
|
||||
@@ -1,35 +0,0 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#ifndef BOOST_THREADMON_WEK062504_HPP
|
||||
#define BOOST_THREADMON_WEK062504_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_WINTHREADS
|
||||
|
||||
extern "C" BOOST_THREAD_DECL int at_thread_exit(void (__cdecl * func)(void));
|
||||
//Add a function to the list of thread-exit functions
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_process_enter(void);
|
||||
//To be called when the process starts, when the dll is loaded, etc.
|
||||
//Called automatically by Boost.Thread when possible
|
||||
extern "C" BOOST_THREAD_DECL void on_thread_exit(void);
|
||||
//To be called for each thread when it exits
|
||||
//Must be called in the context of the thread that is exiting
|
||||
//Called automatically by Boost.Thread when possible
|
||||
extern "C" BOOST_THREAD_DECL void on_process_exit(void);
|
||||
//To be called when the process exits, when the dll is unloaded, etc.
|
||||
//Called automatically by Boost.Thread when possible
|
||||
|
||||
#endif // BOOST_HAS_WINTHREADS
|
||||
|
||||
#endif // BOOST_THREADMON_WEK062504_HPP
|
||||
@@ -1,100 +1,16 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// 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 work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_THREAD_EXCEPTIONS_PDM070801_H
|
||||
#define BOOST_THREAD_EXCEPTIONS_PDM070801_H
|
||||
#ifndef BOOST_THREAD_RS06040710_HPP
|
||||
#define BOOST_THREAD_RS06040710_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/platform.hpp>
|
||||
#include BOOST_THREAD_PLATFORM(exceptions.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 <stdexcept>
|
||||
|
||||
namespace boost {
|
||||
|
||||
class BOOST_THREAD_DECL thread_exception : public std::exception
|
||||
{
|
||||
protected:
|
||||
thread_exception();
|
||||
thread_exception(int sys_err_code);
|
||||
|
||||
public:
|
||||
~thread_exception() throw();
|
||||
|
||||
int native_error() const { return m_sys_err; }
|
||||
|
||||
const char* message() const;
|
||||
|
||||
private:
|
||||
int m_sys_err;
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL lock_error : public thread_exception
|
||||
{
|
||||
public:
|
||||
lock_error();
|
||||
lock_error(int sys_err_code);
|
||||
~lock_error() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL thread_resource_error : public thread_exception
|
||||
{
|
||||
public:
|
||||
thread_resource_error();
|
||||
thread_resource_error(int sys_err_code);
|
||||
~thread_resource_error() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL unsupported_thread_option : public thread_exception
|
||||
{
|
||||
public:
|
||||
unsupported_thread_option();
|
||||
unsupported_thread_option(int sys_err_code);
|
||||
~unsupported_thread_option() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL invalid_thread_argument : public thread_exception
|
||||
{
|
||||
public:
|
||||
invalid_thread_argument();
|
||||
invalid_thread_argument(int sys_err_code);
|
||||
~invalid_thread_argument() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL thread_permission_error : public thread_exception
|
||||
{
|
||||
public:
|
||||
thread_permission_error();
|
||||
thread_permission_error(int sys_err_code);
|
||||
~thread_permission_error() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_THREAD_CONFIG_PDM070801_H
|
||||
|
||||
// Change log:
|
||||
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
|
||||
#endif // BOOST_THREAD_RS06040710_HPP
|
||||
|
||||
|
||||
@@ -1,171 +1,16 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// 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 work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_MUTEX_WEK070601_HPP
|
||||
#define BOOST_MUTEX_WEK070601_HPP
|
||||
#ifndef BOOST_THREAD_RS06040704_HPP
|
||||
#define BOOST_THREAD_RS06040704_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/platform.hpp>
|
||||
#include BOOST_THREAD_PLATFORM(mutex.hpp)
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/detail/lock.hpp>
|
||||
#include <boost/thread/detail/named.hpp>
|
||||
#endif // BOOST_THREAD_RS06040704_HPP
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_MPTASKS)
|
||||
# include "scoped_critical_region.hpp"
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct xtime;
|
||||
|
||||
class BOOST_THREAD_DECL mutex
|
||||
: private noncopyable
|
||||
, public boost::detail::named_object
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::lock_ops<mutex>;
|
||||
|
||||
typedef detail::thread::scoped_lock<mutex> scoped_lock;
|
||||
|
||||
mutex(const char* name=0);
|
||||
~mutex();
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
typedef void* cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
struct cv_state
|
||||
{
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
void* m_mutex;
|
||||
bool m_critical_section;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
threads::mac::detail::scoped_critical_region m_mutex;
|
||||
threads::mac::detail::scoped_critical_region m_mutex_mutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL try_mutex
|
||||
: private noncopyable
|
||||
, public boost::detail::named_object
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::lock_ops<try_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_lock<try_mutex> scoped_lock;
|
||||
typedef detail::thread::scoped_try_lock<try_mutex> scoped_try_lock;
|
||||
|
||||
try_mutex(const char* name=0);
|
||||
~try_mutex();
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
typedef void* cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
struct cv_state
|
||||
{
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
void* m_mutex;
|
||||
bool m_critical_section;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
threads::mac::detail::scoped_critical_region m_mutex;
|
||||
threads::mac::detail::scoped_critical_region m_mutex_mutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL timed_mutex
|
||||
: private noncopyable
|
||||
, public boost::detail::named_object
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::lock_ops<timed_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_lock<timed_mutex> scoped_lock;
|
||||
typedef detail::thread::scoped_try_lock<timed_mutex> scoped_try_lock;
|
||||
typedef detail::thread::scoped_timed_lock<timed_mutex> scoped_timed_lock;
|
||||
|
||||
timed_mutex(const char* name=0);
|
||||
~timed_mutex();
|
||||
|
||||
private:
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
typedef void* cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
struct cv_state
|
||||
{
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
bool do_timedlock(const xtime& xt);
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
void* m_mutex;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
pthread_cond_t m_condition;
|
||||
bool m_locked;
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
threads::mac::detail::scoped_critical_region m_mutex;
|
||||
threads::mac::detail::scoped_critical_region m_mutex_mutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // 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,42 +1,16 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
#ifndef BOOST_THREAD_ONCE_HPP
|
||||
#define BOOST_THREAD_ONCE_HPP
|
||||
|
||||
// once.hpp
|
||||
//
|
||||
// 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.
|
||||
// (C) Copyright 2006 Anthony Williams
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_ONCE_WEK080101_HPP
|
||||
#define BOOST_ONCE_WEK080101_HPP
|
||||
#include <boost/thread/detail/platform.hpp>
|
||||
#include BOOST_THREAD_PLATFORM(once.hpp)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
|
||||
typedef pthread_once_t once_flag;
|
||||
#define BOOST_ONCE_INIT PTHREAD_ONCE_INIT
|
||||
|
||||
#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
|
||||
typedef long once_flag;
|
||||
#define BOOST_ONCE_INIT 0
|
||||
|
||||
#endif
|
||||
|
||||
void BOOST_THREAD_DECL call_once(void (*func)(), once_flag& flag);
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// Change Log:
|
||||
// 1 Aug 01 WEKEMPF Initial version.
|
||||
|
||||
#endif // BOOST_ONCE_WEK080101_HPP
|
||||
|
||||
156
include/boost/thread/pthread/condition.hpp
Normal file
156
include/boost/thread/pthread/condition.hpp
Normal file
@@ -0,0 +1,156 @@
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_THREAD_RS06040707_HPP
|
||||
#define BOOST_THREAD_RS06040707_HPP
|
||||
|
||||
#include <boost/thread/pthread/config.hpp>
|
||||
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/pthread/lock.hpp>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
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();
|
||||
|
||||
void do_wait(pthread_mutex_t* pmutex);
|
||||
bool do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex);
|
||||
|
||||
pthread_cond_t m_condition;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class condition : private noncopyable
|
||||
{
|
||||
public:
|
||||
condition() { }
|
||||
~condition() { }
|
||||
|
||||
void notify_one() { m_impl.notify_one(); }
|
||||
void notify_all() { m_impl.notify_all(); }
|
||||
|
||||
template <typename L>
|
||||
void wait(L& lock)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
do_wait(lock.m_mutex);
|
||||
}
|
||||
|
||||
template <typename L, typename Pr>
|
||||
void wait(L& lock, Pr pred)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
while (!pred())
|
||||
do_wait(lock.m_mutex);
|
||||
}
|
||||
|
||||
template <typename L>
|
||||
bool timed_wait(L& lock, const xtime& xt)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
return do_timed_wait(lock.m_mutex, xt);
|
||||
}
|
||||
|
||||
template <typename L, typename Pr>
|
||||
bool timed_wait(L& lock, const xtime& xt, Pr pred)
|
||||
{
|
||||
if (!lock)
|
||||
throw lock_error();
|
||||
|
||||
while (!pred())
|
||||
{
|
||||
if (!do_timed_wait(lock.m_mutex, xt))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
detail::condition_impl m_impl;
|
||||
|
||||
template <typename M>
|
||||
void do_wait(M& mutex)
|
||||
{
|
||||
|
||||
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);
|
||||
|
||||
m_impl.do_wait(state.pmutex);
|
||||
|
||||
lock_ops::lock(mutex, state);
|
||||
#undef lock_ops
|
||||
}
|
||||
|
||||
template <typename M>
|
||||
bool do_timed_wait(M& mutex, const xtime& xt)
|
||||
{
|
||||
|
||||
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;
|
||||
|
||||
ret = m_impl.do_timed_wait(xt, state.pmutex);
|
||||
|
||||
lock_ops::lock(mutex, state);
|
||||
#undef lock_ops
|
||||
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_CONDITION_RS06040707_HPP
|
||||
77
include/boost/thread/pthread/config.hpp
Normal file
77
include/boost/thread/pthread/config.hpp
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_THREAD_RS06040702_HPP
|
||||
#define BOOST_THREAD_RS06040702_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
// insist on threading support being available:
|
||||
#include <boost/config/requires_threads.hpp>
|
||||
|
||||
#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_pthread
|
||||
#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_RS06040702_HPP
|
||||
88
include/boost/thread/pthread/exceptions.hpp
Normal file
88
include/boost/thread/pthread/exceptions.hpp
Normal file
@@ -0,0 +1,88 @@
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_THREAD_RS06040709_HPP
|
||||
#define BOOST_THREAD_RS06040709_HPP
|
||||
|
||||
#include <boost/thread/pthread/config.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace boost {
|
||||
|
||||
class BOOST_THREAD_DECL thread_exception : public std::exception
|
||||
{
|
||||
protected:
|
||||
thread_exception();
|
||||
thread_exception(int sys_err_code);
|
||||
|
||||
public:
|
||||
~thread_exception() throw();
|
||||
|
||||
int native_error() const;
|
||||
|
||||
const char* message() const;
|
||||
|
||||
private:
|
||||
int m_sys_err;
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL lock_error : public thread_exception
|
||||
{
|
||||
public:
|
||||
lock_error();
|
||||
lock_error(int sys_err_code);
|
||||
~lock_error() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL thread_resource_error : public thread_exception
|
||||
{
|
||||
public:
|
||||
thread_resource_error();
|
||||
thread_resource_error(int sys_err_code);
|
||||
~thread_resource_error() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL unsupported_thread_option : public thread_exception
|
||||
{
|
||||
public:
|
||||
unsupported_thread_option();
|
||||
unsupported_thread_option(int sys_err_code);
|
||||
~unsupported_thread_option() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL invalid_thread_argument : public thread_exception
|
||||
{
|
||||
public:
|
||||
invalid_thread_argument();
|
||||
invalid_thread_argument(int sys_err_code);
|
||||
~invalid_thread_argument() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL thread_permission_error : public thread_exception
|
||||
{
|
||||
public:
|
||||
thread_permission_error();
|
||||
thread_permission_error(int sys_err_code);
|
||||
~thread_permission_error() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_THREAD_RS06040709_HPP
|
||||
@@ -1,21 +1,18 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// 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 work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_XLOCK_WEK070601_HPP
|
||||
#define BOOST_XLOCK_WEK070601_HPP
|
||||
#ifndef BOOST_THREAD_RS06040708_HPP
|
||||
#define BOOST_THREAD_RS06040708_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/pthread/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/thread/pthread/exceptions.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
@@ -205,10 +202,4 @@ private:
|
||||
} // 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_THREAD_RS06040708_HPP
|
||||
116
include/boost/thread/pthread/mutex.hpp
Normal file
116
include/boost/thread/pthread/mutex.hpp
Normal file
@@ -0,0 +1,116 @@
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_THREAD_RS06040705_HPP
|
||||
#define BOOST_THREAD_RS06040705_HPP
|
||||
|
||||
#include <boost/thread/pthread/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/pthread/lock.hpp>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct xtime;
|
||||
|
||||
// disable warnings about non dll import
|
||||
// see: http://www.boost.org/more/separate_compilation.html#dlls
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4251 4231 4660 4275)
|
||||
#endif
|
||||
|
||||
class BOOST_THREAD_DECL mutex
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::lock_ops<mutex>;
|
||||
|
||||
typedef detail::thread::scoped_lock<mutex> scoped_lock;
|
||||
|
||||
mutex();
|
||||
~mutex();
|
||||
|
||||
private:
|
||||
struct cv_state
|
||||
{
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
void do_lock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
pthread_mutex_t m_mutex;
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL try_mutex
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::lock_ops<try_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_lock<try_mutex> scoped_lock;
|
||||
typedef detail::thread::scoped_try_lock<try_mutex> scoped_try_lock;
|
||||
|
||||
try_mutex();
|
||||
~try_mutex();
|
||||
|
||||
private:
|
||||
struct cv_state
|
||||
{
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
pthread_mutex_t m_mutex;
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL timed_mutex
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::lock_ops<timed_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_lock<timed_mutex> scoped_lock;
|
||||
typedef detail::thread::scoped_try_lock<timed_mutex> scoped_try_lock;
|
||||
typedef detail::thread::scoped_timed_lock<timed_mutex> scoped_timed_lock;
|
||||
|
||||
timed_mutex();
|
||||
~timed_mutex();
|
||||
|
||||
private:
|
||||
struct cv_state
|
||||
{
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
bool do_timedlock(const xtime& xt);
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
pthread_mutex_t m_mutex;
|
||||
pthread_cond_t m_condition;
|
||||
bool m_locked;
|
||||
};
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_MUTEX_RS06040705_HPP
|
||||
74
include/boost/thread/pthread/once.hpp
Normal file
74
include/boost/thread/pthread/once.hpp
Normal file
@@ -0,0 +1,74 @@
|
||||
#ifndef BOOST_THREAD_PTHREAD_ONCE_HPP
|
||||
#define BOOST_THREAD_PTHREAD_ONCE_HPP
|
||||
|
||||
// once.hpp
|
||||
//
|
||||
// (C) Copyright 2007 Anthony Williams
|
||||
//
|
||||
// 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/pthread/config.hpp>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct once_flag
|
||||
{
|
||||
pthread_mutex_t mutex;
|
||||
unsigned flag;
|
||||
};
|
||||
|
||||
#define BOOST_ONCE_INIT {PTHREAD_MUTEX_INITIALIZER,0}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct pthread_mutex_scoped_lock
|
||||
{
|
||||
pthread_mutex_t * mutex;
|
||||
|
||||
explicit pthread_mutex_scoped_lock(pthread_mutex_t* mutex_):
|
||||
mutex(mutex_)
|
||||
{
|
||||
int const res=pthread_mutex_lock(mutex);
|
||||
BOOST_ASSERT(!res);
|
||||
}
|
||||
~pthread_mutex_scoped_lock()
|
||||
{
|
||||
int const res=pthread_mutex_unlock(mutex);
|
||||
BOOST_ASSERT(!res);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Function>
|
||||
void call_once(once_flag& flag,Function f)
|
||||
{
|
||||
long const function_complete_flag_value=0xc15730e2;
|
||||
|
||||
#ifdef BOOST_PTHREAD_HAS_ATOMICS
|
||||
if(::boost::detail::interlocked_read_acquire(&flag.flag)!=function_complete_flag_value)
|
||||
{
|
||||
#endif
|
||||
detail::pthread_mutex_scoped_lock const lock(&flag.mutex);
|
||||
if(flag.flag!=function_complete_flag_value)
|
||||
{
|
||||
f();
|
||||
#ifdef BOOST_PTHREAD_HAS_ATOMICS
|
||||
::boost::detail::interlocked_write_release(&flag.flag,function_complete_flag_value);
|
||||
#else
|
||||
flag.flag=function_complete_flag_value;
|
||||
#endif
|
||||
}
|
||||
#ifdef BOOST_PTHREAD_HAS_ATOMICS
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
389
include/boost/thread/pthread/read_write_mutex.hpp
Normal file
389
include/boost/thread/pthread/read_write_mutex.hpp
Normal file
@@ -0,0 +1,389 @@
|
||||
#ifndef BOOST_THREAD_PTHREAD_READ_WRITE_MUTEX_HPP
|
||||
#define BOOST_THREAD_PTHREAD_READ_WRITE_MUTEX_HPP
|
||||
|
||||
// (C) Copyright 2006-7 Anthony Williams
|
||||
//
|
||||
// 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/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class read_write_mutex
|
||||
{
|
||||
private:
|
||||
struct state_data
|
||||
{
|
||||
unsigned shared_count:10;
|
||||
unsigned exclusive:1;
|
||||
unsigned upgradeable:1;
|
||||
unsigned exclusive_waiting_blocked:1;
|
||||
};
|
||||
|
||||
|
||||
|
||||
state_data state;
|
||||
boost::mutex state_change;
|
||||
boost::condition shared_cond;
|
||||
boost::condition exclusive_cond;
|
||||
boost::condition upgradeable_cond;
|
||||
|
||||
void release_waiters()
|
||||
{
|
||||
exclusive_cond.notify_one();
|
||||
shared_cond.notify_all();
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
read_write_mutex()
|
||||
{
|
||||
state_data state_={0};
|
||||
state=state_;
|
||||
}
|
||||
|
||||
~read_write_mutex()
|
||||
{
|
||||
}
|
||||
|
||||
void lock_shareable()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
|
||||
while(true)
|
||||
{
|
||||
if(!state.exclusive && !state.exclusive_waiting_blocked)
|
||||
{
|
||||
++state.shared_count;
|
||||
return;
|
||||
}
|
||||
|
||||
shared_cond.wait(lock);
|
||||
}
|
||||
}
|
||||
|
||||
bool try_lock_shareable()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
|
||||
if(state.exclusive || state.exclusive_waiting_blocked)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
++state.shared_count;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool timed_lock_shareable(xtime const& timeout)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
|
||||
while(true)
|
||||
{
|
||||
if(!state.exclusive && !state.exclusive_waiting_blocked)
|
||||
{
|
||||
++state.shared_count;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!shared_cond.timed_wait(lock,timeout))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void unlock_shareable()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
bool const last_reader=!--state.shared_count;
|
||||
|
||||
if(last_reader)
|
||||
{
|
||||
if(state.upgradeable)
|
||||
{
|
||||
state.upgradeable=false;
|
||||
state.exclusive=true;
|
||||
upgradeable_cond.notify_one();
|
||||
}
|
||||
else
|
||||
{
|
||||
state.exclusive_waiting_blocked=false;
|
||||
}
|
||||
release_waiters();
|
||||
}
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
|
||||
while(true)
|
||||
{
|
||||
if(state.shared_count || state.exclusive)
|
||||
{
|
||||
state.exclusive_waiting_blocked=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.exclusive=true;
|
||||
return;
|
||||
}
|
||||
exclusive_cond.wait(lock);
|
||||
}
|
||||
}
|
||||
|
||||
bool timed_lock(xtime const& timeout)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
|
||||
while(true)
|
||||
{
|
||||
if(state.shared_count || state.exclusive)
|
||||
{
|
||||
state.exclusive_waiting_blocked=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.exclusive=true;
|
||||
return true;
|
||||
}
|
||||
if(!exclusive_cond.timed_wait(lock,timeout))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
|
||||
if(state.shared_count || state.exclusive)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.exclusive=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
state.exclusive=false;
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
}
|
||||
|
||||
void lock_upgradeable()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
while(true)
|
||||
{
|
||||
if(!state.exclusive && !state.exclusive_waiting_blocked && !state.upgradeable)
|
||||
{
|
||||
++state.shared_count;
|
||||
state.upgradeable=true;
|
||||
return;
|
||||
}
|
||||
|
||||
shared_cond.wait(lock);
|
||||
}
|
||||
}
|
||||
|
||||
bool timed_lock_upgradeable(xtime const& timeout)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
while(true)
|
||||
{
|
||||
if(!state.exclusive && !state.exclusive_waiting_blocked && !state.upgradeable)
|
||||
{
|
||||
++state.shared_count;
|
||||
state.upgradeable=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!shared_cond.timed_wait(lock,timeout))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool try_lock_upgradeable()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
if(state.exclusive || state.exclusive_waiting_blocked || state.upgradeable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
++state.shared_count;
|
||||
state.upgradeable=true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void unlock_upgradeable()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
state.upgradeable=false;
|
||||
bool const last_reader=!--state.shared_count;
|
||||
|
||||
if(last_reader)
|
||||
{
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
}
|
||||
}
|
||||
|
||||
void unlock_upgradeable_and_lock()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
--state.shared_count;
|
||||
while(true)
|
||||
{
|
||||
if(!state.shared_count)
|
||||
{
|
||||
state.upgradeable=false;
|
||||
state.exclusive=true;
|
||||
break;
|
||||
}
|
||||
upgradeable_cond.wait(lock);
|
||||
}
|
||||
}
|
||||
|
||||
void unlock_and_lock_upgradeable()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
state.exclusive=false;
|
||||
state.upgradeable=true;
|
||||
++state.shared_count;
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
}
|
||||
|
||||
void unlock_and_lock_shareable()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
state.exclusive=false;
|
||||
++state.shared_count;
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
}
|
||||
|
||||
void unlock_upgradeable_and_lock_shareable()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
state.upgradeable=false;
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
}
|
||||
|
||||
class scoped_read_lock
|
||||
{
|
||||
read_write_mutex& m;
|
||||
public:
|
||||
scoped_read_lock(read_write_mutex& m_):
|
||||
m(m_)
|
||||
{
|
||||
m.lock_shareable();
|
||||
}
|
||||
~scoped_read_lock()
|
||||
{
|
||||
m.unlock_shareable();
|
||||
}
|
||||
};
|
||||
|
||||
class scoped_write_lock
|
||||
{
|
||||
read_write_mutex& m;
|
||||
bool locked;
|
||||
|
||||
public:
|
||||
scoped_write_lock(read_write_mutex& m_):
|
||||
m(m_),locked(false)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
void lock()
|
||||
{
|
||||
m.lock();
|
||||
locked=true;
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
m.unlock();
|
||||
locked=false;
|
||||
}
|
||||
~scoped_write_lock()
|
||||
{
|
||||
if(locked)
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class scoped_upgradeable_lock
|
||||
{
|
||||
read_write_mutex& m;
|
||||
bool locked;
|
||||
bool upgraded;
|
||||
|
||||
public:
|
||||
scoped_upgradeable_lock(read_write_mutex& m_):
|
||||
m(m_),
|
||||
locked(false),upgraded(false)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
void lock()
|
||||
{
|
||||
m.lock_upgradeable();
|
||||
locked=true;
|
||||
}
|
||||
void upgrade()
|
||||
{
|
||||
m.unlock_upgradeable_and_lock();
|
||||
upgraded=true;
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if(upgraded)
|
||||
{
|
||||
m.unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
m.unlock_upgradeable();
|
||||
}
|
||||
}
|
||||
~scoped_upgradeable_lock()
|
||||
{
|
||||
if(locked)
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
136
include/boost/thread/pthread/recursive_mutex.hpp
Normal file
136
include/boost/thread/pthread/recursive_mutex.hpp
Normal file
@@ -0,0 +1,136 @@
|
||||
// Copyright (C) 2001-2003 William E. Kempf
|
||||
// Copyright (C) 2006 Roland Schwarz
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_RECURSIVE_MUTEX_RS06092302_HPP
|
||||
#define BOOST_RECURSIVE_MUTEX_RS06092302_HPP
|
||||
|
||||
#include <boost/thread/pthread/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/pthread/lock.hpp>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct xtime;
|
||||
|
||||
// disable warnings about non dll import
|
||||
// see: http://www.boost.org/more/separate_compilation.html#dlls
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4251 4231 4660 4275)
|
||||
#endif
|
||||
|
||||
class BOOST_THREAD_DECL recursive_mutex
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::lock_ops<recursive_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_lock<recursive_mutex> scoped_lock;
|
||||
|
||||
recursive_mutex();
|
||||
~recursive_mutex();
|
||||
|
||||
private:
|
||||
struct cv_state
|
||||
{
|
||||
long count;
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
void do_lock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
pthread_mutex_t m_mutex;
|
||||
unsigned m_count;
|
||||
#if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
|
||||
pthread_cond_t m_unlocked;
|
||||
pthread_t m_thread_id;
|
||||
bool m_valid_id;
|
||||
#endif
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL recursive_try_mutex
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::lock_ops<recursive_try_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_lock<recursive_try_mutex> scoped_lock;
|
||||
typedef detail::thread::scoped_try_lock<
|
||||
recursive_try_mutex> scoped_try_lock;
|
||||
|
||||
recursive_try_mutex();
|
||||
~recursive_try_mutex();
|
||||
|
||||
private:
|
||||
struct cv_state
|
||||
{
|
||||
long count;
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
pthread_mutex_t m_mutex;
|
||||
unsigned m_count;
|
||||
#if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
|
||||
pthread_cond_t m_unlocked;
|
||||
pthread_t m_thread_id;
|
||||
bool m_valid_id;
|
||||
#endif
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL recursive_timed_mutex
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::lock_ops<recursive_timed_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_lock<recursive_timed_mutex> scoped_lock;
|
||||
typedef detail::thread::scoped_try_lock<
|
||||
recursive_timed_mutex> scoped_try_lock;
|
||||
typedef detail::thread::scoped_timed_lock<
|
||||
recursive_timed_mutex> scoped_timed_lock;
|
||||
|
||||
recursive_timed_mutex();
|
||||
~recursive_timed_mutex();
|
||||
|
||||
private:
|
||||
struct cv_state
|
||||
{
|
||||
long count;
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
bool do_timedlock(const xtime& xt);
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
pthread_mutex_t m_mutex;
|
||||
pthread_cond_t m_unlocked;
|
||||
pthread_t m_thread_id;
|
||||
bool m_valid_id;
|
||||
unsigned m_count;
|
||||
};
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_RECURSIVE_MUTEX_RS06092302_HPP
|
||||
75
include/boost/thread/pthread/thread.hpp
Normal file
75
include/boost/thread/pthread/thread.hpp
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_THREAD_RS06040701_HPP
|
||||
#define BOOST_THREAD_RS06040701_HPP
|
||||
|
||||
#include <boost/thread/pthread/config.hpp>
|
||||
|
||||
#include <boost/thread/pthread/mutex.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <pthread.h>
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct xtime;
|
||||
|
||||
// disable warnings about non dll import
|
||||
// see: http://www.boost.org/more/separate_compilation.html#dlls
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4251 4231 4660 4275)
|
||||
#endif
|
||||
|
||||
class BOOST_THREAD_DECL thread : private noncopyable
|
||||
{
|
||||
public:
|
||||
thread();
|
||||
explicit thread(const function0<void>& threadfunc);
|
||||
~thread();
|
||||
|
||||
bool operator==(const thread& other) const;
|
||||
bool operator!=(const thread& other) const;
|
||||
|
||||
void join();
|
||||
|
||||
static void sleep(const xtime& xt);
|
||||
static void yield();
|
||||
|
||||
private:
|
||||
pthread_t m_thread;
|
||||
bool m_joinable;
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL thread_group : private noncopyable
|
||||
{
|
||||
public:
|
||||
thread_group();
|
||||
~thread_group();
|
||||
|
||||
thread* create_thread(const function0<void>& threadfunc);
|
||||
void add_thread(thread* thrd);
|
||||
void remove_thread(thread* thrd);
|
||||
void join_all();
|
||||
int size();
|
||||
|
||||
private:
|
||||
std::list<thread*> m_threads;
|
||||
mutex m_mutex;
|
||||
};
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_THREAD_RS06040701_HPP
|
||||
108
include/boost/thread/pthread/tss.hpp
Normal file
108
include/boost/thread/pthread/tss.hpp
Normal file
@@ -0,0 +1,108 @@
|
||||
// Copyright (C) 2001-2003 William E. Kempf
|
||||
// Copyright (C) 2006 Roland Schwarz
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_TSS_RS06092304_HPP
|
||||
#define BOOST_TSS_RS06092304_HPP
|
||||
|
||||
#include <boost/thread/pthread/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/thread/pthread/exceptions.hpp>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace boost {
|
||||
|
||||
// disable warnings about non dll import
|
||||
// see: http://www.boost.org/more/separate_compilation.html#dlls
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4251 4231 4660 4275)
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
class BOOST_THREAD_DECL tss : private noncopyable
|
||||
{
|
||||
public:
|
||||
tss(boost::function1<void, void*>* pcleanup) {
|
||||
if (pcleanup == 0) throw boost::thread_resource_error();
|
||||
try
|
||||
{
|
||||
init(pcleanup);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
delete pcleanup;
|
||||
throw boost::thread_resource_error();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct tss_adapter
|
||||
{
|
||||
template <typename F>
|
||||
tss_adapter(const F& cleanup) : m_cleanup(cleanup) { }
|
||||
void operator()(void* p) { m_cleanup(static_cast<T*>(p)); }
|
||||
boost::function1<void, T*> m_cleanup;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T>
|
||||
class thread_specific_ptr : private noncopyable
|
||||
{
|
||||
public:
|
||||
thread_specific_ptr()
|
||||
: m_tss(new boost::function1<void, void*>(
|
||||
boost::detail::tss_adapter<T>(
|
||||
&thread_specific_ptr<T>::cleanup)))
|
||||
{
|
||||
}
|
||||
thread_specific_ptr(void (*clean)(T*))
|
||||
: m_tss(new boost::function1<void, void*>(
|
||||
boost::detail::tss_adapter<T>(clean)))
|
||||
{
|
||||
}
|
||||
~thread_specific_ptr() { reset(); }
|
||||
|
||||
T* get() const { return static_cast<T*>(m_tss.get()); }
|
||||
T* operator->() const { return get(); }
|
||||
T& operator*() const { return *get(); }
|
||||
T* release() { T* temp = get(); if (temp) m_tss.set(0); return temp; }
|
||||
void reset(T* p=0)
|
||||
{
|
||||
T* cur = get();
|
||||
if (cur == p) return;
|
||||
m_tss.set(p);
|
||||
if (cur) m_tss.cleanup(cur);
|
||||
}
|
||||
|
||||
private:
|
||||
static void cleanup(T* p) { delete p; }
|
||||
detail::tss m_tss;
|
||||
};
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif //BOOST_TSS_RS06092304_HPP
|
||||
56
include/boost/thread/pthread/xtime.hpp
Normal file
56
include/boost/thread/pthread/xtime.hpp
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_THREAD_RS06040711_HPP
|
||||
#define BOOST_THREAD_RS06040711_HPP
|
||||
|
||||
#include <boost/thread/pthread/config.hpp>
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
enum xtime_clock_types
|
||||
{
|
||||
TIME_UTC=1
|
||||
// TIME_TAI,
|
||||
// TIME_MONOTONIC,
|
||||
// TIME_PROCESS,
|
||||
// TIME_THREAD,
|
||||
// TIME_LOCAL,
|
||||
// TIME_SYNC,
|
||||
// TIME_RESOLUTION
|
||||
};
|
||||
|
||||
struct xtime
|
||||
{
|
||||
#if defined(BOOST_NO_INT64_T)
|
||||
typedef int_fast32_t xtime_sec_t; //INT_FAST32_MIN <= sec <= INT_FAST32_MAX
|
||||
#else
|
||||
typedef int_fast64_t xtime_sec_t; //INT_FAST64_MIN <= sec <= INT_FAST64_MAX
|
||||
#endif
|
||||
|
||||
typedef int_fast32_t xtime_nsec_t; //0 <= xtime.nsec < NANOSECONDS_PER_SECOND
|
||||
|
||||
xtime_sec_t sec;
|
||||
xtime_nsec_t nsec;
|
||||
};
|
||||
|
||||
int BOOST_THREAD_DECL xtime_get(struct xtime* xtp, int clock_type);
|
||||
|
||||
inline int xtime_cmp(const xtime& xt1, const xtime& xt2)
|
||||
{
|
||||
if (xt1.sec == xt2.sec)
|
||||
return (int)(xt1.nsec - xt2.nsec);
|
||||
else
|
||||
return (xt1.sec > xt2.sec) ? 1 : -1;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif //BOOST_THREAD_RS06040711_HPP
|
||||
@@ -1,271 +1,13 @@
|
||||
// Copyright (C) 2002-2003
|
||||
// David Moore, William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. David Moore makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
#ifndef BOOST_THREAD_READ_WRITE_MUTEX_HPP
|
||||
#define BOOST_THREAD_READ_WRITE_MUTEX_HPP
|
||||
|
||||
// A Boost::threads implementation of a synchronization
|
||||
// primitive which can allow multiple readers or a single
|
||||
// writer to have access to a shared resource.
|
||||
|
||||
#ifndef BOOST_READ_WRITE_MUTEX_JDM030602_HPP
|
||||
#define BOOST_READ_WRITE_MUTEX_JDM030602_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/detail/lock.hpp>
|
||||
#include <boost/thread/detail/read_write_lock.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace read_write_scheduling_policy {
|
||||
enum read_write_scheduling_policy_enum
|
||||
{
|
||||
writer_priority, //Prefer writers; can starve readers
|
||||
reader_priority, //Prefer readers; can starve writers
|
||||
alternating_many_reads, //Alternate readers and writers; before a writer, release all queued readers
|
||||
alternating_single_read //Alternate readers and writers; before a writer, release only on queued reader
|
||||
};
|
||||
} // namespace read_write_scheduling_policy
|
||||
|
||||
namespace detail {
|
||||
|
||||
namespace thread {
|
||||
|
||||
// Shared implementation construct for explicit Scheduling Policies
|
||||
// This implementation is susceptible to self-deadlock, though....
|
||||
template<typename Mutex>
|
||||
struct read_write_mutex_impl
|
||||
{
|
||||
typedef Mutex mutex_type;
|
||||
typedef detail::thread::scoped_lock<Mutex> scoped_lock;
|
||||
typedef detail::thread::scoped_try_lock<Mutex> scoped_try_lock;
|
||||
typedef detail::thread::scoped_timed_lock<Mutex> scoped_timed_lock;
|
||||
|
||||
read_write_mutex_impl(read_write_scheduling_policy::read_write_scheduling_policy_enum sp)
|
||||
: m_num_waiting_writers(0),
|
||||
m_num_waiting_readers(0),
|
||||
m_num_readers_to_wake(0),
|
||||
m_state_waiting_promotion(false),
|
||||
m_state(0),
|
||||
m_sp(sp),
|
||||
m_readers_next(true) { }
|
||||
|
||||
Mutex m_prot;
|
||||
boost::condition m_waiting_writers;
|
||||
boost::condition m_waiting_readers;
|
||||
int m_num_waiting_writers;
|
||||
int m_num_waiting_readers;
|
||||
int m_num_readers_to_wake;
|
||||
boost::condition m_waiting_promotion;
|
||||
bool m_state_waiting_promotion;
|
||||
int m_state; // -1 = excl locked
|
||||
// 0 = unlocked
|
||||
// 1-> INT_MAX - shared locked
|
||||
const read_write_scheduling_policy::read_write_scheduling_policy_enum m_sp;
|
||||
bool m_readers_next;
|
||||
|
||||
void do_read_lock();
|
||||
void do_write_lock();
|
||||
void do_write_unlock();
|
||||
void do_read_unlock();
|
||||
bool do_try_write_lock();
|
||||
bool do_try_read_lock();
|
||||
bool do_timed_write_lock(const xtime &xt);
|
||||
bool do_timed_read_lock(const xtime &xt);
|
||||
|
||||
void do_demote_to_read_lock();
|
||||
bool do_try_demote_to_read_lock();
|
||||
bool do_timed_demote_to_read_lock(const xtime &xt);
|
||||
|
||||
void do_promote_to_write_lock();
|
||||
bool do_try_promote_to_write_lock();
|
||||
bool do_timed_promote_to_write_lock(const xtime &xt);
|
||||
|
||||
bool locked();
|
||||
read_write_lock_state::read_write_lock_state_enum state();
|
||||
|
||||
private:
|
||||
|
||||
void do_unlock_scheduling_impl();
|
||||
void do_demote_scheduling_impl();
|
||||
void do_scheduling_impl();
|
||||
bool do_demote_to_read_lock_impl();
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace thread
|
||||
|
||||
class BOOST_THREAD_DECL read_write_mutex : private noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
read_write_mutex(read_write_scheduling_policy::read_write_scheduling_policy_enum sp) : m_impl(sp) { }
|
||||
~read_write_mutex() { }
|
||||
|
||||
read_write_scheduling_policy::read_write_scheduling_policy_enum policy() const { return m_impl.m_sp; }
|
||||
|
||||
friend class detail::thread::read_write_lock_ops<read_write_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_read_write_lock<
|
||||
read_write_mutex> scoped_read_write_lock;
|
||||
|
||||
typedef detail::thread::scoped_read_lock<
|
||||
read_write_mutex> scoped_read_lock;
|
||||
|
||||
typedef detail::thread::scoped_write_lock<
|
||||
read_write_mutex> scoped_write_lock;
|
||||
|
||||
private:
|
||||
|
||||
// Operations that will eventually be done only
|
||||
// via lock types
|
||||
void do_write_lock();
|
||||
void do_read_lock();
|
||||
void do_write_unlock();
|
||||
void do_read_unlock();
|
||||
|
||||
void do_demote_to_read_lock();
|
||||
|
||||
void do_promote_to_write_lock();
|
||||
|
||||
bool locked();
|
||||
read_write_lock_state::read_write_lock_state_enum state();
|
||||
|
||||
detail::thread::read_write_mutex_impl<mutex> m_impl;
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL try_read_write_mutex : private noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
try_read_write_mutex(read_write_scheduling_policy::read_write_scheduling_policy_enum sp) : m_impl(sp) { }
|
||||
~try_read_write_mutex() { }
|
||||
|
||||
read_write_scheduling_policy::read_write_scheduling_policy_enum policy() const { return m_impl.m_sp; }
|
||||
|
||||
friend class detail::thread::read_write_lock_ops<try_read_write_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_read_write_lock<
|
||||
try_read_write_mutex> scoped_read_write_lock;
|
||||
typedef detail::thread::scoped_try_read_write_lock<
|
||||
try_read_write_mutex> scoped_try_read_write_lock;
|
||||
|
||||
typedef detail::thread::scoped_read_lock<
|
||||
try_read_write_mutex> scoped_read_lock;
|
||||
typedef detail::thread::scoped_try_read_lock<
|
||||
try_read_write_mutex> scoped_try_read_lock;
|
||||
|
||||
typedef detail::thread::scoped_write_lock<
|
||||
try_read_write_mutex> scoped_write_lock;
|
||||
typedef detail::thread::scoped_try_write_lock<
|
||||
try_read_write_mutex> scoped_try_write_lock;
|
||||
|
||||
private:
|
||||
|
||||
// Operations that will eventually be done only
|
||||
// via lock types
|
||||
void do_write_lock();
|
||||
void do_read_lock();
|
||||
void do_write_unlock();
|
||||
void do_read_unlock();
|
||||
bool do_try_write_lock();
|
||||
bool do_try_read_lock();
|
||||
// (C) Copyright 2006 Anthony Williams
|
||||
// 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)
|
||||
|
||||
|
||||
void do_demote_to_read_lock();
|
||||
bool do_try_demote_to_read_lock();
|
||||
|
||||
void do_promote_to_write_lock();
|
||||
bool do_try_promote_to_write_lock();
|
||||
|
||||
bool locked();
|
||||
read_write_lock_state::read_write_lock_state_enum state();
|
||||
|
||||
detail::thread::read_write_mutex_impl<try_mutex> m_impl;
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL timed_read_write_mutex : private noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
timed_read_write_mutex(read_write_scheduling_policy::read_write_scheduling_policy_enum sp) : m_impl(sp) { }
|
||||
~timed_read_write_mutex() { }
|
||||
|
||||
read_write_scheduling_policy::read_write_scheduling_policy_enum policy() const { return m_impl.m_sp; }
|
||||
|
||||
friend class detail::thread::read_write_lock_ops<timed_read_write_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_read_write_lock<
|
||||
timed_read_write_mutex> scoped_read_write_lock;
|
||||
typedef detail::thread::scoped_try_read_write_lock<
|
||||
timed_read_write_mutex> scoped_try_read_write_lock;
|
||||
typedef detail::thread::scoped_timed_read_write_lock<
|
||||
timed_read_write_mutex> scoped_timed_read_write_lock;
|
||||
|
||||
typedef detail::thread::scoped_read_lock<
|
||||
timed_read_write_mutex> scoped_read_lock;
|
||||
typedef detail::thread::scoped_try_read_lock<
|
||||
timed_read_write_mutex> scoped_try_read_lock;
|
||||
typedef detail::thread::scoped_timed_read_lock<
|
||||
timed_read_write_mutex> scoped_timed_read_lock;
|
||||
|
||||
typedef detail::thread::scoped_write_lock<
|
||||
timed_read_write_mutex> scoped_write_lock;
|
||||
typedef detail::thread::scoped_try_write_lock<
|
||||
timed_read_write_mutex> scoped_try_write_lock;
|
||||
typedef detail::thread::scoped_timed_write_lock<
|
||||
timed_read_write_mutex> scoped_timed_write_lock;
|
||||
|
||||
private:
|
||||
|
||||
// Operations that will eventually be done only
|
||||
// via lock types
|
||||
void do_write_lock();
|
||||
void do_read_lock();
|
||||
void do_write_unlock();
|
||||
void do_read_unlock();
|
||||
bool do_try_write_lock();
|
||||
bool do_try_read_lock();
|
||||
bool do_timed_write_lock(const xtime &xt);
|
||||
bool do_timed_read_lock(const xtime &xt);
|
||||
|
||||
void do_demote_to_read_lock();
|
||||
bool do_try_demote_to_read_lock();
|
||||
bool do_timed_demote_to_read_lock(const xtime &xt);
|
||||
|
||||
void do_promote_to_write_lock();
|
||||
bool do_try_promote_to_write_lock();
|
||||
bool do_timed_promote_to_write_lock(const xtime &xt);
|
||||
|
||||
bool locked();
|
||||
read_write_lock_state::read_write_lock_state_enum state();
|
||||
|
||||
detail::thread::read_write_mutex_impl<timed_mutex> m_impl;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
#include <boost/thread/detail/platform.hpp>
|
||||
#include BOOST_THREAD_PLATFORM(read_write_mutex.hpp)
|
||||
|
||||
#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,186 +1,16 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
#ifndef BOOST_THREAD_RECURSIVE_MUTEX_HPP
|
||||
#define BOOST_THREAD_RECURSIVE_MUTEX_HPP
|
||||
|
||||
// recursive_mutex.hpp
|
||||
//
|
||||
// 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.
|
||||
// (C) Copyright 2006 Anthony Williams
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_RECURSIVE_MUTEX_WEK070601_HPP
|
||||
#define BOOST_RECURSIVE_MUTEX_WEK070601_HPP
|
||||
#include <boost/thread/detail/platform.hpp>
|
||||
#include BOOST_THREAD_PLATFORM(recursive_mutex.hpp)
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/detail/lock.hpp>
|
||||
#include <boost/thread/detail/named.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_HAS_MPTASKS)
|
||||
# include "scoped_critical_region.hpp"
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct xtime;
|
||||
|
||||
class BOOST_THREAD_DECL recursive_mutex
|
||||
: private noncopyable
|
||||
, public boost::detail::named_object
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::lock_ops<recursive_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_lock<recursive_mutex> scoped_lock;
|
||||
|
||||
recursive_mutex(const char* name=0);
|
||||
~recursive_mutex();
|
||||
|
||||
private:
|
||||
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
typedef std::size_t cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
long count;
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
void* m_mutex;
|
||||
bool m_critical_section;
|
||||
unsigned long m_count;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
unsigned m_count;
|
||||
# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
|
||||
pthread_cond_t m_unlocked;
|
||||
pthread_t m_thread_id;
|
||||
bool m_valid_id;
|
||||
# endif
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
threads::mac::detail::scoped_critical_region m_mutex;
|
||||
threads::mac::detail::scoped_critical_region m_mutex_mutex;
|
||||
std::size_t m_count;
|
||||
#endif
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL recursive_try_mutex
|
||||
: private noncopyable
|
||||
, public boost::detail::named_object
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::lock_ops<recursive_try_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_lock<recursive_try_mutex> scoped_lock;
|
||||
typedef detail::thread::scoped_try_lock<
|
||||
recursive_try_mutex> scoped_try_lock;
|
||||
|
||||
recursive_try_mutex(const char* name=0);
|
||||
~recursive_try_mutex();
|
||||
|
||||
private:
|
||||
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
typedef std::size_t cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
long count;
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
void* m_mutex;
|
||||
bool m_critical_section;
|
||||
unsigned long m_count;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
unsigned m_count;
|
||||
# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
|
||||
pthread_cond_t m_unlocked;
|
||||
pthread_t m_thread_id;
|
||||
bool m_valid_id;
|
||||
# endif
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
threads::mac::detail::scoped_critical_region m_mutex;
|
||||
threads::mac::detail::scoped_critical_region m_mutex_mutex;
|
||||
std::size_t m_count;
|
||||
#endif
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL recursive_timed_mutex
|
||||
: private noncopyable
|
||||
, public boost::detail::named_object
|
||||
{
|
||||
public:
|
||||
friend class detail::thread::lock_ops<recursive_timed_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_lock<recursive_timed_mutex> scoped_lock;
|
||||
typedef detail::thread::scoped_try_lock<
|
||||
recursive_timed_mutex> scoped_try_lock;
|
||||
typedef detail::thread::scoped_timed_lock<
|
||||
recursive_timed_mutex> scoped_timed_lock;
|
||||
|
||||
recursive_timed_mutex(const char* name=0);
|
||||
~recursive_timed_mutex();
|
||||
|
||||
private:
|
||||
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
|
||||
typedef std::size_t cv_state;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
struct cv_state
|
||||
{
|
||||
long count;
|
||||
pthread_mutex_t* pmutex;
|
||||
};
|
||||
#endif
|
||||
void do_lock();
|
||||
bool do_trylock();
|
||||
bool do_timedlock(const xtime& xt);
|
||||
void do_unlock();
|
||||
void do_lock(cv_state& state);
|
||||
void do_unlock(cv_state& state);
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
void* m_mutex;
|
||||
unsigned long m_count;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_mutex_t m_mutex;
|
||||
pthread_cond_t m_unlocked;
|
||||
pthread_t m_thread_id;
|
||||
bool m_valid_id;
|
||||
unsigned m_count;
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
threads::mac::detail::scoped_critical_region m_mutex;
|
||||
threads::mac::detail::scoped_critical_region m_mutex_mutex;
|
||||
std::size_t m_count;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_RECURSIVE_MUTEX_WEK070601_HPP
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 1 Jun 01 WEKEMPF Modified to use xtime for time outs. Factored out
|
||||
// to three classes, mutex, try_mutex and timed_mutex.
|
||||
// 11 Jun 01 WEKEMPF Modified to use PTHREAD_MUTEX_RECURSIVE if available.
|
||||
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
|
||||
@@ -1,58 +0,0 @@
|
||||
// Copyright (C) 2002-2003
|
||||
// William E. Kempf, David Moore
|
||||
//
|
||||
// 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_MUTEX_JDM062402_HPP
|
||||
#define BOOST_MUTEX_JDM062402_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/function.hpp>
|
||||
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/thread/detail/named.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
|
||||
class shared_memory : public boost::detail::named_object
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
write=0x1,
|
||||
create=0x2,
|
||||
exclusive=0x4,
|
||||
};
|
||||
|
||||
shared_memory(const char *name, std::size_t len, int flags);
|
||||
shared_memory(const char *name, std::size_t len, int flags,
|
||||
const boost::function1<void,void *>& initfunc);
|
||||
~shared_memory();
|
||||
|
||||
void* get() const { return m_ptr; }
|
||||
|
||||
private:
|
||||
void init(std::size_t len, int flags,
|
||||
const boost::function1<void, void*>* initfunc);
|
||||
|
||||
void *m_ptr; // Pointer to shared memory block
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
void* m_hmap;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
std::size_t m_len;
|
||||
int m_hmap;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
@@ -1,193 +1,16 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// 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 work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_THREAD_WEK070601_HPP
|
||||
#define BOOST_THREAD_WEK070601_HPP
|
||||
#ifndef BOOST_THREAD_RS06032802_HPP
|
||||
#define BOOST_THREAD_RS06032802_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/platform.hpp>
|
||||
#include BOOST_THREAD_PLATFORM(thread.hpp)
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#endif // BOOST_THREAD_RS06032802_HPP
|
||||
|
||||
#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 BOOST_THREAD_DECL thread_cancel
|
||||
{
|
||||
public:
|
||||
thread_cancel();
|
||||
~thread_cancel();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL cancellation_guard
|
||||
{
|
||||
public:
|
||||
cancellation_guard();
|
||||
~cancellation_guard();
|
||||
|
||||
private:
|
||||
void* m_handle;
|
||||
};
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
|
||||
struct sched_param
|
||||
{
|
||||
int priority;
|
||||
};
|
||||
|
||||
enum { sched_fifo, sched_round_robin, sched_other };
|
||||
enum { scope_process, scope_system };
|
||||
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
|
||||
using ::sched_param;
|
||||
|
||||
enum
|
||||
{
|
||||
sched_fifo = SCHED_FIFO,
|
||||
sched_round_robin = SCHED_RR,
|
||||
sched_other = SCHED_OTHER
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
scope_process = PTHREAD_SCOPE_PROCESS,
|
||||
scope_system = PTHREAD_SCOPE_SYSTEM
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
class BOOST_THREAD_DECL thread
|
||||
{
|
||||
public:
|
||||
class BOOST_THREAD_DECL attributes
|
||||
{
|
||||
public:
|
||||
attributes();
|
||||
~attributes();
|
||||
|
||||
attributes& set_stack_size(size_t size);
|
||||
size_t get_stack_size() const;
|
||||
|
||||
attributes& set_stack_address(void* addr);
|
||||
void* get_stack_address() const;
|
||||
|
||||
attributes& inherit_scheduling(bool inherit);
|
||||
bool inherit_scheduling() const;
|
||||
attributes& set_schedule(int policy, const sched_param& param);
|
||||
void get_schedule(int& policy, sched_param& param);
|
||||
attributes& scope(int scope);
|
||||
int scope() const;
|
||||
|
||||
private:
|
||||
friend class thread;
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
size_t m_stacksize;
|
||||
bool m_schedinherit;
|
||||
sched_param m_schedparam;
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
pthread_attr_t m_attr;
|
||||
#endif
|
||||
};
|
||||
|
||||
thread();
|
||||
explicit thread(const function0<void>& threadfunc,
|
||||
const attributes& attr=attributes());
|
||||
thread(const thread& other);
|
||||
~thread();
|
||||
|
||||
thread& operator=(const thread& other);
|
||||
|
||||
bool operator==(const thread& other) const;
|
||||
bool operator!=(const thread& other) const;
|
||||
bool operator<(const thread& other) const;
|
||||
|
||||
void join();
|
||||
bool timed_join(const xtime& xt);
|
||||
void cancel();
|
||||
bool cancelled() const;
|
||||
|
||||
void set_scheduling_parameter(int policy, const sched_param& param);
|
||||
void get_scheduling_parameter(int& policy, sched_param& param) const;
|
||||
|
||||
static int max_priority(int policy);
|
||||
static int min_priority(int policy);
|
||||
|
||||
static void test_cancel();
|
||||
static void sleep(const xtime& xt);
|
||||
static void yield();
|
||||
|
||||
static const int stack_min;
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
typedef unsigned int id_type;
|
||||
#else
|
||||
typedef const void* id_type;
|
||||
#endif
|
||||
|
||||
id_type id() const;
|
||||
|
||||
private:
|
||||
void* m_handle;
|
||||
};
|
||||
|
||||
template <typename charT, typename Traits>
|
||||
std::basic_ostream<charT, Traits>& operator<<(
|
||||
std::basic_ostream<charT, Traits>& os, const thread& thrd)
|
||||
{
|
||||
if (!os.good()) return os;
|
||||
|
||||
typename std::basic_ostream<charT, Traits>::sentry opfx(os);
|
||||
|
||||
if (opfx)
|
||||
os << thrd.id();
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
class BOOST_THREAD_DECL thread_group : private noncopyable
|
||||
{
|
||||
public:
|
||||
thread_group();
|
||||
~thread_group();
|
||||
|
||||
thread create_thread(const function0<void>& threadfunc);
|
||||
void add_thread(thread thrd);
|
||||
void remove_thread(thread thrd);
|
||||
// thread* thread_group::find(thread& thrd);
|
||||
void join_all();
|
||||
|
||||
private:
|
||||
std::list<thread> m_threads;
|
||||
mutex m_mutex;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_THREAD_WEK070601_HPP
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 1 Jun 01 WEKEMPF Added boost::thread initial implementation.
|
||||
// 3 Jul 01 WEKEMPF Redesigned boost::thread to be noncopyable.
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
// Copyright (C) 2002-2003
|
||||
// David Moore, William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. 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.
|
||||
|
||||
// Derived loosely from work queue manager in "Programming POSIX Threads"
|
||||
// by David Butenhof.
|
||||
|
||||
#ifndef BOOST_THREAD_POOL_JDM031802_HPP
|
||||
#define BOOST_THREAD_POOL_JDM031802_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
class BOOST_THREAD_DECL thread_pool
|
||||
{
|
||||
public:
|
||||
thread_pool(int max_threads=std::numeric_limits<int>::max(),
|
||||
int min_threads=0, int timeout_secs=5, int timeout_nsecs=0);
|
||||
~thread_pool();
|
||||
|
||||
void add(const boost::function0<void> &job);
|
||||
void join();
|
||||
void cancel();
|
||||
void detach();
|
||||
|
||||
private:
|
||||
class impl;
|
||||
impl* m_pimpl;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
@@ -1,121 +1,16 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// 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 work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_TSS_WEK070601_HPP
|
||||
#define BOOST_TSS_WEK070601_HPP
|
||||
#ifndef BOOST_TSS_RS06092303_HPP
|
||||
#define BOOST_TSS_RS06092303_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/platform.hpp>
|
||||
#include BOOST_THREAD_PLATFORM(tss.hpp)
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#endif // BOOST_TSS_RS06092301_HPP
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
# include <Multiprocessing.h>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class BOOST_THREAD_DECL tss : private noncopyable
|
||||
{
|
||||
public:
|
||||
tss(boost::function1<void, void*>* pcleanup) {
|
||||
if (pcleanup == 0) throw boost::thread_resource_error();
|
||||
try
|
||||
{
|
||||
init(pcleanup);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
delete pcleanup;
|
||||
throw boost::thread_resource_error();
|
||||
}
|
||||
}
|
||||
|
||||
void* get() const;
|
||||
void set(void* value);
|
||||
void cleanup(void* p);
|
||||
|
||||
private:
|
||||
unsigned int m_slot; //This is a "pseudo-slot", not a native slot
|
||||
|
||||
void init(boost::function1<void, void*>* pcleanup);
|
||||
};
|
||||
|
||||
#if defined(BOOST_HAS_MPTASKS)
|
||||
void thread_cleanup();
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
struct tss_adapter
|
||||
{
|
||||
template <typename F>
|
||||
tss_adapter(const F& cleanup) : m_cleanup(cleanup) { }
|
||||
void operator()(void* p) { m_cleanup(static_cast<T*>(p)); }
|
||||
boost::function1<void, T*> m_cleanup;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T>
|
||||
class thread_specific_ptr : private noncopyable
|
||||
{
|
||||
public:
|
||||
thread_specific_ptr()
|
||||
: m_tss(new boost::function1<void, void*>(
|
||||
boost::detail::tss_adapter<T>(
|
||||
&thread_specific_ptr<T>::cleanup)))
|
||||
{
|
||||
}
|
||||
thread_specific_ptr(void (*clean)(T*))
|
||||
: m_tss(new boost::function1<void, void*>(
|
||||
boost::detail::tss_adapter<T>(clean)))
|
||||
{
|
||||
}
|
||||
~thread_specific_ptr() { reset(); }
|
||||
|
||||
T* get() const { return static_cast<T*>(m_tss.get()); }
|
||||
T* operator->() const { return get(); }
|
||||
T& operator*() const { return *get(); }
|
||||
T* release() { T* temp = get(); if (temp) m_tss.set(0); return temp; }
|
||||
void reset(T* p=0)
|
||||
{
|
||||
T* cur = get();
|
||||
if (cur == p) return;
|
||||
m_tss.set(p);
|
||||
if (cur) m_tss.cleanup(cur);
|
||||
}
|
||||
|
||||
private:
|
||||
static void cleanup(T* p) { delete p; }
|
||||
detail::tss m_tss;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif //BOOST_TSS_WEK070601_HPP
|
||||
|
||||
// Change Log:
|
||||
// 6 Jun 01
|
||||
// WEKEMPF Initial version.
|
||||
// 30 May 02 WEKEMPF
|
||||
// Added interface to set specific cleanup handlers.
|
||||
// Removed TLS slot limits from most implementations.
|
||||
// 22 Mar 04 GlassfordM for WEKEMPF
|
||||
// Fixed: thread_specific_ptr::reset() doesn't check error returned
|
||||
// by tss::set(); tss::set() now throws if it fails.
|
||||
// Fixed: calling thread_specific_ptr::reset() or
|
||||
// thread_specific_ptr::release() causes double-delete: once on
|
||||
// reset()/release() and once on ~thread_specific_ptr().
|
||||
140
include/boost/thread/win32/basic_checked_mutex.hpp
Normal file
140
include/boost/thread/win32/basic_checked_mutex.hpp
Normal file
@@ -0,0 +1,140 @@
|
||||
#ifndef BOOST_BASIC_CHECKED_MUTEX_WIN32_HPP
|
||||
#define BOOST_BASIC_CHECKED_MUTEX_WIN32_HPP
|
||||
|
||||
// basic_checked_mutex_win32.hpp
|
||||
//
|
||||
// (C) Copyright 2006 Anthony Williams
|
||||
//
|
||||
// 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/detail/interlocked.hpp>
|
||||
#include <boost/thread/win32/thread_primitives.hpp>
|
||||
#include <boost/thread/win32/interlocked_read.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct basic_checked_mutex
|
||||
{
|
||||
long locking_thread;
|
||||
long active_count;
|
||||
void* semaphore;
|
||||
|
||||
BOOST_STATIC_CONSTANT(long,destroyed_mutex_marker=~0);
|
||||
|
||||
void initialize()
|
||||
{
|
||||
locking_thread=0;
|
||||
active_count=0;
|
||||
semaphore=0;
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
long const old_locking_thread=BOOST_INTERLOCKED_EXCHANGE(&locking_thread,destroyed_mutex_marker);
|
||||
BOOST_ASSERT(!old_locking_thread);
|
||||
void* const old_semaphore=BOOST_INTERLOCKED_EXCHANGE_POINTER(&semaphore,0);
|
||||
if(old_semaphore)
|
||||
{
|
||||
bool const close_handle_succeeded=BOOST_CLOSE_HANDLE(old_semaphore)!=0;
|
||||
BOOST_ASSERT(close_handle_succeeded);
|
||||
}
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
check_mutex_lock();
|
||||
bool const success=!BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,1,0);
|
||||
if(success)
|
||||
{
|
||||
set_locking_thread();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
check_mutex_lock();
|
||||
if(BOOST_INTERLOCKED_INCREMENT(&active_count)!=1)
|
||||
{
|
||||
bool const wait_succeeded=BOOST_WAIT_FOR_SINGLE_OBJECT(get_semaphore(),BOOST_INFINITE)==0;
|
||||
BOOST_ASSERT(wait_succeeded);
|
||||
}
|
||||
set_locking_thread();
|
||||
}
|
||||
|
||||
long get_active_count()
|
||||
{
|
||||
return ::boost::detail::interlocked_read(&active_count);
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
long const current_thread=BOOST_GET_CURRENT_THREAD_ID();
|
||||
long const old_locking_thread=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&locking_thread,0,current_thread);
|
||||
BOOST_ASSERT(old_locking_thread!=destroyed_mutex_marker);
|
||||
BOOST_ASSERT(old_locking_thread==current_thread);
|
||||
|
||||
if(BOOST_INTERLOCKED_DECREMENT(&active_count)!=0)
|
||||
{
|
||||
bool const release_succeeded=BOOST_RELEASE_SEMAPHORE(get_semaphore(),1,0)!=0;
|
||||
BOOST_ASSERT(release_succeeded);
|
||||
}
|
||||
}
|
||||
|
||||
bool locked()
|
||||
{
|
||||
return get_active_count()!=0;
|
||||
}
|
||||
|
||||
private:
|
||||
void check_mutex_lock()
|
||||
{
|
||||
long const current_thread=BOOST_GET_CURRENT_THREAD_ID();
|
||||
long const current_locking_thread=::boost::detail::interlocked_read(&locking_thread);
|
||||
BOOST_ASSERT(current_locking_thread!=current_thread);
|
||||
BOOST_ASSERT(current_locking_thread!=destroyed_mutex_marker);
|
||||
}
|
||||
|
||||
void set_locking_thread()
|
||||
{
|
||||
long const old_owner=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&locking_thread,BOOST_GET_CURRENT_THREAD_ID(),0);
|
||||
BOOST_ASSERT(old_owner==0);
|
||||
}
|
||||
|
||||
void* get_semaphore()
|
||||
{
|
||||
void* current_semaphore=::boost::detail::interlocked_read(&semaphore);
|
||||
|
||||
if(!current_semaphore)
|
||||
{
|
||||
void* const new_semaphore=BOOST_CREATE_SEMAPHORE(0,0,1,0);
|
||||
BOOST_ASSERT(new_semaphore);
|
||||
void* const old_semaphore=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&semaphore,new_semaphore,0);
|
||||
if(old_semaphore!=0)
|
||||
{
|
||||
bool const close_succeeded=BOOST_CLOSE_HANDLE(new_semaphore)!=0;
|
||||
BOOST_ASSERT(close_succeeded);
|
||||
return old_semaphore;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new_semaphore;
|
||||
}
|
||||
}
|
||||
return current_semaphore;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#define BOOST_BASIC_CHECKED_MUTEX_INITIALIZER {0}
|
||||
|
||||
#endif
|
||||
123
include/boost/thread/win32/basic_recursive_mutex.hpp
Normal file
123
include/boost/thread/win32/basic_recursive_mutex.hpp
Normal file
@@ -0,0 +1,123 @@
|
||||
#ifndef BOOST_BASIC_RECURSIVE_MUTEX_WIN32_HPP
|
||||
#define BOOST_BASIC_RECURSIVE_MUTEX_WIN32_HPP
|
||||
|
||||
// basic_recursive_mutex.hpp
|
||||
//
|
||||
// (C) Copyright 2006 Anthony Williams
|
||||
//
|
||||
// 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/detail/interlocked.hpp>
|
||||
#include <boost/thread/win32/thread_primitives.hpp>
|
||||
#include <boost/thread/win32/interlocked_read.hpp>
|
||||
#include <boost/thread/win32/basic_timed_mutex.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename underlying_mutex_type>
|
||||
struct basic_recursive_mutex_impl
|
||||
{
|
||||
long recursion_count;
|
||||
long locking_thread_id;
|
||||
underlying_mutex_type mutex;
|
||||
|
||||
void initialize()
|
||||
{
|
||||
recursion_count=0;
|
||||
locking_thread_id=0;
|
||||
mutex.initialize();
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
mutex.destroy();
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
long const current_thread_id=win32::GetCurrentThreadId();
|
||||
return try_recursive_lock(current_thread_id) || try_basic_lock(current_thread_id);
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
long const current_thread_id=win32::GetCurrentThreadId();
|
||||
if(!try_recursive_lock(current_thread_id))
|
||||
{
|
||||
mutex.lock();
|
||||
BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
|
||||
recursion_count=1;
|
||||
}
|
||||
}
|
||||
bool timed_lock(::boost::xtime const& target)
|
||||
{
|
||||
long const current_thread_id=win32::GetCurrentThreadId();
|
||||
return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target);
|
||||
}
|
||||
long get_active_count()
|
||||
{
|
||||
return mutex.get_active_count();
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
if(!--recursion_count)
|
||||
{
|
||||
BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,0);
|
||||
mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
bool locked()
|
||||
{
|
||||
return mutex.locked();
|
||||
}
|
||||
|
||||
private:
|
||||
bool try_recursive_lock(long current_thread_id)
|
||||
{
|
||||
if(::boost::detail::interlocked_read(&locking_thread_id)==current_thread_id)
|
||||
{
|
||||
++recursion_count;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool try_basic_lock(long current_thread_id)
|
||||
{
|
||||
if(mutex.try_lock())
|
||||
{
|
||||
BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
|
||||
recursion_count=1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool try_timed_lock(long current_thread_id,::boost::xtime const& target)
|
||||
{
|
||||
if(mutex.timed_lock(target))
|
||||
{
|
||||
BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
|
||||
recursion_count=1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
typedef basic_recursive_mutex_impl<basic_timed_mutex> basic_recursive_mutex;
|
||||
typedef basic_recursive_mutex_impl<basic_timed_mutex> basic_recursive_timed_mutex;
|
||||
}
|
||||
}
|
||||
|
||||
#define BOOST_BASIC_RECURSIVE_MUTEX_INITIALIZER {0}
|
||||
|
||||
#endif
|
||||
158
include/boost/thread/win32/basic_timed_mutex.hpp
Normal file
158
include/boost/thread/win32/basic_timed_mutex.hpp
Normal file
@@ -0,0 +1,158 @@
|
||||
#ifndef BOOST_BASIC_TIMED_MUTEX_WIN32_HPP
|
||||
#define BOOST_BASIC_TIMED_MUTEX_WIN32_HPP
|
||||
|
||||
// basic_timed_mutex_win32.hpp
|
||||
//
|
||||
// (C) Copyright 2006 Anthony Williams
|
||||
//
|
||||
// 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/assert.hpp>
|
||||
#include <boost/detail/interlocked.hpp>
|
||||
#include <boost/thread/win32/thread_primitives.hpp>
|
||||
#include <boost/thread/win32/interlocked_read.hpp>
|
||||
#include <boost/thread/win32/xtime.hpp>
|
||||
#include <boost/thread/win32/xtime_utils.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct basic_timed_mutex
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(long,lock_flag_value=0x10000);
|
||||
long active_count;
|
||||
void* event;
|
||||
|
||||
void initialize()
|
||||
{
|
||||
active_count=0;
|
||||
event=0;
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
void* const old_event=BOOST_INTERLOCKED_EXCHANGE_POINTER(&event,0);
|
||||
if(old_event)
|
||||
{
|
||||
win32::CloseHandle(old_event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
long old_count=0;
|
||||
while(!(old_count&lock_flag_value))
|
||||
{
|
||||
long const current_count=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,(old_count+1)|lock_flag_value,old_count);
|
||||
if(current_count==old_count)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
old_count=current_count;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
bool const success=timed_lock(::boost::detail::get_xtime_sentinel());
|
||||
BOOST_ASSERT(success);
|
||||
}
|
||||
bool timed_lock(::boost::xtime const& target_time)
|
||||
{
|
||||
long old_count=0;
|
||||
while(true)
|
||||
{
|
||||
long const current_count=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,(old_count+1)|lock_flag_value,old_count);
|
||||
if(current_count==old_count)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_count=current_count;
|
||||
}
|
||||
|
||||
if(old_count&lock_flag_value)
|
||||
{
|
||||
bool lock_acquired=false;
|
||||
void* const sem=get_event();
|
||||
++old_count; // we're waiting, too
|
||||
do
|
||||
{
|
||||
old_count-=(lock_flag_value+1); // there will be one less active thread on this mutex when it gets unlocked
|
||||
if(win32::WaitForSingleObject(sem,::boost::detail::get_milliseconds_until_time(target_time))!=0)
|
||||
{
|
||||
BOOST_INTERLOCKED_DECREMENT(&active_count);
|
||||
return false;
|
||||
}
|
||||
do
|
||||
{
|
||||
long const current_count=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,old_count|lock_flag_value,old_count);
|
||||
if(current_count==old_count)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_count=current_count;
|
||||
}
|
||||
while(!(old_count&lock_flag_value));
|
||||
lock_acquired=!(old_count&lock_flag_value);
|
||||
}
|
||||
while(!lock_acquired);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
long get_active_count()
|
||||
{
|
||||
return ::boost::detail::interlocked_read(&active_count);
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
long const offset=lock_flag_value+1;
|
||||
long old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,-offset);
|
||||
|
||||
if(old_count>offset)
|
||||
{
|
||||
win32::SetEvent(get_event());
|
||||
}
|
||||
}
|
||||
|
||||
bool locked()
|
||||
{
|
||||
return get_active_count()>=lock_flag_value;
|
||||
}
|
||||
|
||||
private:
|
||||
void* get_event()
|
||||
{
|
||||
void* current_event=::boost::detail::interlocked_read(&event);
|
||||
|
||||
if(!current_event)
|
||||
{
|
||||
void* const new_event=win32::create_anonymous_event(win32::auto_reset_event,win32::event_initially_reset);
|
||||
void* const old_event=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&event,new_event,0);
|
||||
if(old_event!=0)
|
||||
{
|
||||
win32::CloseHandle(new_event);
|
||||
return old_event;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new_event;
|
||||
}
|
||||
}
|
||||
return current_event;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#define BOOST_BASIC_TIMED_MUTEX_INITIALIZER {0}
|
||||
|
||||
#endif
|
||||
229
include/boost/thread/win32/condition.hpp
Normal file
229
include/boost/thread/win32/condition.hpp
Normal file
@@ -0,0 +1,229 @@
|
||||
// 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)
|
||||
// (C) Copyright 2007 Anthony Williams
|
||||
#ifndef CONDITION_HPP
|
||||
#define CONDITION_HPP
|
||||
#include "boost/config.hpp"
|
||||
#include "boost/thread/mutex.hpp"
|
||||
#include "boost/thread/win32/thread_primitives.hpp"
|
||||
#include "boost/thread/win32/xtime.hpp"
|
||||
#include "boost/thread/win32/xtime_utils.hpp"
|
||||
#include <limits.h>
|
||||
#include "boost/assert.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template<typename lock_type>
|
||||
class basic_condition
|
||||
{
|
||||
boost::mutex internal_mutex;
|
||||
|
||||
struct list_entry
|
||||
{
|
||||
detail::win32::handle semaphore;
|
||||
long count;
|
||||
bool notified;
|
||||
};
|
||||
|
||||
BOOST_STATIC_CONSTANT(unsigned,generation_count=10);
|
||||
|
||||
list_entry generations[generation_count];
|
||||
detail::win32::handle wake_sem;
|
||||
|
||||
static bool no_waiters(list_entry const& entry)
|
||||
{
|
||||
return entry.count==0;
|
||||
}
|
||||
|
||||
void shift_generations_down()
|
||||
{
|
||||
if(std::remove_if(generations,generations+generation_count,no_waiters)==generations+generation_count)
|
||||
{
|
||||
broadcast_entry(generations[generation_count-1],false);
|
||||
}
|
||||
std::copy_backward(generations,generations+generation_count,generations+generation_count);
|
||||
generations[0].semaphore=0;
|
||||
generations[0].count=0;
|
||||
generations[0].notified=false;
|
||||
}
|
||||
|
||||
void broadcast_entry(list_entry& entry,bool wake)
|
||||
{
|
||||
if(wake)
|
||||
{
|
||||
detail::win32::ReleaseSemaphore(wake_sem,entry.count,NULL);
|
||||
}
|
||||
detail::win32::ReleaseSemaphore(entry.semaphore,entry.count,NULL);
|
||||
entry.count=0;
|
||||
dispose_entry(entry);
|
||||
}
|
||||
|
||||
|
||||
void dispose_entry(list_entry& entry)
|
||||
{
|
||||
BOOST_ASSERT(entry.count==0);
|
||||
if(entry.semaphore)
|
||||
{
|
||||
unsigned long const close_result=detail::win32::CloseHandle(entry.semaphore);
|
||||
BOOST_ASSERT(close_result);
|
||||
}
|
||||
entry.semaphore=0;
|
||||
entry.notified=false;
|
||||
}
|
||||
|
||||
detail::win32::handle duplicate_handle(detail::win32::handle source)
|
||||
{
|
||||
detail::win32::handle const current_process=detail::win32::GetCurrentProcess();
|
||||
|
||||
long const same_access_flag=2;
|
||||
detail::win32::handle new_handle=0;
|
||||
bool const success=detail::win32::DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
|
||||
BOOST_ASSERT(success);
|
||||
return new_handle;
|
||||
}
|
||||
|
||||
bool do_wait(lock_type& lock,::boost::xtime const& target_time)
|
||||
{
|
||||
detail::win32::handle local_wake_sem;
|
||||
detail::win32::handle sem;
|
||||
bool first_loop=true;
|
||||
bool woken=false;
|
||||
while(!woken)
|
||||
{
|
||||
{
|
||||
boost::mutex::scoped_lock internal_lock(internal_mutex);
|
||||
if(first_loop)
|
||||
{
|
||||
lock.unlock();
|
||||
if(!wake_sem)
|
||||
{
|
||||
wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
||||
BOOST_ASSERT(wake_sem);
|
||||
}
|
||||
local_wake_sem=duplicate_handle(wake_sem);
|
||||
|
||||
if(generations[0].notified)
|
||||
{
|
||||
shift_generations_down();
|
||||
}
|
||||
if(!generations[0].semaphore)
|
||||
{
|
||||
generations[0].semaphore=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
||||
BOOST_ASSERT(generations[0].semaphore);
|
||||
}
|
||||
first_loop=false;
|
||||
}
|
||||
++generations[0].count;
|
||||
sem=duplicate_handle(generations[0].semaphore);
|
||||
}
|
||||
unsigned long const notified=detail::win32::WaitForSingleObject(sem,::boost::detail::get_milliseconds_until_time(target_time));
|
||||
BOOST_ASSERT(notified==detail::win32::timeout || notified==0);
|
||||
|
||||
unsigned long const sem_close_result=detail::win32::CloseHandle(sem);
|
||||
BOOST_ASSERT(sem_close_result);
|
||||
|
||||
if(notified==detail::win32::timeout)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned long const woken_result=detail::win32::WaitForSingleObject(local_wake_sem,0);
|
||||
BOOST_ASSERT(woken_result==detail::win32::timeout || woken_result==0);
|
||||
|
||||
woken=(woken_result==0);
|
||||
}
|
||||
unsigned long const wake_sem_close_result=detail::win32::CloseHandle(local_wake_sem);
|
||||
BOOST_ASSERT(wake_sem_close_result);
|
||||
lock.lock();
|
||||
return woken;
|
||||
}
|
||||
|
||||
public:
|
||||
basic_condition():
|
||||
wake_sem(0)
|
||||
{
|
||||
for(unsigned i=0;i<generation_count;++i)
|
||||
{
|
||||
generations[i]=list_entry();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
~basic_condition()
|
||||
{
|
||||
for(unsigned i=0;i<generation_count;++i)
|
||||
{
|
||||
dispose_entry(generations[i]);
|
||||
}
|
||||
detail::win32::CloseHandle(wake_sem);
|
||||
}
|
||||
|
||||
void wait(lock_type& m)
|
||||
{
|
||||
do_wait(m,::boost::detail::get_xtime_sentinel());
|
||||
}
|
||||
|
||||
template<typename predicate_type>
|
||||
void wait(lock_type& m,predicate_type pred)
|
||||
{
|
||||
while(!pred()) wait(m);
|
||||
}
|
||||
|
||||
|
||||
bool timed_wait(lock_type& m,::boost::xtime const& target_time)
|
||||
{
|
||||
return do_wait(m,target_time);
|
||||
}
|
||||
|
||||
template<typename predicate_type>
|
||||
bool timed_wait(lock_type& m,::boost::xtime const& target_time,predicate_type pred)
|
||||
{
|
||||
while (!pred()) { if (!timed_wait(m, target_time)) return false; } return true;
|
||||
}
|
||||
|
||||
void notify_one()
|
||||
{
|
||||
boost::mutex::scoped_lock internal_lock(internal_mutex);
|
||||
if(wake_sem)
|
||||
{
|
||||
detail::win32::ReleaseSemaphore(wake_sem,1,NULL);
|
||||
for(unsigned generation=generation_count;generation!=0;--generation)
|
||||
{
|
||||
list_entry& entry=generations[generation-1];
|
||||
if(entry.count)
|
||||
{
|
||||
entry.notified=true;
|
||||
detail::win32::ReleaseSemaphore(entry.semaphore,1,NULL);
|
||||
if(!--entry.count)
|
||||
{
|
||||
dispose_entry(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void notify_all()
|
||||
{
|
||||
boost::mutex::scoped_lock internal_lock(internal_mutex);
|
||||
if(wake_sem)
|
||||
{
|
||||
for(unsigned generation=generation_count;generation!=0;--generation)
|
||||
{
|
||||
list_entry& entry=generations[generation-1];
|
||||
if(entry.count)
|
||||
{
|
||||
broadcast_entry(entry,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
typedef basic_condition<boost::mutex::scoped_lock> condition;
|
||||
}
|
||||
|
||||
#endif
|
||||
77
include/boost/thread/win32/config.hpp
Normal file
77
include/boost/thread/win32/config.hpp
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_THREAD_RS06041002_HPP
|
||||
#define BOOST_THREAD_RS06041002_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
// insist on threading support being available:
|
||||
#include <boost/config/requires_threads.hpp>
|
||||
|
||||
#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_RS06041002_HPP
|
||||
91
include/boost/thread/win32/exceptions.hpp
Normal file
91
include/boost/thread/win32/exceptions.hpp
Normal file
@@ -0,0 +1,91 @@
|
||||
// (C) Copyright 2005-6 Anthony Williams
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_THREAD_RS06041003_HPP
|
||||
#define BOOST_THREAD_RS06041003_HPP
|
||||
|
||||
|
||||
#include <boost/thread/win32/config.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace boost {
|
||||
|
||||
class BOOST_THREAD_DECL thread_exception : public std::exception
|
||||
{
|
||||
protected:
|
||||
thread_exception();
|
||||
thread_exception(int sys_err_code);
|
||||
|
||||
public:
|
||||
~thread_exception() throw();
|
||||
|
||||
int native_error() const;
|
||||
|
||||
const char* message() const;
|
||||
|
||||
private:
|
||||
int m_sys_err;
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL lock_error : public thread_exception
|
||||
{
|
||||
public:
|
||||
lock_error();
|
||||
lock_error(int sys_err_code);
|
||||
~lock_error() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL thread_resource_error : public thread_exception
|
||||
{
|
||||
public:
|
||||
thread_resource_error();
|
||||
thread_resource_error(int sys_err_code);
|
||||
~thread_resource_error() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL unsupported_thread_option : public thread_exception
|
||||
{
|
||||
public:
|
||||
unsupported_thread_option();
|
||||
unsupported_thread_option(int sys_err_code);
|
||||
~unsupported_thread_option() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL invalid_thread_argument : public thread_exception
|
||||
{
|
||||
public:
|
||||
invalid_thread_argument();
|
||||
invalid_thread_argument(int sys_err_code);
|
||||
~invalid_thread_argument() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL thread_permission_error : public thread_exception
|
||||
{
|
||||
public:
|
||||
thread_permission_error();
|
||||
thread_permission_error(int sys_err_code);
|
||||
~thread_permission_error() throw();
|
||||
|
||||
virtual const char* what() const throw();
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_THREAD_RS06041003_HPP
|
||||
|
||||
36
include/boost/thread/win32/interlocked_read.hpp
Normal file
36
include/boost/thread/win32/interlocked_read.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef BOOST_THREAD_DETAIL_INTERLOCKED_READ_WIN32_HPP
|
||||
#define BOOST_THREAD_DETAIL_INTERLOCKED_READ_WIN32_HPP
|
||||
|
||||
// interlocked_read_win32.hpp
|
||||
//
|
||||
// (C) Copyright 2005-7 Anthony Williams
|
||||
//
|
||||
// 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/detail/interlocked.hpp>
|
||||
|
||||
extern "C" void _ReadWriteBarrier(void);
|
||||
#pragma intrinsic(_ReadWriteBarrier)
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
inline long interlocked_read_acquire(long volatile* x)
|
||||
{
|
||||
long const res=*x;
|
||||
_ReadWriteBarrier();
|
||||
return res;
|
||||
}
|
||||
inline void* interlocked_read_acquire(void* volatile* x)
|
||||
{
|
||||
void* const res=*x;
|
||||
_ReadWriteBarrier();
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
201
include/boost/thread/win32/lock.hpp
Normal file
201
include/boost/thread/win32/lock.hpp
Normal file
@@ -0,0 +1,201 @@
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_THREAD_RS06041005_HPP
|
||||
#define BOOST_THREAD_RS06041005_HPP
|
||||
|
||||
#include <boost/thread/win32/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/win32/exceptions.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct xtime;
|
||||
|
||||
namespace detail { namespace thread {
|
||||
|
||||
template <typename Mutex>
|
||||
class lock_ops : private noncopyable
|
||||
{
|
||||
private:
|
||||
lock_ops() { }
|
||||
|
||||
public:
|
||||
typedef typename Mutex::cv_state lock_state;
|
||||
|
||||
static void lock(Mutex& m)
|
||||
{
|
||||
m.do_lock();
|
||||
}
|
||||
static bool trylock(Mutex& m)
|
||||
{
|
||||
return m.do_trylock();
|
||||
}
|
||||
static bool timedlock(Mutex& m, const xtime& xt)
|
||||
{
|
||||
return m.do_timedlock(xt);
|
||||
}
|
||||
static void unlock(Mutex& m)
|
||||
{
|
||||
m.do_unlock();
|
||||
}
|
||||
static void lock(Mutex& m, lock_state& state)
|
||||
{
|
||||
m.do_lock(state);
|
||||
}
|
||||
static void unlock(Mutex& m, lock_state& state)
|
||||
{
|
||||
m.do_unlock(state);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Mutex>
|
||||
class scoped_lock : private noncopyable
|
||||
{
|
||||
public:
|
||||
typedef Mutex mutex_type;
|
||||
|
||||
explicit scoped_lock(Mutex& mx, bool initially_locked=true)
|
||||
: m_mutex(mx), m_locked(false)
|
||||
{
|
||||
if (initially_locked) lock();
|
||||
}
|
||||
~scoped_lock()
|
||||
{
|
||||
if (m_locked) unlock();
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if (m_locked) throw lock_error();
|
||||
lock_ops<Mutex>::lock(m_mutex);
|
||||
m_locked = true;
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if (!m_locked) throw lock_error();
|
||||
lock_ops<Mutex>::unlock(m_mutex);
|
||||
m_locked = false;
|
||||
}
|
||||
|
||||
bool locked() const { return m_locked; }
|
||||
operator const void*() const { return m_locked ? this : 0; }
|
||||
|
||||
private:
|
||||
|
||||
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:
|
||||
|
||||
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:
|
||||
|
||||
TimedMutex& m_mutex;
|
||||
bool m_locked;
|
||||
};
|
||||
|
||||
} // namespace thread
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_THREAD_RS06041005_HPP
|
||||
272
include/boost/thread/win32/mutex.hpp
Normal file
272
include/boost/thread/win32/mutex.hpp
Normal file
@@ -0,0 +1,272 @@
|
||||
// (C) Copyright 2005-6 Anthony Williams
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_THREAD_RS06041004_HPP
|
||||
#define BOOST_THREAD_RS06041004_HPP
|
||||
|
||||
#include <boost/thread/win32/config.hpp>
|
||||
|
||||
#include <boost/thread/win32/basic_timed_mutex.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/win32/lock.hpp>
|
||||
#include <boost/thread/win32/xtime.hpp>
|
||||
#include <boost/thread/win32/exceptions.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
typedef ::boost::detail::basic_timed_mutex underlying_mutex;
|
||||
}
|
||||
|
||||
class mutex:
|
||||
noncopyable,
|
||||
public ::boost::detail::underlying_mutex
|
||||
{
|
||||
public:
|
||||
mutex()
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
~mutex()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
class scoped_lock
|
||||
{
|
||||
protected:
|
||||
mutex& m;
|
||||
bool is_locked;
|
||||
public:
|
||||
scoped_lock(mutex& m_):
|
||||
m(m_),is_locked(false)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
scoped_lock(mutex& m_,bool do_lock):
|
||||
m(m_),is_locked(false)
|
||||
{
|
||||
if(do_lock)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
}
|
||||
~scoped_lock()
|
||||
{
|
||||
if(locked())
|
||||
{
|
||||
m.unlock();
|
||||
}
|
||||
}
|
||||
void lock()
|
||||
{
|
||||
if(locked())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m.lock();
|
||||
is_locked=true;
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if(!locked())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m.unlock();
|
||||
is_locked=false;
|
||||
}
|
||||
|
||||
operator void* () const
|
||||
{
|
||||
return is_locked?const_cast<void*>(static_cast<void const*>(this)):0;
|
||||
}
|
||||
bool locked() const
|
||||
{
|
||||
return is_locked;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class try_mutex:
|
||||
noncopyable,
|
||||
protected ::boost::detail::underlying_mutex
|
||||
{
|
||||
public:
|
||||
try_mutex()
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
~try_mutex()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
class scoped_try_lock
|
||||
{
|
||||
protected:
|
||||
try_mutex& m;
|
||||
bool is_locked;
|
||||
public:
|
||||
scoped_try_lock(try_mutex& m_):
|
||||
m(m_),is_locked(false)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
scoped_try_lock(try_mutex& m_,bool do_lock):
|
||||
m(m_),is_locked(false)
|
||||
{
|
||||
if(do_lock)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
}
|
||||
~scoped_try_lock()
|
||||
{
|
||||
if(locked())
|
||||
{
|
||||
m.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if(locked())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m.lock();
|
||||
is_locked=true;
|
||||
}
|
||||
bool try_lock()
|
||||
{
|
||||
if(locked())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
is_locked=m.try_lock();
|
||||
return is_locked;
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if(!locked())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m.unlock();
|
||||
is_locked=false;
|
||||
}
|
||||
|
||||
operator void* () const
|
||||
{
|
||||
return is_locked?const_cast<void*>(static_cast<void const*>(this)):0;
|
||||
}
|
||||
bool locked() const
|
||||
{
|
||||
return is_locked;
|
||||
}
|
||||
};
|
||||
|
||||
typedef scoped_try_lock scoped_lock;
|
||||
};
|
||||
|
||||
class timed_mutex:
|
||||
noncopyable,
|
||||
protected ::boost::detail::basic_timed_mutex
|
||||
{
|
||||
public:
|
||||
timed_mutex()
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
~timed_mutex()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
class scoped_timed_lock
|
||||
{
|
||||
protected:
|
||||
timed_mutex& m;
|
||||
bool is_locked;
|
||||
public:
|
||||
scoped_timed_lock(timed_mutex& m_):
|
||||
m(m_),is_locked(false)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
scoped_timed_lock(timed_mutex& m_,::boost::xtime const& target):
|
||||
m(m_),is_locked(false)
|
||||
{
|
||||
timed_lock(target);
|
||||
}
|
||||
scoped_timed_lock(timed_mutex& m_,bool do_lock):
|
||||
m(m_),is_locked(false)
|
||||
{
|
||||
if(do_lock)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
}
|
||||
~scoped_timed_lock()
|
||||
{
|
||||
if(locked())
|
||||
{
|
||||
m.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if(locked())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m.lock();
|
||||
is_locked=true;
|
||||
}
|
||||
bool try_lock()
|
||||
{
|
||||
is_locked=m.try_lock();
|
||||
return is_locked;
|
||||
}
|
||||
bool timed_lock(::boost::xtime const& target)
|
||||
{
|
||||
is_locked=m.timed_lock(target);
|
||||
return is_locked;
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
if(!locked())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m.unlock();
|
||||
is_locked=false;
|
||||
}
|
||||
|
||||
operator void* () const
|
||||
{
|
||||
return is_locked?const_cast<void*>(static_cast<void const*>(this)):0;
|
||||
}
|
||||
bool locked() const
|
||||
{
|
||||
return is_locked;
|
||||
}
|
||||
};
|
||||
|
||||
typedef scoped_timed_lock scoped_try_lock;
|
||||
typedef scoped_timed_lock scoped_lock;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // BOOST_THREAD_RS06041004_HPP
|
||||
114
include/boost/thread/win32/once.hpp
Normal file
114
include/boost/thread/win32/once.hpp
Normal file
@@ -0,0 +1,114 @@
|
||||
#ifndef BOOST_THREAD_WIN32_ONCE_HPP
|
||||
#define BOOST_THREAD_WIN32_ONCE_HPP
|
||||
|
||||
// once.hpp
|
||||
//
|
||||
// (C) Copyright 2005-7 Anthony Williams
|
||||
// (C) Copyright 2005 John Maddock
|
||||
//
|
||||
// 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 <cstring>
|
||||
#include <cstddef>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/detail/interlocked.hpp>
|
||||
#include <boost/thread/win32/thread_primitives.hpp>
|
||||
#include <boost/thread/win32/interlocked_read.hpp>
|
||||
|
||||
#ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std
|
||||
{
|
||||
using ::strlen;
|
||||
using ::memcpy;
|
||||
using ::ptrdiff_t;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
typedef long once_flag;
|
||||
|
||||
#define BOOST_ONCE_INIT 0
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct win32_mutex_scoped_lock
|
||||
{
|
||||
void* const mutex_handle;
|
||||
explicit win32_mutex_scoped_lock(void* mutex_handle_):
|
||||
mutex_handle(mutex_handle_)
|
||||
{
|
||||
unsigned long const res=win32::WaitForSingleObject(mutex_handle,win32::infinite);
|
||||
BOOST_ASSERT(!res);
|
||||
}
|
||||
~win32_mutex_scoped_lock()
|
||||
{
|
||||
bool const success=win32::ReleaseMutex(mutex_handle)!=0;
|
||||
BOOST_ASSERT(success);
|
||||
}
|
||||
};
|
||||
|
||||
template <class I>
|
||||
void int_to_string(I p, char* buf)
|
||||
{
|
||||
unsigned i=0;
|
||||
for(; i < sizeof(I)*2; ++i)
|
||||
{
|
||||
buf[i] = 'A' + static_cast<char>((p >> (i*4)) & 0x0f);
|
||||
}
|
||||
buf[i] = 0;
|
||||
}
|
||||
|
||||
unsigned const once_mutex_name_fixed_length=48;
|
||||
unsigned const once_mutex_name_fixed_buffer_size=once_mutex_name_fixed_length+1;
|
||||
unsigned const once_mutex_name_length=once_mutex_name_fixed_buffer_size+sizeof(void*)*2+sizeof(unsigned long)*2;
|
||||
|
||||
// create a named mutex. It doesn't really matter what this name is
|
||||
// as long as it is unique both to this process, and to the address of "flag":
|
||||
inline void* create_once_mutex(char (&mutex_name)[once_mutex_name_length],void* flag_address)
|
||||
{
|
||||
static const char fixed_mutex_name[]="{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
|
||||
BOOST_STATIC_ASSERT(sizeof(fixed_mutex_name) == once_mutex_name_fixed_buffer_size);
|
||||
|
||||
std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name));
|
||||
BOOST_ASSERT(sizeof(mutex_name) == std::strlen(mutex_name) + sizeof(void*)*2 + sizeof(unsigned long)*2 + 1);
|
||||
|
||||
BOOST_STATIC_ASSERT(sizeof(void*) == sizeof(std::ptrdiff_t));
|
||||
detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address), mutex_name + once_mutex_name_fixed_length);
|
||||
detail::int_to_string(win32::GetCurrentProcessId(), mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2);
|
||||
BOOST_ASSERT(sizeof(mutex_name) == std::strlen(mutex_name) + 1);
|
||||
|
||||
return win32::CreateMutexA(NULL, 0, mutex_name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<typename Function>
|
||||
void call_once(once_flag& flag,Function f)
|
||||
{
|
||||
// Try for a quick win: if the proceedure has already been called
|
||||
// just skip through:
|
||||
long const function_complete_flag_value=0xc15730e2;
|
||||
|
||||
if(::boost::detail::interlocked_read_acquire(&flag)!=function_complete_flag_value)
|
||||
{
|
||||
char mutex_name[::boost::detail::once_mutex_name_length];
|
||||
void* const mutex_handle(::boost::detail::create_once_mutex(mutex_name,&flag));
|
||||
BOOST_ASSERT(mutex_handle);
|
||||
detail::win32::handle_manager const closer(mutex_handle);
|
||||
detail::win32_mutex_scoped_lock const lock(mutex_handle);
|
||||
|
||||
if(flag!=function_complete_flag_value)
|
||||
{
|
||||
f();
|
||||
BOOST_INTERLOCKED_EXCHANGE(&flag,function_complete_flag_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
528
include/boost/thread/win32/read_write_mutex.hpp
Normal file
528
include/boost/thread/win32/read_write_mutex.hpp
Normal file
@@ -0,0 +1,528 @@
|
||||
#ifndef BOOST_THREAD_WIN32_READ_WRITE_MUTEX_HPP
|
||||
#define BOOST_THREAD_WIN32_READ_WRITE_MUTEX_HPP
|
||||
|
||||
// (C) Copyright 2006 Anthony Williams
|
||||
//
|
||||
// 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/assert.hpp>
|
||||
#include <boost/detail/interlocked.hpp>
|
||||
#include <boost/thread/win32/thread_primitives.hpp>
|
||||
#include <boost/thread/win32/interlocked_read.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <limits.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class read_write_mutex
|
||||
{
|
||||
private:
|
||||
struct state_data
|
||||
{
|
||||
unsigned shared_count:10;
|
||||
unsigned shared_waiting:10;
|
||||
unsigned exclusive:1;
|
||||
unsigned upgradeable:1;
|
||||
unsigned exclusive_waiting:9;
|
||||
unsigned exclusive_waiting_blocked:1;
|
||||
|
||||
friend bool operator==(state_data const& lhs,state_data const& rhs)
|
||||
{
|
||||
return *reinterpret_cast<unsigned const*>(&lhs)==*reinterpret_cast<unsigned const*>(&rhs);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
T interlocked_compare_exchange(T* target,T new_value,T comparand)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(sizeof(T)==sizeof(long));
|
||||
long const res=BOOST_INTERLOCKED_COMPARE_EXCHANGE(reinterpret_cast<long*>(target),
|
||||
*reinterpret_cast<long*>(&new_value),
|
||||
*reinterpret_cast<long*>(&comparand));
|
||||
return *reinterpret_cast<T const*>(&res);
|
||||
}
|
||||
|
||||
state_data state;
|
||||
void* semaphores[2];
|
||||
void* &unlock_sem;
|
||||
void* &exclusive_sem;
|
||||
void* upgradeable_sem;
|
||||
|
||||
void release_waiters(state_data old_state)
|
||||
{
|
||||
if(old_state.exclusive_waiting)
|
||||
{
|
||||
bool const success=detail::win32::ReleaseSemaphore(exclusive_sem,1,NULL)!=0;
|
||||
BOOST_ASSERT(success);
|
||||
}
|
||||
|
||||
if(old_state.shared_waiting || old_state.exclusive_waiting)
|
||||
{
|
||||
bool const success=detail::win32::ReleaseSemaphore(unlock_sem,old_state.shared_waiting + (old_state.exclusive_waiting?1:0),NULL)!=0;
|
||||
BOOST_ASSERT(success);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
read_write_mutex():
|
||||
unlock_sem(semaphores[0]),
|
||||
exclusive_sem(semaphores[1])
|
||||
{
|
||||
unlock_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
||||
exclusive_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
||||
upgradeable_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
||||
state_data state_={0};
|
||||
state=state_;
|
||||
}
|
||||
|
||||
~read_write_mutex()
|
||||
{
|
||||
detail::win32::CloseHandle(upgradeable_sem);
|
||||
detail::win32::CloseHandle(unlock_sem);
|
||||
detail::win32::CloseHandle(exclusive_sem);
|
||||
}
|
||||
|
||||
bool try_lock_shareable()
|
||||
{
|
||||
state_data old_state=state;
|
||||
do
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
if(!new_state.exclusive && !new_state.exclusive_waiting_blocked)
|
||||
{
|
||||
++new_state.shared_count;
|
||||
}
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if(current_state==old_state)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
while(true);
|
||||
return !(old_state.exclusive| old_state.exclusive_waiting_blocked);
|
||||
}
|
||||
|
||||
void lock_shareable()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
state_data old_state=state;
|
||||
do
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
|
||||
{
|
||||
++new_state.shared_waiting;
|
||||
}
|
||||
else
|
||||
{
|
||||
++new_state.shared_count;
|
||||
}
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if(current_state==old_state)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
while(true);
|
||||
|
||||
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long const res=detail::win32::WaitForSingleObject(unlock_sem,detail::win32::infinite);
|
||||
BOOST_ASSERT(res==0);
|
||||
}
|
||||
}
|
||||
|
||||
void unlock_shareable()
|
||||
{
|
||||
state_data old_state=state;
|
||||
do
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
bool const last_reader=!--new_state.shared_count;
|
||||
|
||||
if(last_reader)
|
||||
{
|
||||
if(new_state.upgradeable)
|
||||
{
|
||||
new_state.upgradeable=false;
|
||||
new_state.exclusive=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(new_state.exclusive_waiting)
|
||||
{
|
||||
--new_state.exclusive_waiting;
|
||||
new_state.exclusive_waiting_blocked=false;
|
||||
}
|
||||
new_state.shared_waiting=0;
|
||||
}
|
||||
}
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if(current_state==old_state)
|
||||
{
|
||||
if(last_reader)
|
||||
{
|
||||
if(old_state.upgradeable)
|
||||
{
|
||||
bool const success=detail::win32::ReleaseSemaphore(upgradeable_sem,1,NULL)!=0;
|
||||
BOOST_ASSERT(success);
|
||||
}
|
||||
else
|
||||
{
|
||||
release_waiters(old_state);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
while(true);
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
state_data old_state=state;
|
||||
|
||||
do
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
if(new_state.shared_count || new_state.exclusive)
|
||||
{
|
||||
++new_state.exclusive_waiting;
|
||||
new_state.exclusive_waiting_blocked=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_state.exclusive=true;
|
||||
}
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if(current_state==old_state)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
while(true);
|
||||
|
||||
if(!old_state.shared_count && !old_state.exclusive)
|
||||
{
|
||||
break;
|
||||
}
|
||||
bool const success2=detail::win32::WaitForMultipleObjects(2,semaphores,true,detail::win32::infinite)<2;
|
||||
BOOST_ASSERT(success2);
|
||||
}
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
state_data old_state=state;
|
||||
do
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
new_state.exclusive=false;
|
||||
if(new_state.exclusive_waiting)
|
||||
{
|
||||
--new_state.exclusive_waiting;
|
||||
new_state.exclusive_waiting_blocked=false;
|
||||
}
|
||||
new_state.shared_waiting=0;
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if(current_state==old_state)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
while(true);
|
||||
release_waiters(old_state);
|
||||
}
|
||||
|
||||
void lock_upgradeable()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
state_data old_state=state;
|
||||
do
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgradeable)
|
||||
{
|
||||
++new_state.shared_waiting;
|
||||
}
|
||||
else
|
||||
{
|
||||
++new_state.shared_count;
|
||||
new_state.upgradeable=true;
|
||||
}
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if(current_state==old_state)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
while(true);
|
||||
|
||||
if(!(old_state.exclusive|| old_state.exclusive_waiting_blocked|| old_state.upgradeable))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned long const res=detail::win32::WaitForSingleObject(unlock_sem,detail::win32::infinite);
|
||||
BOOST_ASSERT(res==0);
|
||||
}
|
||||
}
|
||||
|
||||
void unlock_upgradeable()
|
||||
{
|
||||
state_data old_state=state;
|
||||
do
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
new_state.upgradeable=false;
|
||||
bool const last_reader=!--new_state.shared_count;
|
||||
|
||||
if(last_reader)
|
||||
{
|
||||
if(new_state.exclusive_waiting)
|
||||
{
|
||||
--new_state.exclusive_waiting;
|
||||
new_state.exclusive_waiting_blocked=false;
|
||||
}
|
||||
new_state.shared_waiting=0;
|
||||
}
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if(current_state==old_state)
|
||||
{
|
||||
if(last_reader)
|
||||
{
|
||||
release_waiters(old_state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
while(true);
|
||||
}
|
||||
|
||||
void unlock_upgradeable_and_lock()
|
||||
{
|
||||
state_data old_state=state;
|
||||
do
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
bool const last_reader=!--new_state.shared_count;
|
||||
|
||||
if(last_reader)
|
||||
{
|
||||
new_state.upgradeable=false;
|
||||
new_state.exclusive=true;
|
||||
}
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if(current_state==old_state)
|
||||
{
|
||||
if(!last_reader)
|
||||
{
|
||||
unsigned long const res=detail::win32::WaitForSingleObject(upgradeable_sem,detail::win32::infinite);
|
||||
BOOST_ASSERT(res==0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
while(true);
|
||||
}
|
||||
|
||||
void unlock_and_lock_upgradeable()
|
||||
{
|
||||
state_data old_state=state;
|
||||
do
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
new_state.exclusive=false;
|
||||
new_state.upgradeable=true;
|
||||
++new_state.shared_count;
|
||||
if(new_state.exclusive_waiting)
|
||||
{
|
||||
--new_state.exclusive_waiting;
|
||||
new_state.exclusive_waiting_blocked=false;
|
||||
}
|
||||
new_state.shared_waiting=0;
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if(current_state==old_state)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
while(true);
|
||||
release_waiters(old_state);
|
||||
}
|
||||
|
||||
void unlock_and_lock_shareable()
|
||||
{
|
||||
state_data old_state=state;
|
||||
do
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
new_state.exclusive=false;
|
||||
++new_state.shared_count;
|
||||
if(new_state.exclusive_waiting)
|
||||
{
|
||||
--new_state.exclusive_waiting;
|
||||
new_state.exclusive_waiting_blocked=false;
|
||||
}
|
||||
new_state.shared_waiting=0;
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if(current_state==old_state)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
while(true);
|
||||
release_waiters(old_state);
|
||||
}
|
||||
|
||||
void unlock_upgradeable_and_lock_shareable()
|
||||
{
|
||||
state_data old_state=state;
|
||||
do
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
new_state.upgradeable=false;
|
||||
if(new_state.exclusive_waiting)
|
||||
{
|
||||
--new_state.exclusive_waiting;
|
||||
new_state.exclusive_waiting_blocked=false;
|
||||
}
|
||||
new_state.shared_waiting=0;
|
||||
|
||||
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
|
||||
if(current_state==old_state)
|
||||
{
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
while(true);
|
||||
release_waiters(old_state);
|
||||
}
|
||||
|
||||
class scoped_read_lock
|
||||
{
|
||||
read_write_mutex& m;
|
||||
public:
|
||||
scoped_read_lock(read_write_mutex& m_):
|
||||
m(m_)
|
||||
{
|
||||
m.lock_shareable();
|
||||
}
|
||||
~scoped_read_lock()
|
||||
{
|
||||
m.unlock_shareable();
|
||||
}
|
||||
};
|
||||
|
||||
class scoped_write_lock
|
||||
{
|
||||
read_write_mutex& m;
|
||||
bool locked;
|
||||
|
||||
public:
|
||||
scoped_write_lock(read_write_mutex& m_):
|
||||
m(m_),locked(false)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
void lock()
|
||||
{
|
||||
m.lock();
|
||||
locked=true;
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
m.unlock();
|
||||
locked=false;
|
||||
}
|
||||
~scoped_write_lock()
|
||||
{
|
||||
if(locked)
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class scoped_upgradeable_lock
|
||||
{
|
||||
read_write_mutex& m;
|
||||
bool locked;
|
||||
bool upgraded;
|
||||
|
||||
public:
|
||||
scoped_upgradeable_lock(read_write_mutex& m_):
|
||||
m(m_),
|
||||
locked(false),upgraded(false)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
void lock()
|
||||
{
|
||||
m.lock_upgradeable();
|
||||
locked=true;
|
||||
}
|
||||
void upgrade()
|
||||
{
|
||||
m.unlock_upgradeable_and_lock();
|
||||
upgraded=true;
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if(upgraded)
|
||||
{
|
||||
m.unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
m.unlock_upgradeable();
|
||||
}
|
||||
}
|
||||
~scoped_upgradeable_lock()
|
||||
{
|
||||
if(locked)
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
263
include/boost/thread/win32/recursive_mutex.hpp
Normal file
263
include/boost/thread/win32/recursive_mutex.hpp
Normal file
@@ -0,0 +1,263 @@
|
||||
#ifndef BOOST_RECURSIVE_MUTEX_WIN32_HPP
|
||||
#define BOOST_RECURSIVE_MUTEX_WIN32_HPP
|
||||
|
||||
// recursive_mutex.hpp
|
||||
//
|
||||
// (C) Copyright 2006 Anthony Williams
|
||||
//
|
||||
// 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/win32/basic_recursive_mutex.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class recursive_mutex:
|
||||
noncopyable,
|
||||
protected ::boost::detail::basic_recursive_mutex
|
||||
{
|
||||
public:
|
||||
recursive_mutex()
|
||||
{
|
||||
::boost::detail::basic_recursive_mutex::initialize();
|
||||
}
|
||||
~recursive_mutex()
|
||||
{
|
||||
::boost::detail::basic_recursive_mutex::destroy();
|
||||
}
|
||||
|
||||
class scoped_lock
|
||||
{
|
||||
protected:
|
||||
recursive_mutex& m;
|
||||
bool is_locked;
|
||||
public:
|
||||
scoped_lock(recursive_mutex& m_):
|
||||
m(m_),is_locked(false)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
scoped_lock(recursive_mutex& m_,bool do_lock):
|
||||
m(m_),is_locked(false)
|
||||
{
|
||||
if(do_lock)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
}
|
||||
~scoped_lock()
|
||||
{
|
||||
if(locked())
|
||||
{
|
||||
m.unlock();
|
||||
}
|
||||
}
|
||||
void lock()
|
||||
{
|
||||
if(locked())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m.lock();
|
||||
is_locked=true;
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if(!locked())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m.unlock();
|
||||
is_locked=false;
|
||||
}
|
||||
|
||||
operator void* () const
|
||||
{
|
||||
return is_locked?const_cast<void*>(static_cast<void const*>(this)):0;
|
||||
}
|
||||
bool locked() const
|
||||
{
|
||||
return is_locked;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class recursive_try_mutex:
|
||||
noncopyable,
|
||||
protected ::boost::detail::basic_recursive_mutex
|
||||
{
|
||||
public:
|
||||
recursive_try_mutex()
|
||||
{
|
||||
::boost::detail::basic_recursive_mutex::initialize();
|
||||
}
|
||||
~recursive_try_mutex()
|
||||
{
|
||||
::boost::detail::basic_recursive_mutex::destroy();
|
||||
}
|
||||
class scoped_try_lock
|
||||
{
|
||||
protected:
|
||||
recursive_try_mutex& m;
|
||||
bool is_locked;
|
||||
public:
|
||||
scoped_try_lock(recursive_try_mutex& m_):
|
||||
m(m_),is_locked(false)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
scoped_try_lock(recursive_try_mutex& m_,bool do_lock):
|
||||
m(m_),is_locked(false)
|
||||
{
|
||||
if(do_lock)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
}
|
||||
~scoped_try_lock()
|
||||
{
|
||||
if(locked())
|
||||
{
|
||||
m.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if(locked())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m.lock();
|
||||
is_locked=true;
|
||||
}
|
||||
bool try_lock()
|
||||
{
|
||||
if(locked())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
is_locked=m.try_lock();
|
||||
return is_locked;
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if(!locked())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m.unlock();
|
||||
is_locked=false;
|
||||
}
|
||||
|
||||
operator void* () const
|
||||
{
|
||||
return is_locked?const_cast<void*>(static_cast<void const*>(this)):0;
|
||||
}
|
||||
bool locked() const
|
||||
{
|
||||
return is_locked;
|
||||
}
|
||||
};
|
||||
|
||||
typedef scoped_try_lock scoped_lock;
|
||||
};
|
||||
|
||||
class recursive_timed_mutex:
|
||||
noncopyable,
|
||||
protected ::boost::detail::basic_recursive_timed_mutex
|
||||
{
|
||||
public:
|
||||
recursive_timed_mutex()
|
||||
{
|
||||
::boost::detail::basic_recursive_timed_mutex::initialize();
|
||||
}
|
||||
~recursive_timed_mutex()
|
||||
{
|
||||
::boost::detail::basic_recursive_timed_mutex::destroy();
|
||||
}
|
||||
|
||||
class scoped_timed_lock
|
||||
{
|
||||
protected:
|
||||
recursive_timed_mutex& m;
|
||||
bool is_locked;
|
||||
public:
|
||||
scoped_timed_lock(recursive_timed_mutex& m_):
|
||||
m(m_),is_locked(false)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
scoped_timed_lock(recursive_timed_mutex& m_,::boost::xtime const& target):
|
||||
m(m_),is_locked(false)
|
||||
{
|
||||
timed_lock(target);
|
||||
}
|
||||
scoped_timed_lock(recursive_timed_mutex& m_,bool do_lock):
|
||||
m(m_),is_locked(false)
|
||||
{
|
||||
if(do_lock)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
}
|
||||
~scoped_timed_lock()
|
||||
{
|
||||
if(locked())
|
||||
{
|
||||
m.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if(locked())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m.lock();
|
||||
is_locked=true;
|
||||
}
|
||||
bool try_lock()
|
||||
{
|
||||
is_locked=m.try_lock();
|
||||
return is_locked;
|
||||
}
|
||||
bool timed_lock(::boost::xtime const& target)
|
||||
{
|
||||
is_locked=m.timed_lock(target);
|
||||
return is_locked;
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
if(!locked())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m.unlock();
|
||||
is_locked=false;
|
||||
}
|
||||
|
||||
operator void* () const
|
||||
{
|
||||
return is_locked?const_cast<void*>(static_cast<void const*>(this)):0;
|
||||
}
|
||||
bool locked() const
|
||||
{
|
||||
return is_locked;
|
||||
}
|
||||
};
|
||||
|
||||
typedef scoped_timed_lock scoped_try_lock;
|
||||
typedef scoped_timed_lock scoped_lock;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
77
include/boost/thread/win32/thread.hpp
Normal file
77
include/boost/thread/win32/thread.hpp
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_THREAD_RS06041007_HPP
|
||||
#define BOOST_THREAD_RS06041007_HPP
|
||||
|
||||
#include <boost/thread/win32/config.hpp>
|
||||
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/function.hpp>
|
||||
|
||||
#include <boost/thread/win32/mutex.hpp>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct xtime;
|
||||
|
||||
// disable warnings about non dll import
|
||||
// see: http://www.boost.org/more/separate_compilation.html#dlls
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4251 4231 4660 4275)
|
||||
#endif
|
||||
|
||||
class BOOST_THREAD_DECL thread : private noncopyable
|
||||
{
|
||||
public:
|
||||
thread();
|
||||
explicit thread(const function0<void>& threadfunc);
|
||||
~thread();
|
||||
|
||||
bool operator==(const thread& other) const;
|
||||
bool operator!=(const thread& other) const;
|
||||
|
||||
void join();
|
||||
|
||||
static void sleep(const xtime& xt);
|
||||
static void yield();
|
||||
|
||||
private:
|
||||
void* m_thread;
|
||||
unsigned int m_id;
|
||||
bool m_joinable;
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL thread_group : private noncopyable
|
||||
{
|
||||
public:
|
||||
thread_group();
|
||||
~thread_group();
|
||||
|
||||
thread* create_thread(const function0<void>& threadfunc);
|
||||
void add_thread(thread* thrd);
|
||||
void remove_thread(thread* thrd);
|
||||
void join_all();
|
||||
int size();
|
||||
|
||||
private:
|
||||
std::list<thread*> m_threads;
|
||||
mutex m_mutex;
|
||||
};
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_THREAD_RS06041007_HPP
|
||||
198
include/boost/thread/win32/thread_primitives.hpp
Normal file
198
include/boost/thread/win32/thread_primitives.hpp
Normal file
@@ -0,0 +1,198 @@
|
||||
#ifndef BOOST_WIN32_THREAD_PRIMITIVES_HPP
|
||||
#define BOOST_WIN32_THREAD_PRIMITIVES_HPP
|
||||
|
||||
// win32_thread_primitives.hpp
|
||||
//
|
||||
// (C) Copyright 2005-6 Anthony Williams
|
||||
//
|
||||
// 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/config.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
|
||||
#if defined( BOOST_USE_WINDOWS_H )
|
||||
# include <windows.h>
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
namespace win32
|
||||
{
|
||||
typedef ULONG_PTR ulong_ptr;
|
||||
typedef HANDLE handle;
|
||||
unsigned const infinite=INFINITE;
|
||||
unsigned const timeout=WAIT_TIMEOUT;
|
||||
|
||||
using ::CreateMutexA;
|
||||
using ::CreateEventA;
|
||||
using ::CreateSemaphoreA;
|
||||
using ::CloseHandle;
|
||||
using ::ReleaseMutex;
|
||||
using ::ReleaseSemaphore;
|
||||
using ::SetEvent;
|
||||
using ::ResetEvent;
|
||||
using ::WaitForMultipleObjects;
|
||||
using ::WaitForSingleObject;
|
||||
using ::GetCurrentProcessId;
|
||||
using ::GetCurrentThreadId;
|
||||
using ::GetCurrentThread;
|
||||
using ::GetCurrentProcess;
|
||||
using ::DuplicateHandle;
|
||||
using ::SleepEx;
|
||||
using ::QueueUserAPC;
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
namespace win32
|
||||
{
|
||||
|
||||
# ifdef _WIN64
|
||||
typedef unsigned __int64 ulong_ptr;
|
||||
# else
|
||||
typedef unsigned long ulong_ptr;
|
||||
# endif
|
||||
typedef void* handle;
|
||||
unsigned const infinite=~0U;
|
||||
unsigned const timeout=258U;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
struct _SECURITY_ATTRIBUTES;
|
||||
__declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*);
|
||||
__declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*);
|
||||
__declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*);
|
||||
__declspec(dllimport) int __stdcall CloseHandle(void*);
|
||||
__declspec(dllimport) int __stdcall ReleaseMutex(void*);
|
||||
__declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
|
||||
__declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
|
||||
__declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void*,unsigned long);
|
||||
__declspec(dllimport) int __stdcall ReleaseSemaphore(void*,long,long*);
|
||||
__declspec(dllimport) void* __stdcall GetCurrentThread();
|
||||
__declspec(dllimport) void* __stdcall GetCurrentProcess();
|
||||
__declspec(dllimport) int __stdcall DuplicateHandle(void*,void*,void*,void**,unsigned long,int,unsigned long);
|
||||
__declspec(dllimport) unsigned long __stdcall SleepEx(unsigned long,int);
|
||||
typedef void (__stdcall *queue_user_apc_callback_function)(ulong_ptr);
|
||||
__declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr);
|
||||
__declspec(dllimport) int __stdcall SetEvent(void*);
|
||||
__declspec(dllimport) int __stdcall ResetEvent(void*);
|
||||
__declspec(dllimport) unsigned long __stdcall WaitForMultipleObjects(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
# error "Win32 functions not available"
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
namespace win32
|
||||
{
|
||||
enum event_type
|
||||
{
|
||||
auto_reset_event=false,
|
||||
manual_reset_event=true
|
||||
};
|
||||
|
||||
enum initial_event_state
|
||||
{
|
||||
event_initially_reset=false,
|
||||
event_initially_set=true
|
||||
};
|
||||
|
||||
inline handle create_anonymous_event(event_type type,initial_event_state state)
|
||||
{
|
||||
handle const res=CreateEventA(0,type,state,0);
|
||||
return res?res:throw thread_resource_error();
|
||||
}
|
||||
|
||||
inline handle create_anonymous_semaphore(long initial_count,long max_count)
|
||||
{
|
||||
handle const res=CreateSemaphoreA(NULL,initial_count,max_count,NULL);
|
||||
return res?res:throw thread_resource_error();
|
||||
}
|
||||
|
||||
inline handle duplicate_handle(handle source)
|
||||
{
|
||||
handle const current_process=GetCurrentProcess();
|
||||
long const same_access_flag=2;
|
||||
handle new_handle=0;
|
||||
bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
|
||||
return success?new_handle:throw thread_resource_error();
|
||||
}
|
||||
|
||||
inline void release_semaphore(handle semaphore,long count)
|
||||
{
|
||||
bool const success=ReleaseSemaphore(semaphore,count,0)!=0;
|
||||
BOOST_ASSERT(success);
|
||||
}
|
||||
|
||||
class handle_manager
|
||||
{
|
||||
private:
|
||||
handle handle_to_manage;
|
||||
handle_manager(handle_manager&);
|
||||
handle_manager& operator=(handle_manager&);
|
||||
|
||||
void cleanup()
|
||||
{
|
||||
if(handle_to_manage)
|
||||
{
|
||||
unsigned long result=CloseHandle(handle_to_manage);
|
||||
BOOST_ASSERT(result);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
explicit handle_manager(handle handle_to_manage_):
|
||||
handle_to_manage(handle_to_manage_)
|
||||
{}
|
||||
handle_manager():
|
||||
handle_to_manage(0)
|
||||
{}
|
||||
|
||||
handle_manager& operator=(handle new_handle)
|
||||
{
|
||||
cleanup();
|
||||
handle_to_manage=new_handle;
|
||||
}
|
||||
|
||||
operator handle() const
|
||||
{
|
||||
return handle_to_manage;
|
||||
}
|
||||
|
||||
handle release()
|
||||
{
|
||||
handle const res=handle_to_manage;
|
||||
handle_to_manage=0;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
return !handle_to_manage;
|
||||
}
|
||||
|
||||
~handle_manager()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
106
include/boost/thread/win32/tss.hpp
Normal file
106
include/boost/thread/win32/tss.hpp
Normal file
@@ -0,0 +1,106 @@
|
||||
// Copyright (C) 2001-2003 William E. Kempf
|
||||
// Copyright (C) 2006 Roland Schwarz
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_TSS_RS06092305_HPP
|
||||
#define BOOST_TSS_RS06092305_HPP
|
||||
|
||||
#include <boost/thread/win32/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/thread/win32/exceptions.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 detail {
|
||||
|
||||
class BOOST_THREAD_DECL tss : private noncopyable
|
||||
{
|
||||
public:
|
||||
tss(boost::function1<void, void*>* pcleanup) {
|
||||
if (pcleanup == 0) throw boost::thread_resource_error();
|
||||
try
|
||||
{
|
||||
init(pcleanup);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
delete pcleanup;
|
||||
throw boost::thread_resource_error();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct tss_adapter
|
||||
{
|
||||
template <typename F>
|
||||
tss_adapter(const F& cleanup) : m_cleanup(cleanup) { }
|
||||
void operator()(void* p) { m_cleanup(static_cast<T*>(p)); }
|
||||
boost::function1<void, T*> m_cleanup;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T>
|
||||
class thread_specific_ptr : private noncopyable
|
||||
{
|
||||
public:
|
||||
thread_specific_ptr()
|
||||
: m_tss(new boost::function1<void, void*>(
|
||||
boost::detail::tss_adapter<T>(
|
||||
&thread_specific_ptr<T>::cleanup)))
|
||||
{
|
||||
}
|
||||
thread_specific_ptr(void (*clean)(T*))
|
||||
: m_tss(new boost::function1<void, void*>(
|
||||
boost::detail::tss_adapter<T>(clean)))
|
||||
{
|
||||
}
|
||||
~thread_specific_ptr() { reset(); }
|
||||
|
||||
T* get() const { return static_cast<T*>(m_tss.get()); }
|
||||
T* operator->() const { return get(); }
|
||||
T& operator*() const { return *get(); }
|
||||
T* release() { T* temp = get(); if (temp) m_tss.set(0); return temp; }
|
||||
void reset(T* p=0)
|
||||
{
|
||||
T* cur = get();
|
||||
if (cur == p) return;
|
||||
m_tss.set(p);
|
||||
if (cur) m_tss.cleanup(cur);
|
||||
}
|
||||
|
||||
private:
|
||||
static void cleanup(T* p) { delete p; }
|
||||
detail::tss m_tss;
|
||||
};
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif //BOOST_TSS_RS06092305_HPP
|
||||
74
include/boost/thread/win32/tss_hooks.hpp
Normal file
74
include/boost/thread/win32/tss_hooks.hpp
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright (C) 2001-2003 William E. Kempf
|
||||
// Copyright (C) Michael Glassford 2004.
|
||||
// Copyright (C) 2006 Roland Schwarz
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_TLS_HOOKS_RS06092306_HPP
|
||||
#define BOOST_TLS_HOOKS_RS06092306_HPP
|
||||
|
||||
#include <boost/thread/win32/config.hpp>
|
||||
|
||||
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.
|
||||
|
||||
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 //BOOST_TLS_HOOKS_RS06092306_HPP
|
||||
56
include/boost/thread/win32/xtime.hpp
Normal file
56
include/boost/thread/win32/xtime.hpp
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// This work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_THREAD_RS06041006_HPP
|
||||
#define BOOST_THREAD_RS06041006_HPP
|
||||
|
||||
#include <boost/thread/win32/config.hpp>
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
enum xtime_clock_types
|
||||
{
|
||||
TIME_UTC=1
|
||||
// TIME_TAI,
|
||||
// TIME_MONOTONIC,
|
||||
// TIME_PROCESS,
|
||||
// TIME_THREAD,
|
||||
// TIME_LOCAL,
|
||||
// TIME_SYNC,
|
||||
// TIME_RESOLUTION
|
||||
};
|
||||
|
||||
struct xtime
|
||||
{
|
||||
#if defined(BOOST_NO_INT64_T)
|
||||
typedef int_fast32_t xtime_sec_t; //INT_FAST32_MIN <= sec <= INT_FAST32_MAX
|
||||
#else
|
||||
typedef int_fast64_t xtime_sec_t; //INT_FAST64_MIN <= sec <= INT_FAST64_MAX
|
||||
#endif
|
||||
|
||||
typedef int_fast32_t xtime_nsec_t; //0 <= xtime.nsec < NANOSECONDS_PER_SECOND
|
||||
|
||||
xtime_sec_t sec;
|
||||
xtime_nsec_t nsec;
|
||||
};
|
||||
|
||||
int BOOST_THREAD_DECL xtime_get(struct xtime* xtp, int clock_type);
|
||||
|
||||
inline int xtime_cmp(const xtime& xt1, const xtime& xt2)
|
||||
{
|
||||
if (xt1.sec == xt2.sec)
|
||||
return (int)(xt1.nsec - xt2.nsec);
|
||||
else
|
||||
return (xt1.sec > xt2.sec) ? 1 : -1;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif //BOOST_THREAD_RS06041006_HPP
|
||||
85
include/boost/thread/win32/xtime_utils.hpp
Normal file
85
include/boost/thread/win32/xtime_utils.hpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#ifndef BOOST_THREAD_DETAIL_XTIME_UTILS_HPP
|
||||
#define BOOST_THREAD_DETAIL_XTIME_UTILS_HPP
|
||||
|
||||
// xtime_utils.hpp
|
||||
//
|
||||
// (C) Copyright 2005 Anthony Williams
|
||||
//
|
||||
// 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/win32/xtime.hpp>
|
||||
#include <limits>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
inline ::boost::xtime get_xtime_sentinel()
|
||||
{
|
||||
boost::xtime const sentinel={
|
||||
(std::numeric_limits<boost::xtime::xtime_sec_t>::max)(),
|
||||
(std::numeric_limits<boost::xtime::xtime_nsec_t>::max)()
|
||||
};
|
||||
return sentinel;
|
||||
|
||||
}
|
||||
|
||||
// get the number of milliseconds from now to target
|
||||
// if target is in the past, return 0
|
||||
// if target cannot be represented as unsigned long, return
|
||||
// the maximum instead
|
||||
// 2006-08-04 <roland>
|
||||
inline unsigned long get_milliseconds_until_time(::boost::xtime target)
|
||||
{
|
||||
if(!boost::xtime_cmp(target,get_xtime_sentinel()))
|
||||
{
|
||||
return (std::numeric_limits<unsigned long>::max)();
|
||||
}
|
||||
|
||||
boost::xtime now;
|
||||
boost::xtime_get(&now, boost::TIME_UTC);
|
||||
|
||||
if (target.sec < now.sec)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::xtime::xtime_nsec_t const nanoseconds_per_second=1000000000;
|
||||
boost::xtime::xtime_nsec_t const milliseconds_per_second=1000;
|
||||
boost::xtime::xtime_nsec_t const nanoseconds_per_millisecond=nanoseconds_per_second/milliseconds_per_second;
|
||||
if (target.nsec < now.nsec)
|
||||
{
|
||||
if (target.sec == now.sec)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
target.nsec += nanoseconds_per_second - now.nsec;
|
||||
target.sec -= now.sec + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
target.nsec -= now.nsec;
|
||||
target.sec -= now.sec;
|
||||
}
|
||||
// we are throwing away some bits, but one second after having
|
||||
// waited for 49 years does not really matter ...
|
||||
if (target.sec < (std::numeric_limits<unsigned long>::max)()/milliseconds_per_second)
|
||||
{
|
||||
return static_cast<unsigned long>(
|
||||
target.sec*milliseconds_per_second +
|
||||
(target.nsec+nanoseconds_per_millisecond/2)/nanoseconds_per_millisecond);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (std::numeric_limits<unsigned long>::max)();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,58 +1,16 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// 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 work is a reimplementation along the design and ideas
|
||||
// of William E. Kempf.
|
||||
|
||||
#ifndef BOOST_XTIME_WEK070601_HPP
|
||||
#define BOOST_XTIME_WEK070601_HPP
|
||||
#ifndef BOOST_THREAD_RS06040712_HPP
|
||||
#define BOOST_THREAD_RS06040712_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/detail/platform.hpp>
|
||||
#include BOOST_THREAD_PLATFORM(xtime.hpp)
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
enum xtime_clock_types
|
||||
{
|
||||
TIME_UTC=1
|
||||
// TIME_TAI,
|
||||
// TIME_MONOTONIC,
|
||||
// TIME_PROCESS,
|
||||
// TIME_THREAD,
|
||||
// TIME_LOCAL,
|
||||
// TIME_SYNC,
|
||||
// TIME_RESOLUTION
|
||||
};
|
||||
|
||||
struct xtime
|
||||
{
|
||||
#if defined(BOOST_NO_INT64_T)
|
||||
int_fast32_t sec;
|
||||
#else
|
||||
int_fast64_t sec;
|
||||
#endif
|
||||
int_fast32_t nsec;
|
||||
};
|
||||
|
||||
int BOOST_THREAD_DECL xtime_get(struct xtime* xtp, int clock_type);
|
||||
inline int xtime_cmp(const xtime& xt1, const xtime& xt2)
|
||||
{
|
||||
int res = (int)(xt1.sec - xt2.sec);
|
||||
if (res == 0)
|
||||
res = (int)(xt1.nsec - xt2.nsec);
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
|
||||
#endif // BOOST_XTIME_WEK070601_HPP
|
||||
#endif // BOOST_THREAD_RS06040712_HPP
|
||||
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
<body>
|
||||
Automatic redirection failed, please go to <a href="doc/index.html">doc/index.html</a>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
// Copyright (C) 2002-2003
|
||||
// David Moore, William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/barrier.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
boost::cancellation_guard guard;
|
||||
while (gen == m_generation)
|
||||
m_cond.wait(lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
@@ -1,677 +0,0 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/condition.hpp>
|
||||
#include <boost/thread/xtime.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)
|
||||
# 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_impl::condition_impl()
|
||||
: m_gone(0), m_blocked(0), m_waiting(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);
|
||||
}
|
||||
|
||||
throw thread_resource_error();
|
||||
}
|
||||
}
|
||||
|
||||
condition_impl::~condition_impl()
|
||||
{
|
||||
int res = 0;
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(m_gate));
|
||||
assert(res);
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(m_queue));
|
||||
assert(res);
|
||||
res = CloseHandle(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
}
|
||||
|
||||
void condition_impl::notify_one()
|
||||
{
|
||||
unsigned signals = 0;
|
||||
|
||||
int res = 0;
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
|
||||
if (m_waiting != 0) // the m_gate is already closed
|
||||
{
|
||||
if (m_blocked == 0)
|
||||
{
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
return;
|
||||
}
|
||||
|
||||
++m_waiting;
|
||||
--m_blocked;
|
||||
signals = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
if (m_blocked > m_gone)
|
||||
{
|
||||
if (m_gone != 0)
|
||||
{
|
||||
m_blocked -= m_gone;
|
||||
m_gone = 0;
|
||||
}
|
||||
signals = m_waiting = 1;
|
||||
--m_blocked;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
|
||||
assert(res);
|
||||
}
|
||||
}
|
||||
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
|
||||
if (signals)
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0);
|
||||
assert(res);
|
||||
}
|
||||
}
|
||||
|
||||
void condition_impl::notify_all()
|
||||
{
|
||||
unsigned signals = 0;
|
||||
|
||||
int res = 0;
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
|
||||
if (m_waiting != 0) // the m_gate is already closed
|
||||
{
|
||||
if (m_blocked == 0)
|
||||
{
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
return;
|
||||
}
|
||||
|
||||
m_waiting += (signals = m_blocked);
|
||||
m_blocked = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
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
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
|
||||
assert(res);
|
||||
}
|
||||
}
|
||||
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
|
||||
if (signals)
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0);
|
||||
assert(res);
|
||||
}
|
||||
}
|
||||
|
||||
void condition_impl::enter_wait()
|
||||
{
|
||||
int res = 0;
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
++m_blocked;
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
|
||||
assert(res);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
was_waiting = m_waiting;
|
||||
was_gone = m_gone;
|
||||
if (was_waiting != 0)
|
||||
{
|
||||
if (--m_waiting == 0)
|
||||
{
|
||||
if (m_blocked != 0)
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1,
|
||||
0); // open m_gate
|
||||
assert(res);
|
||||
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
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
m_blocked -= m_gone;
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
|
||||
assert(res);
|
||||
m_gone = 0;
|
||||
}
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
|
||||
if (was_waiting == 1)
|
||||
{
|
||||
for (/**/ ; was_gone; --was_gone)
|
||||
{
|
||||
// better now than spurious later
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue),
|
||||
INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
}
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
|
||||
assert(res);
|
||||
}
|
||||
}
|
||||
|
||||
bool condition_impl::do_timed_wait(const xtime& xt)
|
||||
{
|
||||
bool ret = false;
|
||||
unsigned int res = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
unsigned was_waiting=0;
|
||||
unsigned was_gone=0;
|
||||
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
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)
|
||||
{
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1,
|
||||
0); // open m_gate
|
||||
assert(res);
|
||||
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
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
m_blocked -= m_gone;
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
|
||||
assert(res);
|
||||
m_gone = 0;
|
||||
}
|
||||
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
|
||||
assert(res);
|
||||
|
||||
if (was_waiting == 1)
|
||||
{
|
||||
for (/**/ ; was_gone; --was_gone)
|
||||
{
|
||||
// better now than spurious later
|
||||
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue),
|
||||
INFINITE);
|
||||
assert(res == WAIT_OBJECT_0);
|
||||
}
|
||||
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
|
||||
assert(res);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
condition_impl::condition_impl()
|
||||
{
|
||||
int res = 0;
|
||||
res = pthread_cond_init(&m_condition, 0);
|
||||
if (res != 0)
|
||||
throw thread_resource_error();
|
||||
}
|
||||
|
||||
condition_impl::~condition_impl()
|
||||
{
|
||||
int res = 0;
|
||||
res = pthread_cond_destroy(&m_condition);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void condition_impl::notify_one()
|
||||
{
|
||||
int res = 0;
|
||||
res = pthread_cond_signal(&m_condition);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void condition_impl::notify_all()
|
||||
{
|
||||
int res = 0;
|
||||
res = pthread_cond_broadcast(&m_condition);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
void condition_impl::do_wait(pthread_mutex_t* pmutex)
|
||||
{
|
||||
int res = 0;
|
||||
res = pthread_cond_wait(&m_condition, pmutex);
|
||||
assert(res == 0);
|
||||
}
|
||||
|
||||
bool condition_impl::do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex)
|
||||
{
|
||||
timespec ts;
|
||||
to_timespec(xt, ts);
|
||||
|
||||
int res = 0;
|
||||
res = pthread_cond_timedwait(&m_condition, pmutex, &ts);
|
||||
assert(res == 0 || res == ETIMEDOUT);
|
||||
|
||||
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.
|
||||
@@ -1,14 +0,0 @@
|
||||
// Copyright (C) 2001
|
||||
// Mac Murrett
|
||||
//
|
||||
// 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. Mac Murrett makes no representations
|
||||
// about the suitability of this software for any purpose. It is
|
||||
// provided "as is" without express or implied warranty.
|
||||
//
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
#define TARGET_CARBON 1
|
||||
@@ -1,72 +0,0 @@
|
||||
// Copyright (C) 2001
|
||||
// Mac Murrett
|
||||
//
|
||||
// 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. Mac Murrett makes no representations
|
||||
// about the suitability of this software for any purpose. It is
|
||||
// provided "as is" without express or implied warranty.
|
||||
//
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
#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
|
||||
@@ -1,90 +0,0 @@
|
||||
// Copyright (C) 2001
|
||||
// Mac Murrett
|
||||
//
|
||||
// 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. Mac Murrett makes no representations
|
||||
// about the suitability of this software for any purpose. It is
|
||||
// provided "as is" without express or implied warranty.
|
||||
//
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
#ifndef BOOST_DELIVERY_MAN_MJM012402_HPP
|
||||
#define BOOST_DELIVERY_MAN_MJM012402_HPP
|
||||
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
#include "package.hpp"
|
||||
|
||||
#include <Multiprocessing.h>
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace threads {
|
||||
|
||||
namespace mac {
|
||||
|
||||
namespace detail {
|
||||
|
||||
|
||||
// class delivery_man is intended to move boost::function objects from MP tasks to
|
||||
// other execution contexts (such as deferred task time or system task time).
|
||||
|
||||
class delivery_man: private noncopyable
|
||||
{
|
||||
public:
|
||||
delivery_man();
|
||||
~delivery_man();
|
||||
|
||||
public:
|
||||
template<class R>
|
||||
R deliver(function<R> &rFunctor);
|
||||
|
||||
void accept_deliveries();
|
||||
|
||||
private:
|
||||
base_package *m_pPackage;
|
||||
mutex m_oMutex;
|
||||
MPSemaphoreID m_pSemaphore;
|
||||
bool m_bPackageWaiting;
|
||||
};
|
||||
|
||||
|
||||
template<class R>
|
||||
R delivery_man::deliver(function<R> &rFunctor)
|
||||
{
|
||||
assert(at_mp());
|
||||
|
||||
// lock our mutex
|
||||
mutex::scoped_lock oLock(m_oMutex);
|
||||
|
||||
// create a package and save it
|
||||
package<R> oPackage(rFunctor);
|
||||
m_pPackage = &oPackage;
|
||||
m_bPackageWaiting = true;
|
||||
|
||||
// wait on the semaphore
|
||||
OSStatus lStatus = MPWaitOnSemaphore(m_pSemaphore, kDurationForever);
|
||||
assert(lStatus == noErr);
|
||||
|
||||
return(oPackage.return_value());
|
||||
}
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace mac
|
||||
|
||||
} // namespace threads
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_DELIVERY_MAN_MJM012402_HPP
|
||||
@@ -1,99 +0,0 @@
|
||||
// Copyright (C) 2001
|
||||
// Mac Murrett
|
||||
//
|
||||
// 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. Mac Murrett makes no representations
|
||||
// about the suitability of this software for any purpose. It is
|
||||
// provided "as is" without express or implied warranty.
|
||||
//
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
#include "dt_scheduler.hpp"
|
||||
|
||||
#include "ot_context.hpp"
|
||||
|
||||
|
||||
#include <boost/thread/detail/singleton.hpp>
|
||||
|
||||
#include <OpenTransportProtocol.h>
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace threads {
|
||||
|
||||
namespace mac {
|
||||
|
||||
namespace detail {
|
||||
|
||||
|
||||
const OTTimeout k_ulTimerTaskDelay = 1UL;
|
||||
|
||||
|
||||
dt_scheduler::dt_scheduler():
|
||||
m_bReschedule(false),
|
||||
m_uppTask(NULL),
|
||||
m_lTask(0UL)
|
||||
{
|
||||
using ::boost::detail::thread::singleton;
|
||||
|
||||
ot_context &rContext(singleton<ot_context>::instance());
|
||||
|
||||
m_uppTask = NewOTProcessUPP(task_entry);
|
||||
m_lTask = OTCreateTimerTaskInContext(m_uppTask, this, rContext.get_context());
|
||||
}
|
||||
|
||||
dt_scheduler::~dt_scheduler()
|
||||
{
|
||||
OTDestroyTimerTask(m_lTask);
|
||||
m_lTask = 0UL;
|
||||
DisposeOTProcessUPP(m_uppTask);
|
||||
m_uppTask = NULL;
|
||||
}
|
||||
|
||||
|
||||
void dt_scheduler::start_polling()
|
||||
{
|
||||
m_bReschedule = true;
|
||||
schedule_task();
|
||||
}
|
||||
|
||||
void dt_scheduler::stop_polling()
|
||||
{
|
||||
m_bReschedule = false;
|
||||
}
|
||||
|
||||
|
||||
void dt_scheduler::schedule_task()
|
||||
{
|
||||
if(m_bReschedule)
|
||||
{
|
||||
OTScheduleTimerTask(m_lTask, k_ulTimerTaskDelay);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*static*/ pascal void dt_scheduler::task_entry(void *pRefCon)
|
||||
{
|
||||
dt_scheduler *pThis = reinterpret_cast<dt_scheduler *>(pRefCon);
|
||||
assert(pThis != NULL);
|
||||
pThis->task();
|
||||
}
|
||||
|
||||
void dt_scheduler::task()
|
||||
{
|
||||
periodic_function();
|
||||
schedule_task();
|
||||
}
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace mac
|
||||
|
||||
} // namespace threads
|
||||
|
||||
} // namespace boost
|
||||
@@ -1,69 +0,0 @@
|
||||
// Copyright (C) 2001
|
||||
// Mac Murrett
|
||||
//
|
||||
// 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. Mac Murrett makes no representations
|
||||
// about the suitability of this software for any purpose. It is
|
||||
// provided "as is" without express or implied warranty.
|
||||
//
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
#ifndef BOOST_DT_SCHEDULER_MJM012402_HPP
|
||||
#define BOOST_DT_SCHEDULER_MJM012402_HPP
|
||||
|
||||
|
||||
#include "periodical.hpp"
|
||||
|
||||
#include <OpenTransport.h>
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace threads {
|
||||
|
||||
namespace mac {
|
||||
|
||||
namespace detail {
|
||||
|
||||
|
||||
// class dt_scheduler calls its pure-virtual periodic_function method periodically at
|
||||
// deferred task time. This is generally 1kHz under Mac OS 9.
|
||||
|
||||
class dt_scheduler
|
||||
{
|
||||
public:
|
||||
dt_scheduler();
|
||||
virtual ~dt_scheduler();
|
||||
|
||||
protected:
|
||||
void start_polling();
|
||||
void stop_polling();
|
||||
|
||||
private:
|
||||
virtual void periodic_function() = 0;
|
||||
|
||||
private:
|
||||
void schedule_task();
|
||||
static pascal void task_entry(void *pRefCon);
|
||||
void task();
|
||||
|
||||
private:
|
||||
bool m_bReschedule;
|
||||
OTProcessUPP m_uppTask;
|
||||
long m_lTask;
|
||||
};
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace mac
|
||||
|
||||
} // namespace threads
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_DT_SCHEDULER_MJM012402_HPP
|
||||
@@ -1,66 +0,0 @@
|
||||
// Copyright (C) 2001
|
||||
// Mac Murrett
|
||||
//
|
||||
// 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. Mac Murrett makes no representations
|
||||
// about the suitability of this software for any purpose. It is
|
||||
// provided "as is" without express or implied warranty.
|
||||
//
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
#include <Debugging.h>
|
||||
#include <Multiprocessing.h>
|
||||
|
||||
#include "execution_context.hpp"
|
||||
#include "init.hpp"
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace threads {
|
||||
|
||||
namespace mac {
|
||||
|
||||
|
||||
execution_context_t execution_context()
|
||||
{
|
||||
// make sure that MP services are available the first time through
|
||||
static bool bIgnored = detail::thread_init();
|
||||
|
||||
// first check if we're an MP task
|
||||
if(MPTaskIsPreemptive(kInvalidID))
|
||||
{
|
||||
return(k_eExecutionContextMPTask);
|
||||
}
|
||||
|
||||
#if TARGET_CARBON
|
||||
// Carbon has TaskLevel
|
||||
UInt32 ulLevel = TaskLevel();
|
||||
|
||||
if(ulLevel == 0UL)
|
||||
{
|
||||
return(k_eExecutionContextSystemTask);
|
||||
}
|
||||
|
||||
if(ulLevel & kInDeferredTaskMask)
|
||||
{
|
||||
return(k_eExecutionContextDeferredTask);
|
||||
}
|
||||
|
||||
return(k_eExecutionContextOther);
|
||||
#else
|
||||
// this can be implemented using TaskLevel if you don't mind linking against
|
||||
// DebugLib (and therefore breaking Mac OS 8.6 support), or CurrentExecutionLevel.
|
||||
# error execution_context unimplimented
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
} // namespace mac
|
||||
|
||||
} // namespace threads
|
||||
|
||||
} // namespace boost
|
||||
@@ -1,53 +0,0 @@
|
||||
// Copyright (C) 2001
|
||||
// Mac Murrett
|
||||
//
|
||||
// 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. Mac Murrett makes no representations
|
||||
// about the suitability of this software for any purpose. It is
|
||||
// provided "as is" without express or implied warranty.
|
||||
//
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
#ifndef BOOST_EXECUTION_CONTEXT_MJM012402_HPP
|
||||
#define BOOST_EXECUTION_CONTEXT_MJM012402_HPP
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace threads {
|
||||
|
||||
namespace mac {
|
||||
|
||||
|
||||
// utility functions for figuring out what context your code is executing in.
|
||||
// Bear in mind that at_mp and in_blue are the only functions guarenteed by
|
||||
// Apple to work. There is simply no way of being sure that you will not get
|
||||
// false readings about task level at interrupt time in blue.
|
||||
|
||||
typedef enum {
|
||||
k_eExecutionContextSystemTask,
|
||||
k_eExecutionContextDeferredTask,
|
||||
k_eExecutionContextMPTask,
|
||||
k_eExecutionContextOther
|
||||
} execution_context_t;
|
||||
|
||||
execution_context_t execution_context();
|
||||
|
||||
inline bool at_st()
|
||||
{ return(execution_context() == k_eExecutionContextSystemTask); }
|
||||
|
||||
inline bool at_mp()
|
||||
{ return(execution_context() == k_eExecutionContextMPTask); }
|
||||
inline bool in_blue()
|
||||
{ return(!at_mp()); }
|
||||
|
||||
|
||||
} // namespace mac
|
||||
|
||||
} // namespace threads
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_EXECUTION_CONTEXT_MJM012402_HPP
|
||||
@@ -1,64 +0,0 @@
|
||||
// Copyright (C) 2001
|
||||
// Mac Murrett
|
||||
//
|
||||
// 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. Mac Murrett makes no representations
|
||||
// about the suitability of this software for any purpose. It is
|
||||
// provided "as is" without express or implied warranty.
|
||||
//
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
#include "init.hpp"
|
||||
|
||||
#include "remote_call_manager.hpp"
|
||||
|
||||
|
||||
#include <boost/thread/detail/singleton.hpp>
|
||||
|
||||
#include <Multiprocessing.h>
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace threads {
|
||||
|
||||
namespace mac {
|
||||
|
||||
namespace detail {
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
// force these to get called by the end of static initialization time.
|
||||
static bool g_bInitialized = (thread_init() && create_singletons());
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool thread_init()
|
||||
{
|
||||
static bool bResult = MPLibraryIsLoaded();
|
||||
|
||||
return(bResult);
|
||||
}
|
||||
|
||||
bool create_singletons()
|
||||
{
|
||||
using ::boost::detail::thread::singleton;
|
||||
|
||||
singleton<remote_call_manager>::instance();
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
} // 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