mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 21:52:07 +00:00
Compare commits
110 Commits
boost-1.35
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f9292e2e3 | ||
|
|
0a88a53a33 | ||
|
|
0bce1befd9 | ||
|
|
9f354c98ab | ||
|
|
274b04bcf7 | ||
|
|
539d19468d | ||
|
|
fff6d9eddd | ||
|
|
5472ebdfde | ||
|
|
50c034f650 | ||
|
|
2a5e1a36b5 | ||
|
|
2e10da00ba | ||
|
|
af4b2d5d2a | ||
|
|
a89ec945c0 | ||
|
|
08eb9eed48 | ||
|
|
7ed1a79ab8 | ||
|
|
18974b3cb4 | ||
|
|
c973faf627 | ||
|
|
6ffcde749a | ||
|
|
42840199aa | ||
|
|
1addb6ad9b | ||
|
|
1dbdb77ed7 | ||
|
|
430ebf66f9 | ||
|
|
97562928a8 | ||
|
|
45aabefb4d | ||
|
|
b0e970863b | ||
|
|
3468fb61bc | ||
|
|
5982a97bdf | ||
|
|
ffef009696 | ||
|
|
c8f181e461 | ||
|
|
7b84d69915 | ||
|
|
bbb8efe58f | ||
|
|
63209e3c69 | ||
|
|
2272c322f9 | ||
|
|
36acb80412 | ||
|
|
b72142cef7 | ||
|
|
6dd6f51faa | ||
|
|
82630dc9bb | ||
|
|
3402aea7c1 | ||
|
|
5c4bd8e9c9 | ||
|
|
a11748d187 | ||
|
|
dc906613dc | ||
|
|
b69bdd3918 | ||
|
|
d90ef5eeef | ||
|
|
641d658a10 | ||
|
|
fef99d3db2 | ||
|
|
0fc8d8897d | ||
|
|
ad9f6244b0 | ||
|
|
59d082202c | ||
|
|
b7549a5bae | ||
|
|
f0dce755bb | ||
|
|
c1261d6df3 | ||
|
|
1fb0dac16d | ||
|
|
424d02fafa | ||
|
|
52717aaa75 | ||
|
|
335f85ad5b | ||
|
|
7da456edca | ||
|
|
f50176946d | ||
|
|
aeafcbb822 | ||
|
|
171b890972 | ||
|
|
89a9531d34 | ||
|
|
3259f681a4 | ||
|
|
17f72cf580 | ||
|
|
e03f0ed008 | ||
|
|
0804944002 | ||
|
|
8e5d5002cd | ||
|
|
008aaeaeee | ||
|
|
c1283bb731 | ||
|
|
46b1a4d1e3 | ||
|
|
ff6e0df2bc | ||
|
|
9cb9224b3c | ||
|
|
5ea5494172 | ||
|
|
e4c27981d0 | ||
|
|
fe61772d47 | ||
|
|
a437d6d7f6 | ||
|
|
c9f52098b9 | ||
|
|
a15a35a4b6 | ||
|
|
14c8137ba6 | ||
|
|
5caf9ed169 | ||
|
|
5da4a7b105 | ||
|
|
91c4af37ad | ||
|
|
5848dc2f56 | ||
|
|
efa12b1db9 | ||
|
|
58b6eba0ea | ||
|
|
f73253fcf5 | ||
|
|
3627dfc3b7 | ||
|
|
f8ebb9a127 | ||
|
|
2a0f57a8de | ||
|
|
da7278acef | ||
|
|
b17eb23f2e | ||
|
|
8e01ac5d04 | ||
|
|
5d6a1633e0 | ||
|
|
2e6f9a785e | ||
|
|
4e1acef27e | ||
|
|
73e482832d | ||
|
|
949b332337 | ||
|
|
244cfd3f01 | ||
|
|
3239fe0c22 | ||
|
|
ca10110aa7 | ||
|
|
fd4c76c7a5 | ||
|
|
60d7c84aa2 | ||
|
|
c043efa346 | ||
|
|
dab1961b5a | ||
|
|
6f94d26c50 | ||
|
|
83baf142f2 | ||
|
|
88bb39e3ce | ||
|
|
48ad27558a | ||
|
|
a0ba7f174c | ||
|
|
6e60d33181 | ||
|
|
bc69926604 | ||
|
|
d90825f7f9 |
3
build/.cvsignore
Normal file
3
build/.cvsignore
Normal file
@@ -0,0 +1,3 @@
|
||||
bin*
|
||||
*.pdb
|
||||
bjam.log
|
||||
132
build/Jamfile
Normal file
132
build/Jamfile
Normal file
@@ -0,0 +1,132 @@
|
||||
# Copyright (C) 2001-2003
|
||||
# William E. Kempf
|
||||
#
|
||||
# Permission to use, copy, modify, distribute and sell this software
|
||||
# and its documentation for any purpose is hereby granted without fee,
|
||||
# provided that the above copyright notice appear in all copies and
|
||||
# that both that copyright notice and this permission notice appear
|
||||
# in supporting documentation. William E. Kempf makes no representations
|
||||
# about the suitability of this software for any purpose.
|
||||
# It is provided "as is" without express or implied warranty.
|
||||
#
|
||||
# Boost.Threads 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"
|
||||
|
||||
# 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
|
||||
;
|
||||
|
||||
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 ##
|
||||
;
|
||||
|
||||
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 ##
|
||||
;
|
||||
|
||||
lib $(boost_thread_lib_name)
|
||||
: ## sources ##
|
||||
<template>boost_thread_lib_base
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name)
|
||||
: ## default build ##
|
||||
;
|
||||
|
||||
dll $(boost_thread_lib_name)
|
||||
: ## sources ##
|
||||
<template>thread_dll_base
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name)
|
||||
: ## default build ##
|
||||
;
|
||||
|
||||
stage bin-stage
|
||||
: <dll>$(boost_thread_lib_name)
|
||||
<lib>$(boost_thread_lib_name)
|
||||
;
|
||||
|
||||
install thread lib
|
||||
: <dll>$(boost_thread_lib_name)
|
||||
<lib>$(boost_thread_lib_name)
|
||||
;
|
||||
|
||||
if $(boost_thread_lib_settings_ptw32)
|
||||
{
|
||||
lib $(boost_thread_lib_name_ptw32)
|
||||
: ## sources ##
|
||||
<template>boost_thread_lib_base
|
||||
: ## requirements ##
|
||||
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name_ptw32)
|
||||
$(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)
|
||||
;
|
||||
}
|
||||
}
|
||||
208
build/Jamfile.v2
208
build/Jamfile.v2
@@ -1,208 +1,12 @@
|
||||
# $Id$
|
||||
# Copyright 2006-2007 Roland Schwarz.
|
||||
# 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)
|
||||
|
||||
#########################################################################
|
||||
# The boost threading library can be built on top of different API's
|
||||
# Currently this is the win32 API and the pthreads API.
|
||||
# Pthread is native on unix variants.
|
||||
# To get pthread on windows you need the pthread win32 library
|
||||
# http://sourceware.org/pthreads-win32 which is available under LGPL.
|
||||
#
|
||||
# You need to provide the include path and lib path in the variables
|
||||
# PTW32_INCLUDE and PTW32_LIB respectively. You can specify these
|
||||
# paths in site-config.jam, user-config.jam or in the environment.
|
||||
# A new feature is provided to request a specific API:
|
||||
# <threadapi>win32 and <threadapi)pthread.
|
||||
#
|
||||
# The naming of the resulting libraries is mostly the same for the
|
||||
# variant native to the build platform, i.e.
|
||||
# boost_thread and the boost specific tagging.
|
||||
# For the library variant that is not native on the build platform
|
||||
# an additional tag is applied:
|
||||
# boost_thread_pthread for the pthread variant on windows, and
|
||||
# boost_thread_win32 for the win32 variant (likely when built on cygwin).
|
||||
#
|
||||
# To request the pthread variant on windows, from boost root you would
|
||||
# say e.g:
|
||||
# bjam msvc-8.0 --with-thread install threadapi=pthread
|
||||
#########################################################################
|
||||
|
||||
import os ;
|
||||
import feature ;
|
||||
import indirect ;
|
||||
import path ;
|
||||
# Declare the uses system library
|
||||
lib pthread : : <name>pthread ;
|
||||
|
||||
project boost/thread
|
||||
: source-location ../src
|
||||
: requirements <threading>multi
|
||||
<link>static:<define>BOOST_THREAD_BUILD_LIB=1
|
||||
<link>shared:<define>BOOST_THREAD_BUILD_DLL=1
|
||||
-<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
|
||||
<tag>@$(__name__).tag
|
||||
: default-build <threading>multi
|
||||
: source-location ../src
|
||||
: usage-requirements <library>pthread
|
||||
;
|
||||
|
||||
local rule default_threadapi ( )
|
||||
{
|
||||
local api = pthread ;
|
||||
if [ os.name ] = "NT" { api = win32 ; }
|
||||
return $(api) ;
|
||||
}
|
||||
CPP_SOURCES = condition mutex recursive_mutex thread tss xtime once exceptions ;
|
||||
|
||||
feature.feature threadapi : pthread win32 : propagated ;
|
||||
feature.set-default threadapi : [ default_threadapi ] ;
|
||||
|
||||
rule tag ( name : type ? : property-set )
|
||||
{
|
||||
local result = $(name) ;
|
||||
|
||||
if $(type) in STATIC_LIB SHARED_LIB IMPORT_LIB
|
||||
{
|
||||
local api = [ $(property-set).get <threadapi> ] ;
|
||||
|
||||
# non native api gets additional tag
|
||||
if $(api) != [ default_threadapi ] {
|
||||
result = $(result)_$(api) ;
|
||||
}
|
||||
}
|
||||
|
||||
# forward to the boost tagging rule
|
||||
return [ indirect.call $(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
|
||||
$(result) : $(type) : $(property-set) ] ;
|
||||
}
|
||||
|
||||
rule win32_pthread_paths ( properties * )
|
||||
{
|
||||
local result ;
|
||||
local PTW32_INCLUDE ;
|
||||
local PTW32_LIB ;
|
||||
PTW32_INCLUDE = [ modules.peek : PTW32_INCLUDE ] ;
|
||||
PTW32_LIB = [ modules.peek : PTW32_LIB ] ;
|
||||
PTW32_INCLUDE ?= [ modules.peek user-config : PTW32_INCLUDE ] ;
|
||||
PTW32_LIB ?= [ modules.peek user-config : PTW32_LIB ] ;
|
||||
PTW32_INCLUDE ?= [ modules.peek site-config : PTW32_INCLUDE ] ;
|
||||
PTW32_LIB ?= [ modules.peek site-config : PTW32_LIB ] ;
|
||||
|
||||
if ! ( $(PTW32_INCLUDE) && $(PTW32_LIB) )
|
||||
{
|
||||
if ! $(.notified)
|
||||
{
|
||||
echo "************************************************************" ;
|
||||
echo "Trying to build Boost.Thread with pthread support." ;
|
||||
echo "If you need pthread you should specify the paths." ;
|
||||
echo "You can specify them in site-config.jam, user-config.jam" ;
|
||||
echo "or in the environment." ;
|
||||
echo "For example:" ;
|
||||
echo "PTW32_INCLUDE=C:\\Program Files\\ptw32\\Pre-built2\\include" ;
|
||||
echo "PTW32_LIB=C:\\Program Files\\ptw32\\Pre-built2\\lib" ;
|
||||
echo "************************************************************" ;
|
||||
.notified = true ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
local include_path = [ path.make $(PTW32_INCLUDE) ] ;
|
||||
local lib_path = [ path.make $(PTW32_LIB) ] ;
|
||||
local libname = pthread ;
|
||||
if <toolset>msvc in $(properties)
|
||||
{
|
||||
libname = $(libname)VC2.lib ;
|
||||
}
|
||||
if <toolset>gcc in $(properties)
|
||||
{
|
||||
libname = lib$(libname)GC2.a ;
|
||||
}
|
||||
lib_path = [ path.glob $(lib_path) : $(libname) ] ;
|
||||
if ! $(lib_path)
|
||||
{
|
||||
if ! $(.notified)
|
||||
{
|
||||
echo "************************************************************" ;
|
||||
echo "Trying to build Boost.Thread with pthread support." ;
|
||||
echo "But the library" $(libname) "could not be found in path" ;
|
||||
echo $(PTW32_LIB) ;
|
||||
echo "************************************************************" ;
|
||||
.notified = true ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result += <include>$(include_path) ;
|
||||
result += <library>$(lib_path) ;
|
||||
}
|
||||
}
|
||||
return $(result) ;
|
||||
}
|
||||
|
||||
rule usage-requirements ( properties * )
|
||||
{
|
||||
local result ;
|
||||
if <threadapi>pthread in $(properties)
|
||||
{
|
||||
result += <define>BOOST_THREAD_POSIX ;
|
||||
if <target-os>windows in $(properties)
|
||||
{
|
||||
result += [ win32_pthread_paths $(properties) ] ;
|
||||
# TODO: What is for static linking? Is the <library> also needed
|
||||
# in that case?
|
||||
}
|
||||
}
|
||||
return $(result) ;
|
||||
}
|
||||
|
||||
rule requirements ( properties * )
|
||||
{
|
||||
local result ;
|
||||
|
||||
if <threadapi>pthread in $(properties)
|
||||
{
|
||||
result += <define>BOOST_THREAD_POSIX ;
|
||||
if <target-os>windows in $(properties)
|
||||
{
|
||||
local paths = [ win32_pthread_paths $(properties) ] ;
|
||||
if $(paths)
|
||||
{
|
||||
result += $(paths) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = <build>no ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $(result) ;
|
||||
}
|
||||
|
||||
alias thread_sources
|
||||
: ## win32 sources ##
|
||||
win32/thread.cpp
|
||||
win32/exceptions.cpp
|
||||
win32/tss_dll.cpp
|
||||
win32/tss_pe.cpp
|
||||
: ## requirements ##
|
||||
<threadapi>win32
|
||||
;
|
||||
|
||||
alias thread_sources
|
||||
: ## pthread sources ##
|
||||
pthread/thread.cpp
|
||||
pthread/exceptions.cpp
|
||||
pthread/once.cpp
|
||||
: ## requirements ##
|
||||
<threadapi>pthread
|
||||
;
|
||||
|
||||
explicit thread_sources ;
|
||||
|
||||
lib boost_thread
|
||||
: thread_sources
|
||||
: <conditional>@requirements
|
||||
:
|
||||
: <link>shared:<define>BOOST_THREAD_USE_DLL=1
|
||||
<link>static:<define>BOOST_THREAD_USE_LIB=1
|
||||
<conditional>@usage-requirements
|
||||
;
|
||||
lib boost_thread : $(CPP_SOURCES).cpp ;
|
||||
|
||||
45
build/threads.jam
Normal file
45
build/threads.jam
Normal file
@@ -0,0 +1,45 @@
|
||||
# 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.
|
||||
|
||||
# Do some OS-specific setup
|
||||
{
|
||||
#thread library name
|
||||
boost_thread_lib_name = boost_thread ;
|
||||
|
||||
#thread library name with "pthreads-win32" library
|
||||
boost_thread_lib_name_ptw32 = boost_thread_ptw32 ;
|
||||
|
||||
if $(NT)
|
||||
{
|
||||
if $(PTW32_DIR)
|
||||
{
|
||||
if $(PTW32_LIB)
|
||||
{
|
||||
boost_thread_lib_settings_ptw32 =
|
||||
<define>BOOST_HAS_PTHREADS
|
||||
<define>PtW32NoCatchWarn
|
||||
<include>$(PTW32_DIR)/pre-built/include
|
||||
<library-file>$(PTW32_DIR)/pre-built/lib/$(PTW32_LIB)
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template thread_base
|
||||
: ## sources ##
|
||||
: ## requirements ##
|
||||
<sysinclude>$(BOOST_ROOT)
|
||||
<threading>multi
|
||||
<borland><*><cxxflags>-w-8004
|
||||
<borland><*><cxxflags>-w-8057
|
||||
: ## default build ##
|
||||
;
|
||||
}
|
||||
BIN
build/threads.mcp
Normal file
BIN
build/threads.mcp
Normal file
Binary file not shown.
3
doc/.cvsignore
Normal file
3
doc/.cvsignore
Normal file
@@ -0,0 +1,3 @@
|
||||
bin
|
||||
html
|
||||
catalog.xml
|
||||
@@ -1,11 +1,5 @@
|
||||
# Copyright (C) 2001-2003
|
||||
# William E. Kempf
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
project boost/doc ;
|
||||
import boostbook : boostbook ;
|
||||
|
||||
import toolset ;
|
||||
toolset.using doxygen ;
|
||||
|
||||
boostbook thread : thread.xml ;
|
||||
boostbook doc : thread.xml ;
|
||||
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<section id="thread.acknowledgements"
|
||||
last-revision="$Date$">
|
||||
<title>Acknowledgements</title>
|
||||
<para>William E. Kempf was the architect, designer, and implementor of
|
||||
&Boost.Thread;.</para>
|
||||
&Boost.Threads;.</para>
|
||||
<para>Mac OS Carbon implementation written by Mac Murrett.</para>
|
||||
<para>Dave Moore provided initial submissions and further comments on the
|
||||
<code>barrier</code>
|
||||
@@ -32,7 +28,7 @@ last-revision="$Date$">
|
||||
on the design), Paul Mclachlan, Thomas Matelich and Iain Hanson (for help
|
||||
in trying to get the build to work on other platforms), and Kevin S. Van
|
||||
Horn (for several updates/corrections to the documentation).</para>
|
||||
<para>Mike Glassford finished changes to &Boost.Thread; that were begun
|
||||
<para>Mike Glassford finished changes to &Boost.Threads; that were begun
|
||||
by William Kempf and moved them into the main CVS branch.
|
||||
He also addressed a number of issues that were brought up on the Boost
|
||||
developer's mailing list and provided some additions and changes to the
|
||||
@@ -42,7 +38,7 @@ last-revision="$Date$">
|
||||
Mike Glassford finished William Kempf's conversion of the documentation to
|
||||
BoostBook format and added a number of new sections.</para>
|
||||
<para>Discussions on the boost.org mailing list were essential in the
|
||||
development of &Boost.Thread;
|
||||
development of &Boost.Threads;
|
||||
. As of August 1, 2001, participants included Alan Griffiths, Albrecht
|
||||
Fritzsche, Aleksey Gurtovoy, Alexander Terekhov, Andrew Green, Andy Sawyer,
|
||||
Asger Alstrup Nielsen, Beman Dawes, Bill Klein, Bill Rutiser, Bill Wade,
|
||||
@@ -63,11 +59,6 @@ last-revision="$Date$">
|
||||
Steve Cleary, Steven Kirk, Thomas Holenstein, Thomas Matelich, Trevor
|
||||
Perrin, Valentin Bonnard, Vesa Karvonen, Wayne Miller, and William
|
||||
Kempf.</para>
|
||||
<para>
|
||||
As of February 2006 Anthony Williams and Roland Schwarz took over maintainance
|
||||
and further development of the library after it has been in an orphaned state
|
||||
for a rather long period of time.
|
||||
</para>
|
||||
<para>Apologies for anyone inadvertently missed.</para>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<header name="boost/thread/barrier.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
@@ -36,9 +32,9 @@
|
||||
and reset the barrier. This functionality allows the same set of N threads to re-use
|
||||
a barrier object to synchronize their execution at multiple points during their
|
||||
execution.</para>
|
||||
<para>See <xref linkend="thread.glossary"/> for definitions of thread
|
||||
states <link linkend="thread.glossary.thread-state">blocked</link>
|
||||
and <link linkend="thread.glossary.thread-state">ready</link>.
|
||||
<para>See <xref linkend="threads.glossary"/> for definitions of thread
|
||||
states <link linkend="threads.glossary.thread-state">blocked</link>
|
||||
and <link linkend="threads.glossary.thread-state">ready</link>.
|
||||
Note that "waiting" is a synonym for blocked.</para>
|
||||
</description>
|
||||
|
||||
@@ -79,4 +75,4 @@
|
||||
</method-group>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
</header>
|
||||
@@ -1,18 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<bibliography id="thread.bibliography"
|
||||
<bibliography id="threads.bibliography"
|
||||
last-revision="$Date$">
|
||||
<title>Bibliography</title>
|
||||
<biblioentry id="thread.bib.AndrewsSchneider83">
|
||||
<abbrev id="thread.bib.AndrewsSchneider83.abbrev">AndrewsSchnieder83</abbrev>
|
||||
<biblioentry id="threads.bib.AndrewsSchneider83">
|
||||
<abbrev id="threads.bib.AndrewsSchneider83.abbrev">AndrewsSchnieder83</abbrev>
|
||||
<biblioset relation="journal">
|
||||
<title>ACM Computing Surveys</title>
|
||||
<volumenum>Vol. 15</volumenum>
|
||||
@@ -42,23 +38,23 @@ last-revision="$Date$">
|
||||
Expressions, Message Passing, and Remote Procedure Call in addition to the
|
||||
basics</para>
|
||||
</biblioentry>
|
||||
<biblioentry id="thread.bib.Boost">
|
||||
<abbrev id="thread.bib.Boost.abbrev">Boost</abbrev>
|
||||
<biblioentry id="threads.bib.Boost">
|
||||
<abbrev id="threads.bib.Boost.abbrev">Boost</abbrev>
|
||||
<bibliomisc>The <emphasis>Boost</emphasis> world wide web site.
|
||||
<ulink url="http:/www.boost.org">http://www.boost.org</ulink></bibliomisc>
|
||||
<para>&Boost.Thread; is one of many Boost libraries. The Boost web
|
||||
<para>&Boost.Threads; is one of many Boost libraries. The Boost web
|
||||
site includes a great deal of documentation and general information which
|
||||
applies to all Boost libraries. Current copies of the libraries including
|
||||
documentation and test programs may be downloaded from the web
|
||||
site.</para>
|
||||
</biblioentry>
|
||||
<biblioentry id="thread.bib.Hansen73">
|
||||
<abbrev id="thread.bib.Hansen73.abbrev">Hansen73</abbrev>
|
||||
<biblioentry id="threads.bib.Hansen73">
|
||||
<abbrev id="threads.bib.Hansen73.abbrev">Hansen73</abbrev>
|
||||
<biblioset relation="journal">
|
||||
<title>ACM Computing Surveys</title>
|
||||
<volumenum>Vol. 5</volumenum>
|
||||
<issuenum>No. 4</issuenum>
|
||||
<date>December, 1973</date>
|
||||
<date>December, 1983</date>
|
||||
</biblioset>
|
||||
<biblioset relation="article">
|
||||
<author>0-201-63392-2
|
||||
@@ -78,8 +74,8 @@ last-revision="$Date$">
|
||||
Brinch Hansen was years ahead of others in recognizing pattern concepts
|
||||
applied to software, too.</para>
|
||||
</biblioentry>
|
||||
<biblioentry id="thread.bib.Butenhof97">
|
||||
<abbrev id="thread.bib.Butenhof97.abbrev">Butenhof97</abbrev>
|
||||
<biblioentry id="threads.bib.Butenhof97">
|
||||
<abbrev id="threads.bib.Butenhof97.abbrev">Butenhof97</abbrev>
|
||||
<title>
|
||||
<ulink url="http://cseng.aw.com/book/0,3828,0201633922,00.html"
|
||||
>Programming with POSIX Threads </ulink>
|
||||
@@ -96,8 +92,8 @@ last-revision="$Date$">
|
||||
them. Many of the insights given apply to all multithreaded programming, not
|
||||
just POSIX Threads</para>
|
||||
</biblioentry>
|
||||
<biblioentry id="thread.bib.Hoare74">
|
||||
<abbrev id="thread.bib.Hoare74.abbrev">Hoare74</abbrev>
|
||||
<biblioentry id="threads.bib.Hoare74">
|
||||
<abbrev id="threads.bib.Hoare74.abbrev">Hoare74</abbrev>
|
||||
<biblioset relation="journal">
|
||||
<title>Communications of the ACM</title>
|
||||
<volumenum>Vol. 17</volumenum>
|
||||
@@ -119,8 +115,8 @@ last-revision="$Date$">
|
||||
multithreading patterns. This is one of the most often referenced papers in
|
||||
all of computer science, and with good reason.</para>
|
||||
</biblioentry>
|
||||
<biblioentry id="thread.bib.ISO98">
|
||||
<abbrev id="thread.bib.ISO98.abbrev">ISO98</abbrev>
|
||||
<biblioentry id="threads.bib.ISO98">
|
||||
<abbrev id="threads.bib.ISO98.abbrev">ISO98</abbrev>
|
||||
<title>
|
||||
<ulink url="http://www.ansi.org">Programming Language C++</ulink>
|
||||
</title>
|
||||
@@ -129,8 +125,8 @@ last-revision="$Date$">
|
||||
<para>This is the official C++ Standards document. Available from the ANSI
|
||||
(American National Standards Institute) Electronic Standards Store.</para>
|
||||
</biblioentry>
|
||||
<biblioentry id="thread.bib.McDowellHelmbold89">
|
||||
<abbrev id="thread.bib.McDowellHelmbold89.abbrev">McDowellHelmbold89</abbrev>
|
||||
<biblioentry id="threads.bib.McDowellHelmbold89">
|
||||
<abbrev id="threads.bib.McDowellHelmbold89.abbrev">McDowellHelmbold89</abbrev>
|
||||
<biblioset relation="journal">
|
||||
<title>Communications of the ACM</title>
|
||||
<volumenum>Vol. 21</volumenum>
|
||||
@@ -157,8 +153,8 @@ last-revision="$Date$">
|
||||
<para>Identifies many of the unique failure modes and debugging difficulties
|
||||
associated with concurrent programs.</para>
|
||||
</biblioentry>
|
||||
<biblioentry id="thread.bib.SchmidtPyarali">
|
||||
<abbrev id="thread.bib.SchmidtPyarali.abbrev">SchmidtPyarali</abbrev>
|
||||
<biblioentry id="threads.bib.SchmidtPyarali">
|
||||
<abbrev id="threads.bib.SchmidtPyarali.abbrev">SchmidtPyarali</abbrev>
|
||||
<title>
|
||||
<ulink url="http://www.cs.wustl.edu/~schmidt/win32-cv-1.html8"
|
||||
>Strategies for Implementing POSIX Condition Variables on Win32</ulink>
|
||||
@@ -176,14 +172,14 @@ last-revision="$Date$">
|
||||
</authorgroup>
|
||||
<orgname>Department of Computer Science, Washington University, St. Louis,
|
||||
Missouri</orgname>
|
||||
<para>Rationale for understanding &Boost.Thread; condition
|
||||
<para>Rationale for understanding &Boost.Threads; condition
|
||||
variables. Note that Alexander Terekhov found some bugs in the
|
||||
implementation given in this article, so pthreads-win32 and &Boost.Thread;
|
||||
implementation given in this article, so pthreads-win32 and &Boost.Threads;
|
||||
are even more complicated yet.</para>
|
||||
</biblioentry>
|
||||
<biblioentry id="thread.bib.SchmidtStalRohnertBuschmann">
|
||||
<biblioentry id="threads.bib.SchmidtStalRohnertBuschmann">
|
||||
<abbrev
|
||||
id="thread.bib.SchmidtStalRohnertBuschmann.abbrev">SchmidtStalRohnertBuschmann</abbrev>
|
||||
id="threads.bib.SchmidtStalRohnertBuschmann.abbrev">SchmidtStalRohnertBuschmann</abbrev>
|
||||
<title>
|
||||
<ulink
|
||||
url="http://www.wiley.com/Corporate/Website/Objects/Products/0,9049,104671,00.html"
|
||||
@@ -214,11 +210,11 @@ last-revision="$Date$">
|
||||
<copyright><year>2000</year></copyright>
|
||||
<para>This is a very good explanation of how to apply several patterns
|
||||
useful for concurrent programming. Among the patterns documented is the
|
||||
Monitor Pattern mentioned frequently in the &Boost.Thread;
|
||||
Monitor Pattern mentioned frequently in the &Boost.Threads;
|
||||
documentation.</para>
|
||||
</biblioentry>
|
||||
<biblioentry id="thread.bib.Stroustrup">
|
||||
<abbrev id="thread.bib.Stroustrup.abbrev">Stroustrup</abbrev>
|
||||
<biblioentry id="threads.bib.Stroustrup">
|
||||
<abbrev id="threads.bib.Stroustrup.abbrev">Stroustrup</abbrev>
|
||||
<title>
|
||||
<ulink url="http://cseng.aw.com/book/0,3828,0201700735,00.html"
|
||||
>The C++ Programming Language</ulink>
|
||||
|
||||
159
doc/build.xml
159
doc/build.xml
@@ -1,137 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Copyright (c) 2007 Roland Schwarz
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<section id="thread.build" last-revision="$Date$">
|
||||
<title>Build</title>
|
||||
<para>
|
||||
How you build the &Boost.Thread; libraries, and how you build your own applications
|
||||
How you build the &Boost.Threads; libraries, and how you build your own applications
|
||||
that use those libraries, are some of the most frequently asked questions. Build
|
||||
processes are difficult to deal with in a portable manner. That's one reason
|
||||
why &Boost.Thread; makes use of &Boost.Build;.
|
||||
why &Boost.Threads; makes use of &Boost.Build;.
|
||||
In general you should refer to the documentation for &Boost.Build;.
|
||||
This document will only supply you with some simple usage examples for how to
|
||||
use <emphasis>bjam</emphasis> to build and test &Boost.Thread;. In addition, this document
|
||||
use <emphasis>bjam</emphasis> to build and test &Boost.Threads;. In addition, this document
|
||||
will try to explain the build requirements so that users may create their own
|
||||
build processes (for instance, create an IDE specific project), both for building
|
||||
and testing &Boost.Thread;, as well as for building their own projects using
|
||||
&Boost.Thread;.
|
||||
and testing &Boost.Threads;, as well as for building their own projects using
|
||||
&Boost.Threads;.
|
||||
</para>
|
||||
<section id="thread.build.building">
|
||||
<title>Building the &Boost.Thread; Libraries</title>
|
||||
<para>
|
||||
Building the &Boost.Thread; Library depends on how you intend to use it. You have several options:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
Using as a <link linkend="thread.build.precompiled">precompiled</link> library, possibly
|
||||
with auto-linking, or for use from within an IDE.
|
||||
</listitem>
|
||||
<listitem>
|
||||
Use from a <link linkend="thread.build.bjam">&Boost.Build;</link> project.
|
||||
</listitem>
|
||||
<listitem>
|
||||
Using in <link linkend="thread.build.source">source</link> form.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<section id="thread.build.precompiled">
|
||||
<title>Precompiled</title>
|
||||
<para>
|
||||
Using the &Boost.Thread; library in precompiled form is the way to go if you want to
|
||||
install the library to a standard place, from where your linker is able to resolve code
|
||||
in binary form. You also will want this option if compile time is a concern. Multiple
|
||||
variants are available, for different toolsets and build variants (debug/release).
|
||||
The library files are named <emphasis>{lead}boost_thread{build-specific-tags}.{extension}</emphasis>,
|
||||
where the build-specific-tags indicate the toolset used to build the library, whether it's
|
||||
a debug or release build, what version of &Boost; was used, etc.; and the lead and extension
|
||||
are the appropriate extensions for a dynamic link library or static library for the platform
|
||||
for which &Boost.Thread; is being built.
|
||||
For instance, a debug build of the dynamic library built for Win32 with VC++ 7.1 using Boost 1.34 would
|
||||
be named <emphasis>boost_thread-vc71-mt-gd-1_34.dll</emphasis>.
|
||||
More information on this should be available from the &Boost.Build; documentation.
|
||||
</para>
|
||||
<para>
|
||||
Building should be possible with the default configuration. If you are running into problems,
|
||||
it might be wise to adjust your local settings of &Boost.Build; though. Typically you will
|
||||
need to get your user-config.jam file to reflect your environment, i.e. used toolsets. Please
|
||||
refer to the &Boost.Build; documentation to learn how to do this.
|
||||
</para>
|
||||
<para>
|
||||
To create the libraries you need to open a command shell and change to the
|
||||
<emphasis>boost_root</emphasis> directory. From there you give the command
|
||||
<programlisting>bjam --toolset=<emphasis>mytoolset</emphasis> stage --with-thread</programlisting>
|
||||
Replace <emphasis>mytoolset</emphasis> with the name of your toolset, e.g. msvc-7.1 .
|
||||
This will compile and put the libraries into the <emphasis>stage</emphasis> directory which is just below the
|
||||
<emphasis>boost_root</emphasis> directory. &Boost.Build; by default will generate static and
|
||||
dynamic variants for debug and release.
|
||||
</para>
|
||||
<note>
|
||||
Invoking the above command without the --with-thread switch &Boost.Build; will build all of
|
||||
the Boost distribution, including &Boost.Thread;.
|
||||
</note>
|
||||
<para>
|
||||
The next step is to copy your libraries to a place where your linker is able to pick them up.
|
||||
It is also quite possible to leave them in the stage directory and instruct your IDE to take them
|
||||
from there.
|
||||
</para>
|
||||
<para>
|
||||
In your IDE you then need to add <emphasis>boost_root</emphasis>/boost to the paths where the compiler
|
||||
expects to find files to be included. For toolsets that support <emphasis>auto-linking</emphasis>
|
||||
it is not necessary to explicitly specify the name of the library to link against, it is sufficient
|
||||
to specify the path of the stage directory. Typically this is true on Windows. For gcc you need
|
||||
to specify the exact library name (including all the tags). Please don't forget that threading
|
||||
support must be turned on to be able to use the library. You should be able now to build your
|
||||
project from the IDE.
|
||||
</para>
|
||||
</section>
|
||||
<section id="thread.build.bjam">
|
||||
<title>&Boost.Build; Project</title>
|
||||
<para>
|
||||
If you have decided to use &Boost.Build; as a build environment for your application, you simply
|
||||
need to add a single line to your <emphasis>Jamroot</emphasis> file:
|
||||
<programlisting>use-project /boost : {path-to-boost-root} ;</programlisting>
|
||||
where <emphasis>{path-to-boost-root}</emphasis> needs to be replaced with the location of
|
||||
your copy of the boost tree.
|
||||
Later when you specify a component that needs to link against &Boost.Thread; you specify this
|
||||
as e.g.:
|
||||
<programlisting>exe myapp : {myappsources} /boost//thread ;</programlisting>
|
||||
and you are done.
|
||||
</para>
|
||||
</section>
|
||||
<section id="thread.build.source">
|
||||
<title>Source Form</title>
|
||||
<para>
|
||||
Of course it is also possible to use the &Boost.Thread; library in source form.
|
||||
First you need to specify the <emphasis>boost_root</emphasis>/boost directory as
|
||||
a path where your compiler expects to find files to include. It is not easy
|
||||
to isolate the &Boost.Thread; include files from the rest of the boost
|
||||
library though. You would also need to isolate every include file that the thread
|
||||
library depends on. Next you need to copy the files from
|
||||
<emphasis>boost_root</emphasis>/libs/thread/src to your project and instruct your
|
||||
build system to compile them together with your project. Please look into the
|
||||
<emphasis>Jamfile</emphasis> in <emphasis>boost_root</emphasis>/libs/thread/build
|
||||
to find out which compiler options and defines you will need to get a clean compile.
|
||||
Using the boost library in this way is the least recommended, and should only be
|
||||
considered if avoiding dependency on &Boost.Build; is a requirement. Even if so
|
||||
it might be a better option to use the library in it's precompiled form.
|
||||
Precompiled downloads are available from the boost consulting web site, or as
|
||||
part of most linux distributions.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
<section id="thread.build.testing">
|
||||
<title>Testing the &Boost.Thread; Libraries</title>
|
||||
<title>Building the &Boost.Threads; Libraries</title>
|
||||
<para>
|
||||
To test the &Boost.Thread; libraries using &Boost.Build;, simply change to the
|
||||
directory <emphasis>boost_root</emphasis>/libs/thread/test and execute the command:
|
||||
<programlisting>bjam --toolset=<emphasis>mytoolset</emphasis> test</programlisting>
|
||||
To build the &Boost.Threads; libraries using &Boost.Build;, simply change to the
|
||||
directory <emphasis>boost_root</emphasis>/libs/thread/build and execute the command:
|
||||
<programlisting>bjam -sTOOLS=<emphasis>toolset</emphasis></programlisting>
|
||||
This will create the debug and the release builds of the &Boost.Threads; library.
|
||||
<note>Invoking the above command in <emphasis>boost_root</emphasis> will build all of
|
||||
the Boost distribution, including &Boost.Threads;.</note>
|
||||
</para>
|
||||
<para>
|
||||
The Jamfile supplied with &Boost.Threads; produces a dynamic link library named
|
||||
<emphasis>boost_thread{build-specific-tags}.{extension}</emphasis>, where the build-specific
|
||||
tags indicate the toolset used to build the library, whether it's a debug or release
|
||||
build, what version of Boost was used, etc.; and the extension is the appropriate extension
|
||||
for a dynamic link library for the platform for which &Boost.Threads; is being built.
|
||||
For instance, a debug library built for Win32 with VC++ 7.1 using Boost 1.31 would
|
||||
be named <emphasis>boost_thread-vc71-mt-gd-1_31.dll</emphasis>.
|
||||
</para>
|
||||
<para>
|
||||
The source files that are used to create the &Boost.Threads; library
|
||||
are all of the *.cpp files found in <emphasis>boost_root</emphasis>/libs/thread/src.
|
||||
These need to be built with the compiler's and linker's multi-threading support enabled.
|
||||
If you want to create your own build solution you'll have to follow these same
|
||||
guidelines. One of the most frequently reported problems when trying to do this
|
||||
occurs from not enabling the compiler's and linker's support for multi-threading.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
<section id="thread.build.testing">
|
||||
<title>Testing the &Boost.Threads; Libraries</title>
|
||||
<para>
|
||||
To test the &Boost.Threads; libraries using &Boost.Build;, simply change to the
|
||||
directory <emphasis>boost_root</emphasis>/libs/thread/test and execute the command:
|
||||
<programlisting>bjam -sTOOLS=<emphasis>toolset</emphasis> test</programlisting>
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
584
doc/concepts.xml
584
doc/concepts.xml
File diff suppressed because it is too large
Load Diff
@@ -1,13 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<header name="boost/thread/condition.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
@@ -25,12 +21,12 @@
|
||||
|
||||
<description>
|
||||
<para>A <classname>condition</classname> object is always used in
|
||||
conjunction with a <link linkend="thread.concepts.mutexes">mutex</link>
|
||||
conjunction with a <link linkend="threads.concepts.mutexes">mutex</link>
|
||||
object (an object whose type is a model of a <link
|
||||
linkend="thread.concepts.Mutex">Mutex</link> or one of its
|
||||
linkend="threads.concepts.Mutex">Mutex</link> or one of its
|
||||
refinements). The mutex object must be locked prior to waiting on the
|
||||
condition, which is verified by passing a lock object (an object whose
|
||||
type is a model of <link linkend="thread.concepts.Lock">Lock</link> or
|
||||
type is a model of <link linkend="threads.concepts.Lock">Lock</link> or
|
||||
one of its refinements) to the <classname>condition</classname> object's
|
||||
wait functions. Upon blocking on the <classname>condition</classname>
|
||||
object, the thread unlocks the mutex object. When the thread returns
|
||||
@@ -43,8 +39,8 @@
|
||||
&cite.SchmidtStalRohnertBuschmann; and &cite.Hoare74;). Monitors are one
|
||||
of the most important patterns for creating reliable multithreaded
|
||||
programs.</para>
|
||||
<para>See <xref linkend="thread.glossary"/> for definitions of <link
|
||||
linkend="thread.glossary.thread-state">thread states</link>
|
||||
<para>See <xref linkend="threads.glossary"/> for definitions of <link
|
||||
linkend="threads.glossary.thread-state">thread states</link>
|
||||
blocked and ready. Note that "waiting" is a synonym for blocked.</para>
|
||||
</description>
|
||||
|
||||
@@ -91,10 +87,10 @@
|
||||
</parameter>
|
||||
|
||||
<requires><simpara><code>ScopedLock</code> meets the <link
|
||||
linkend="thread.concepts.ScopedLock">ScopedLock</link>
|
||||
linkend="threads.concepts.ScopedLock">ScopedLock</link>
|
||||
requirements.</simpara></requires>
|
||||
<effects><simpara>Releases the lock on the <link
|
||||
linkend="thread.concepts.mutexes">mutex object</link>
|
||||
linkend="threads.concepts.mutexes">mutex object</link>
|
||||
associated with <code>lock</code>, blocks the current thread of execution
|
||||
until readied by a call to <code>this->notify_one()</code>
|
||||
or<code> this->notify_all()</code>, and then reacquires the
|
||||
@@ -120,7 +116,7 @@
|
||||
</parameter>
|
||||
|
||||
<requires><simpara><code>ScopedLock</code> meets the <link
|
||||
linkend="thread.concepts.ScopedLock">ScopedLock</link>
|
||||
linkend="threads.concepts.ScopedLock">ScopedLock</link>
|
||||
requirements and the return from <code>pred()</code> is
|
||||
convertible to <code>bool</code>.</simpara></requires>
|
||||
<effects><simpara>As if: <code>while (!pred())
|
||||
@@ -145,10 +141,10 @@
|
||||
</parameter>
|
||||
|
||||
<requires><simpara><code>ScopedLock</code> meets the <link
|
||||
linkend="thread.concepts.ScopedLock">ScopedLock</link>
|
||||
linkend="threads.concepts.ScopedLock">ScopedLock</link>
|
||||
requirements.</simpara></requires>
|
||||
<effects><simpara>Releases the lock on the <link
|
||||
linkend="thread.concepts.mutexes">mutex object</link>
|
||||
linkend="threads.concepts.mutexes">mutex object</link>
|
||||
associated with <code>lock</code>, blocks the current thread of execution
|
||||
until readied by a call to <code>this->notify_one()</code>
|
||||
or<code> this->notify_all()</code>, or until time <code>xt</code>
|
||||
@@ -171,16 +167,12 @@
|
||||
<paramtype>ScopedLock&</paramtype>
|
||||
</parameter>
|
||||
|
||||
<parameter name="xt">
|
||||
<paramtype>const <classname>boost::xtime</classname>&</paramtype>
|
||||
</parameter>
|
||||
|
||||
<parameter name="pred">
|
||||
<paramtype>Pred</paramtype>
|
||||
</parameter>
|
||||
|
||||
<requires><simpara><code>ScopedLock</code> meets the <link
|
||||
linkend="thread.concepts.ScopedLock">ScopedLock</link>
|
||||
linkend="threads.concepts.ScopedLock">ScopedLock</link>
|
||||
requirements and the return from <code>pred()</code> is
|
||||
convertible to <code>bool</code>.</simpara></requires>
|
||||
<effects><simpara>As if: <code>while (!pred()) { if (!timed_wait(lock,
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<section id="thread.configuration" last-revision="$Date$">
|
||||
<title>Configuration</title>
|
||||
<para>&Boost.Thread; uses several configuration macros in <boost/config.hpp>,
|
||||
<para>&Boost.Threads; uses several configuration macros in <boost/config.hpp>,
|
||||
as well as configuration macros meant to be supplied by the application. These
|
||||
macros are documented here.
|
||||
</para>
|
||||
<section id="thread.configuration.public">
|
||||
<title>Library Defined Public Macros</title>
|
||||
<para>
|
||||
These macros are defined by &Boost.Thread; but are expected to be used
|
||||
These macros are defined by &Boost.Threads; but are expected to be used
|
||||
by application code.
|
||||
</para>
|
||||
<informaltable>
|
||||
@@ -33,9 +29,9 @@
|
||||
<entry>BOOST_HAS_THREADS</entry>
|
||||
<entry>
|
||||
Indicates that threading support is available. This means both that there
|
||||
is a platform specific implementation for &Boost.Thread; and that
|
||||
is a platform specific implementation for &Boost.Threads; and that
|
||||
threading support has been enabled in a platform specific manner. For instance,
|
||||
on the Win32 platform there's an implementation for &Boost.Thread;
|
||||
on the Win32 platform there's an implementation for &Boost.Threads;
|
||||
but unless the program is compiled against one of the multithreading runtimes
|
||||
(often determined by the compiler predefining the macro _MT) the BOOST_HAS_THREADS
|
||||
macro remains undefined.
|
||||
@@ -48,7 +44,7 @@
|
||||
<section id="thread.configuration.implementation">
|
||||
<title>Library Defined Implementation Macros</title>
|
||||
<para>
|
||||
These macros are defined by &Boost.Thread; and are implementation details
|
||||
These macros are defined by &Boost.Threads; and are implementation details
|
||||
of interest only to implementors.
|
||||
</para>
|
||||
<informaltable>
|
||||
@@ -64,14 +60,14 @@
|
||||
<entry>BOOST_HAS_WINTHREADS</entry>
|
||||
<entry>
|
||||
Indicates that the platform has the Microsoft Win32 threading libraries,
|
||||
and that they should be used to implement &Boost.Thread;.
|
||||
and that they should be used to implement &Boost.Threads;.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>BOOST_HAS_PTHREADS</entry>
|
||||
<entry>
|
||||
Indicates that the platform has the POSIX pthreads libraries, and that
|
||||
they should be used to implement &Boost.Thread;.
|
||||
they should be used to implement &Boost.Threads;.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
@@ -93,4 +89,4 @@
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
@@ -1,14 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<section id="thread.design" last-revision="$Date$">
|
||||
<section id="threads.design" last-revision="$Date$">
|
||||
<title>Design</title>
|
||||
<para>With client/server and three-tier architectures becoming common place
|
||||
in today's world, it's becoming increasingly important for programs to be
|
||||
@@ -19,18 +15,18 @@
|
||||
Further, these APIs are almost universally C APIs and fail to take
|
||||
advantage of C++'s strengths, or to address concepts unique to C++, such as
|
||||
exceptions.</para>
|
||||
<para>The &Boost.Thread; library is an attempt to define a portable interface
|
||||
<para>The &Boost.Threads; library is an attempt to define a portable interface
|
||||
for writing parallel processes in C++.</para>
|
||||
<section id="thread.design.goals">
|
||||
<section id="threads.design.goals">
|
||||
<title>Goals</title>
|
||||
<para>The &Boost.Thread; library has several goals that should help to set
|
||||
<para>The &Boost.Threads; library has several goals that should help to set
|
||||
it apart from other solutions. These goals are listed in order of precedence
|
||||
with full descriptions below.
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>Portability</term>
|
||||
<listitem>
|
||||
<para>&Boost.Thread; was designed to be highly portable. The goal is
|
||||
<para>&Boost.Threads; was designed to be highly portable. The goal is
|
||||
for the interface to be easily implemented on any platform that
|
||||
supports threads, and possibly even on platforms without native thread
|
||||
support.</para>
|
||||
@@ -39,8 +35,8 @@
|
||||
<varlistentry>
|
||||
<term>Safety</term>
|
||||
<listitem>
|
||||
<para>&Boost.Thread; was designed to be as safe as possible. Writing
|
||||
<link linkend="thread.glossary.thread-safe">thread-safe</link>
|
||||
<para>&Boost.Threads; was designed to be as safe as possible. Writing
|
||||
<link linkend="threads.glossary.thread-safe">thread-safe</link>
|
||||
code is very difficult and successful libraries must strive to
|
||||
insulate the programmer from dangerous constructs as much as
|
||||
possible. This is accomplished in several ways:
|
||||
@@ -49,14 +45,14 @@
|
||||
<para>C++ language features are used to make correct usage easy
|
||||
(if possible) and error-prone usage impossible or at least more
|
||||
difficult. For example, see the <link
|
||||
linkend="thread.concepts.Mutex">Mutex</link> and <link
|
||||
linkend="thread.concepts.Lock">Lock</link> designs, and note
|
||||
linkend="threads.concepts.Mutex">Mutex</link> and <link
|
||||
linkend="threads.concepts.Lock">Lock</link> designs, and note
|
||||
how they interact.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Certain traditional concurrent programming features are
|
||||
considered so error-prone that they are not provided at all. For
|
||||
example, see <xref linkend="thread.rationale.events" />.</para>
|
||||
example, see <xref linkend="threads.rationale.events" />.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Dangerous features, or features which may be misused, are
|
||||
@@ -69,9 +65,9 @@
|
||||
<varlistentry>
|
||||
<term>Flexibility</term>
|
||||
<listitem>
|
||||
<para>&Boost.Thread; was designed to be flexible. This goal is often
|
||||
<para>&Boost.Threads; was designed to be flexible. This goal is often
|
||||
at odds with <emphasis>safety</emphasis>. When functionality might be
|
||||
compromised by the desire to keep the interface safe, &Boost.Thread;
|
||||
compromised by the desire to keep the interface safe, &Boost.Threads;
|
||||
has been designed to provide the functionality, but to make it's use
|
||||
prohibitive for general use. In other words, the interfaces have been
|
||||
designed such that it's usually obvious when something is unsafe, and
|
||||
@@ -81,11 +77,11 @@
|
||||
<varlistentry>
|
||||
<term>Efficiency</term>
|
||||
<listitem>
|
||||
<para>&Boost.Thread; was designed to be as efficient as
|
||||
<para>&Boost.Threads; was designed to be as efficient as
|
||||
possible. When building a library on top of another library there is
|
||||
always a danger that the result will be so much slower than the
|
||||
"native" API that programmers are inclined to ignore the higher level
|
||||
API. &Boost.Thread; was designed to minimize the chances of this
|
||||
API. &Boost.Threads; was designed to minimize the chances of this
|
||||
occurring. The interfaces have been crafted to allow an implementation
|
||||
the greatest chance of being as efficient as possible. This goal is
|
||||
often at odds with the goal for <emphasis>safety</emphasis>. Every
|
||||
@@ -98,18 +94,18 @@
|
||||
</section>
|
||||
<section>
|
||||
<title>Iterative Phases</title>
|
||||
<para>Another goal of &Boost.Thread; was to take a dynamic, iterative
|
||||
<para>Another goal of &Boost.Threads; was to take a dynamic, iterative
|
||||
approach in its development. The computing industry is still exploring the
|
||||
concepts of parallel programming. Most thread libraries supply only simple
|
||||
primitive concepts for thread synchronization. These concepts are very
|
||||
simple, but it is very difficult to use them safely or to provide formal
|
||||
proofs for constructs built on top of them. There has been a lot of research
|
||||
into other concepts, such as in "Communicating Sequential Processes."
|
||||
&Boost.Thread; was designed in iterative steps, with each step providing
|
||||
&Boost.Threads; was designed in iterative steps, with each step providing
|
||||
the building blocks necessary for the next step and giving the researcher
|
||||
the tools necessary to explore new concepts in a portable manner.</para>
|
||||
<para>Given the goal of following a dynamic, iterative approach
|
||||
&Boost.Thread; shall go through several growth cycles. Each phase in its
|
||||
&Boost.Threads; shall go through several growth cycles. Each phase in its
|
||||
development shall be roughly documented here.</para>
|
||||
</section>
|
||||
<section>
|
||||
@@ -123,10 +119,10 @@
|
||||
much help to a programmer who wants to use the library in his multithreaded
|
||||
application. So there's a very great need for portable primitives that will
|
||||
allow the library developer to create <link
|
||||
linkend="thread.glossary.thread-safe">thread-safe</link>
|
||||
linkend="threads.glossary.thread-safe">thread-safe</link>
|
||||
implementations. This need far out weighs the need for portable methods to
|
||||
create and manage threads.</para>
|
||||
<para>Because of this need, the first phase of &Boost.Thread; focuses
|
||||
<para>Because of this need, the first phase of &Boost.Threads; focuses
|
||||
solely on providing portable primitive concepts for thread
|
||||
synchronization. Types provided in this phase include the
|
||||
<classname>boost::mutex</classname>,
|
||||
@@ -139,16 +135,16 @@
|
||||
synchronization primitives, though there are others that will be added in
|
||||
later phases.</para>
|
||||
</section>
|
||||
<section id="thread.design.phase2">
|
||||
<section id="threads.design.phase2">
|
||||
<title>Phase 2, Thread Management and Thread Specific Storage</title>
|
||||
<para>This phase addresses the creation and management of threads and
|
||||
provides a mechanism for thread specific storage (data associated with a
|
||||
thread instance). Thread management is a tricky issue in C++, so this
|
||||
phase addresses only the basic needs of multithreaded program. Later
|
||||
phases are likely to add additional functionality in this area. This
|
||||
phase of &Boost.Thread; adds the <classname>boost::thread</classname> and
|
||||
phase of &Boost.Threads; adds the <classname>boost::thread</classname> and
|
||||
<classname>boost::thread_specific_ptr</classname> types. With these
|
||||
additions the &Boost.Thread; library can be considered minimal but
|
||||
additions the &Boost.Threads; library can be considered minimal but
|
||||
complete.</para>
|
||||
</section>
|
||||
<section>
|
||||
|
||||
@@ -1,31 +1,26 @@
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<!ENTITY Boost "<emphasis role='bold'>Boost</emphasis>">
|
||||
<!ENTITY Boost.Thread "<emphasis role='bold'>Boost.Thread</emphasis>">
|
||||
<!ENTITY Boost.Threads "<emphasis role='bold'>Boost.Threads</emphasis>">
|
||||
<!ENTITY Boost.Build "<emphasis role='bold'>Boost.Build</emphasis>">
|
||||
<!ENTITY cite.AndrewsSchneider83 "<citation><xref
|
||||
linkend='thread.bib.AndrewsSchneider83'
|
||||
endterm='thread.bib.AndrewsSchneider83.abbrev'/></citation>">
|
||||
<!ENTITY cite.Boost "<citation><xref linkend='thread.bib.Boost'
|
||||
endterm='thread.bib.Boost.abbrev'/></citation>">
|
||||
<!ENTITY cite.Hansen73 "<citation><xref linkend='thread.bib.Hansen73'
|
||||
endterm='thread.bib.Hansen73.abbrev'/></citation>">
|
||||
<!ENTITY cite.Butenhof97 "<citation><xref linkend='thread.bib.Butenhof97'
|
||||
endterm='thread.bib.Butenhof97.abbrev'/></citation>">
|
||||
<!ENTITY cite.Hoare74 "<citation><xref linkend='thread.bib.Hoare74'
|
||||
endterm='thread.bib.Hoare74.abbrev'/></citation>">
|
||||
<!ENTITY cite.ISO98 "<citation><xref linkend='thread.bib.ISO98'
|
||||
endterm='thread.bib.ISO98.abbrev'/></citation>">
|
||||
linkend='threads.bib.AndrewsSchneider83'
|
||||
endterm='threads.bib.AndrewsSchneider83.abbrev'/></citation>">
|
||||
<!ENTITY cite.Boost "<citation><xref linkend='threads.bib.Boost'
|
||||
endterm='threads.bib.Boost.abbrev'/></citation>">
|
||||
<!ENTITY cite.Hansen73 "<citation><xref linkend='threads.bib.Hansen73'
|
||||
endterm='threads.bib.Hansen73.abbrev'/></citation>">
|
||||
<!ENTITY cite.Butenhof97 "<citation><xref linkend='threads.bib.Butenhof97'
|
||||
endterm='threads.bib.Butenhof97.abbrev'/></citation>">
|
||||
<!ENTITY cite.Hoare74 "<citation><xref linkend='threads.bib.Hoare74'
|
||||
endterm='threads.bib.Hoare74.abbrev'/></citation>">
|
||||
<!ENTITY cite.ISO98 "<citation><xref linkend='threads.bib.ISO98'
|
||||
endterm='threads.bib.ISO98.abbrev'/></citation>">
|
||||
<!ENTITY cite.McDowellHelmbold89 "<citation><xref
|
||||
linkend='thread.bib.McDowellHelmbold89'
|
||||
endterm='thread.bib.McDowellHelmbold89.abbrev'/></citation>">
|
||||
linkend='threads.bib.McDowellHelmbold89'
|
||||
endterm='threads.bib.McDowellHelmbold89.abbrev'/></citation>">
|
||||
<!ENTITY cite.SchmidtPyarali "<citation><xref
|
||||
linkend='thread.bib.SchmidtPyarali'
|
||||
endterm='thread.bib.SchmidtPyarali.abbrev'/></citation>">
|
||||
linkend='threads.bib.SchmidtPyarali'
|
||||
endterm='threads.bib.SchmidtPyarali.abbrev'/></citation>">
|
||||
<!ENTITY cite.SchmidtStalRohnertBuschmann "<citation><xref
|
||||
linkend='thread.bib.SchmidtStalRohnertBuschmann'
|
||||
endterm='thread.bib.SchmidtStalRohnertBuschmann.abbrev'/></citation>">
|
||||
<!ENTITY cite.Stroustrup "<citation><xref linkend='thread.bib.Stroustrup'
|
||||
endterm='thread.bib.Stroustrup.abbrev'/></citation>">
|
||||
linkend='threads.bib.SchmidtStalRohnertBuschmann'
|
||||
endterm='threads.bib.SchmidtStalRohnertBuschmann.abbrev'/></citation>">
|
||||
<!ENTITY cite.Stroustrup "<citation><xref linkend='threads.bib.Stroustrup'
|
||||
endterm='threads.bib.Stroustrup.abbrev'/></citation>">
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<header name="boost/thread/exceptions.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
@@ -38,7 +34,7 @@
|
||||
<purpose>
|
||||
<simpara>The <classname>thread_resource_error</classname> class
|
||||
defines an exception type that is thrown by constructors in the
|
||||
&Boost.Thread; library when thread-related resources can not be
|
||||
&Boost.Threads; library when thread-related resources can not be
|
||||
acquired.</simpara>
|
||||
</purpose>
|
||||
|
||||
@@ -59,4 +55,4 @@
|
||||
</constructor>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
</header>
|
||||
65
doc/faq.xml
65
doc/faq.xml
@@ -1,49 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<section id="thread.faq" last-revision="$Date$">
|
||||
<section id="threads.faq" last-revision="$Date$">
|
||||
<title>Frequently Asked Questions</title>
|
||||
<qandaset>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Are lock objects <link
|
||||
linkend="thread.glossary.thread-safe">thread safe</link>?</para>
|
||||
linkend="threads.glossary.thread-safe">thread safe</link>?</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para><emphasis role="bold">No!</emphasis> Lock objects are not meant to
|
||||
be shared between threads. They are meant to be short-lived objects
|
||||
created on automatic storage within a code block. Any other usage is
|
||||
just likely to lead to errors and won't really be of actual benefit anyway.
|
||||
Share <link linkend="thread.concepts.mutexes">Mutexes</link>, not
|
||||
Share <link linkend="threads.concepts.mutexes">Mutexes</link>, not
|
||||
Locks. For more information see the <link
|
||||
linkend="thread.rationale.locks">rationale</link> behind the
|
||||
linkend="threads.rationale.locks">rationale</link> behind the
|
||||
design for lock objects.</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Why was &Boost.Thread; modeled after (specific library
|
||||
<para>Why was &Boost.Threads; modeled after (specific library
|
||||
name)?</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>It wasn't. &Boost.Thread; was designed from scratch. Extensive
|
||||
<para>It wasn't. &Boost.Threads; was designed from scratch. Extensive
|
||||
design discussions involved numerous people representing a wide range of
|
||||
experience across many platforms. To ensure portability, the initial
|
||||
implements were done in parallel using POSIX Threads and the Win32
|
||||
threading API. But the &Boost.Thread; design is very much in the spirit
|
||||
threading API. But the &Boost.Threads; design is very much in the spirit
|
||||
of C++, and thus doesn't model such C based APIs.</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Why wasn't &Boost.Thread; modeled after (specific library
|
||||
<para>Why wasn't &Boost.Threads; modeled after (specific library
|
||||
name)?</para>
|
||||
</question>
|
||||
<answer>
|
||||
@@ -58,12 +54,12 @@
|
||||
</qandaentry>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Why do <link linkend="thread.concepts.mutexes">Mutexes</link>
|
||||
<para>Why do <link linkend="threads.concepts.mutexes">Mutexes</link>
|
||||
have noncopyable semantics?</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>To ensure that <link
|
||||
linkend="thread.glossary.deadlock">deadlocks</link> don't occur. The
|
||||
linkend="threads.glossary.deadlock">deadlocks</link> don't occur. The
|
||||
only logical form of copy would be to use some sort of shallow copy
|
||||
semantics in which multiple mutex objects could refer to the same mutex
|
||||
state. This means that if ObjA has a mutex object as part of its state
|
||||
@@ -77,20 +73,20 @@
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>How can you prevent <link
|
||||
linkend="thread.glossary.deadlock">deadlock</link> from occurring when
|
||||
linkend="threads.glossary.deadlock">deadlock</link> from occurring when
|
||||
a thread must lock multiple mutexes?</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>Always lock them in the same order. One easy way of doing this is
|
||||
to use each mutex's address to determine the order in which they are
|
||||
locked. A future &Boost.Thread; concept may wrap this pattern up in a
|
||||
locked. A future &Boost.Threads; concept may wrap this pattern up in a
|
||||
reusable class.</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Don't noncopyable <link
|
||||
linkend="thread.concepts.mutexes">Mutex</link> semantics mean that a
|
||||
linkend="threads.concepts.mutexes">Mutex</link> semantics mean that a
|
||||
class with a mutex member will be noncopyable as well?</para>
|
||||
</question>
|
||||
<answer>
|
||||
@@ -98,7 +94,7 @@
|
||||
copy constructor and assignment operator, so they will have to be coded
|
||||
explicitly. This is a <emphasis role="bold">good thing</emphasis>,
|
||||
however, since the compiler generated operations would not be <link
|
||||
linkend="thread.glossary.thread-safe">thread-safe</link>. The following
|
||||
linkend="threads.glossary.thread-safe">thread-safe</link>. The following
|
||||
is a simple example of a class with copyable semantics and internal
|
||||
synchronization through a mutex member.</para>
|
||||
<programlisting>
|
||||
@@ -148,7 +144,7 @@ private:
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>How can you lock a <link
|
||||
linkend="thread.concepts.mutexes">Mutex</link> member in a const member
|
||||
linkend="threads.concepts.mutexes">Mutex</link> member in a const member
|
||||
function, in order to implement the Monitor Pattern?</para>
|
||||
</question>
|
||||
<answer>
|
||||
@@ -169,8 +165,8 @@ private:
|
||||
</question>
|
||||
<answer>
|
||||
<para>Condition variables result in user code much less prone to <link
|
||||
linkend="thread.glossary.race-condition">race conditions</link> than
|
||||
event variables. See <xref linkend="thread.rationale.events" />
|
||||
linkend="threads.glossary.race-condition">race conditions</link> than
|
||||
event variables. See <xref linkend="threads.rationale.events" />
|
||||
for analysis. Also see &cite.Hoare74; and &cite.SchmidtStalRohnertBuschmann;.
|
||||
</para>
|
||||
</answer>
|
||||
@@ -181,7 +177,7 @@ private:
|
||||
</question>
|
||||
<answer>
|
||||
<para>There's a valid need for thread termination, so at some point
|
||||
&Boost.Thread; probably will include it, but only after we can find a
|
||||
&Boost.Threads; probably will include it, but only after we can find a
|
||||
truly safe (and portable) mechanism for this concept.</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
@@ -210,26 +206,5 @@ private:
|
||||
condition variable.</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>Why doesn't the thread's ctor take at least a void* to pass any
|
||||
information along with the function? All other threading libs support
|
||||
that and it makes Boost.Threads inferiour. </para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>There is no need, because Boost.Threads are superiour! First
|
||||
thing is that its ctor doesn't take a function but a functor. That
|
||||
means that you can pass an object with an overloaded operator() and
|
||||
include additional data as members in that object. Beware though that
|
||||
this object is copied, use boost::ref to prevent that. Secondly, even
|
||||
a boost::function<void (void)> can carry parameters, you only have to
|
||||
use boost::bind() to create it from any function and bind its
|
||||
parameters.</para>
|
||||
<para>That is also why Boost.Threads are superiour, because they
|
||||
don't require you to pass a type-unsafe void pointer. Rather, you can
|
||||
use the flexible Boost.Functions to create a thread entry out of
|
||||
anything that can be called.</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
</qandaset>
|
||||
</section>
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<glossary id="thread.glossary" last-revision="$Date$">
|
||||
<glossary id="threads.glossary" last-revision="$Date$">
|
||||
<title>Glossary</title>
|
||||
<para>Definitions are given in terms of the C++ Standard
|
||||
&cite.ISO98;. References to the standard are in the form [1.2.3/4], which
|
||||
@@ -16,9 +12,9 @@
|
||||
"/".</para>
|
||||
<para>Because the definitions are written in something akin to "standardese",
|
||||
they can be difficult to understand. The intent isn't to confuse, but rather
|
||||
to clarify the additional requirements &Boost.Thread; places on a C++
|
||||
to clarify the additional requirements &Boost.Threads; places on a C++
|
||||
implementation as defined by the C++ Standard.</para>
|
||||
<glossentry id="thread.glossary.thread">
|
||||
<glossentry id="threads.glossary.thread">
|
||||
<glossterm>Thread</glossterm>
|
||||
<glossdef>
|
||||
<para>Thread is short for "thread of execution". A thread of execution is
|
||||
@@ -54,13 +50,13 @@
|
||||
</itemizedlist>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="thread.glossary.thread-safe">
|
||||
<glossentry id="threads.glossary.thread-safe">
|
||||
<glossterm>Thread-safe</glossterm>
|
||||
<glossdef>
|
||||
<para>A program is thread-safe if it has no <link
|
||||
linkend="thread.glossary.race-condition">race conditions</link>, does
|
||||
not <link linkend="thread.glossary.deadlock">deadlock</link>, and has
|
||||
no <link linkend="thread.glossary.priority-failure">priority
|
||||
linkend="threads.glossary.race-condition">race conditions</link>, does
|
||||
not <link linkend="threads.glossary.deadlock">deadlock</link>, and has
|
||||
no <link linkend="threads.glossary.priority-failure">priority
|
||||
failures</link>.</para>
|
||||
<para>Note that thread-safety does not necessarily imply efficiency, and
|
||||
than while some thread-safety violations can be determined statically at
|
||||
@@ -68,7 +64,7 @@
|
||||
runtime.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="thread.glossary.thread-state">
|
||||
<glossentry id="threads.glossary.thread-state">
|
||||
<glossterm>Thread State</glossterm>
|
||||
<glossdef>
|
||||
<para>During the lifetime of a thread, it shall be in one of the following
|
||||
@@ -170,7 +166,7 @@
|
||||
above table.]</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="thread.glossary.race-condition">
|
||||
<glossentry id="threads.glossary.race-condition">
|
||||
<glossterm>Race Condition</glossterm>
|
||||
<glossdef>
|
||||
<para>A race condition is what occurs when multiple threads read from and write
|
||||
@@ -179,10 +175,10 @@
|
||||
pattern which isn't even a valid value for the data type. A race condition
|
||||
results in undefined behavior [1.3.12].</para>
|
||||
<para>Race conditions can be prevented by serializing memory access using
|
||||
the tools provided by &Boost.Thread;.</para>
|
||||
the tools provided by &Boost.Threads;.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="thread.glossary.deadlock">
|
||||
<glossentry id="threads.glossary.deadlock">
|
||||
<glossterm>Deadlock</glossterm>
|
||||
<glossdef>
|
||||
<para>Deadlock is an execution state where for some set of threads, each
|
||||
@@ -191,14 +187,14 @@
|
||||
become ready again.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="thread.glossary.starvation">
|
||||
<glossentry id="threads.glossary.starvation">
|
||||
<glossterm>Starvation</glossterm>
|
||||
<glossdef>
|
||||
<para>The condition in which a thread is not making sufficient progress in
|
||||
its work during a given time interval.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="thread.glossary.priority-failure">
|
||||
<glossentry id="threads.glossary.priority-failure">
|
||||
<glossterm>Priority Failure</glossterm>
|
||||
<glossdef>
|
||||
<para>A priority failure (such as priority inversion or infinite overtaking)
|
||||
@@ -206,10 +202,10 @@
|
||||
performed in time to be useful.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="thread.glossary.undefined-behavior">
|
||||
<glossentry id="threads.glossary.undefined-behavior">
|
||||
<glossterm>Undefined Behavior</glossterm>
|
||||
<glossdef>
|
||||
<para>The result of certain operations in &Boost.Thread; is undefined;
|
||||
<para>The result of certain operations in &Boost.Threads; is undefined;
|
||||
this means that those operations can invoke almost any behavior when
|
||||
they are executed.</para>
|
||||
|
||||
@@ -224,7 +220,7 @@
|
||||
programming error.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
<glossentry id="thread.glossary.memory-visibility">
|
||||
<glossentry id="threads.glossary.memory-visibility">
|
||||
<glossterm>Memory Visibility</glossterm>
|
||||
<glossdef>
|
||||
<para>An address [1.7] shall always point to the same memory byte,
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<section id="thread.implementation_notes" last-revision="$Date$">
|
||||
<section id="threads.implementation_notes" last-revision="$Date$">
|
||||
<title>Implementation Notes</title>
|
||||
<section id="thread.implementation_notes.win32">
|
||||
<section id="threads.implementation_notes.win32">
|
||||
<title>Win32</title>
|
||||
<para>
|
||||
In the current Win32 implementation, creating a boost::thread object
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
<!-- Copyright (c) 2002-2003 Beman Dawes, William E. Kempf.
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=../../../doc/html/thread.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to <a href="../../../doc/html/thread.html">../../../doc/html/thread.html</a>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,42 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<header name="boost/thread/mutex.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
<class name="mutex">
|
||||
<purpose>
|
||||
<para>The <classname>mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.Mutex">Mutex</link> concept.</para>
|
||||
<link linkend="threads.concepts.Mutex">Mutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.Mutex">Mutex</link> concept.
|
||||
<link linkend="threads.concepts.Mutex">Mutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
<link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking mechanics.</para>
|
||||
|
||||
<para>For classes that model related mutex concepts, see
|
||||
<classname>try_mutex</classname> and <classname>timed_mutex</classname>.</para>
|
||||
|
||||
<para>For <link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
|
||||
<para>For <link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
|
||||
locking mechanics, see <classname>recursive_mutex</classname>,
|
||||
<classname>recursive_try_mutex</classname>, and <classname>recursive_timed_mutex</classname>.
|
||||
</para>
|
||||
|
||||
<para>The <classname>mutex</classname> class supplies the following typedef,
|
||||
which <link linkend="thread.concepts.lock-models">models</link>
|
||||
which <link linkend="threads.concepts.lock-models">models</link>
|
||||
the specified locking strategy:
|
||||
|
||||
<informaltable>
|
||||
<title>Supported Lock Types</title>
|
||||
<tgroup cols="2" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
@@ -47,7 +44,7 @@
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -55,7 +52,7 @@
|
||||
</para>
|
||||
|
||||
<para>The <classname>mutex</classname> class uses an
|
||||
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
<link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking strategy, so attempts to recursively lock a <classname>mutex</classname>
|
||||
object or attempts to unlock one by threads that don't own a lock on it result in
|
||||
<emphasis role="bold">undefined behavior</emphasis>.
|
||||
@@ -65,10 +62,10 @@
|
||||
<code>NDEBUG</code> is not defined.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="thread.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Thread;, <classname>mutex</classname> leaves the
|
||||
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
<link linkend="threads.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Threads;, <classname>mutex</classname> leaves the
|
||||
<link linkend="threads.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
Programmers should make no assumptions about the order in which
|
||||
waiting threads acquire a lock.</para>
|
||||
</description>
|
||||
@@ -104,29 +101,30 @@
|
||||
<class name="try_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>try_mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.TryMutex">TryMutex</link> concept.</para>
|
||||
<link linkend="threads.concepts.TryMutex">TryMutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>try_mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.TryMutex">TryMutex</link> concept.
|
||||
<link linkend="threads.concepts.TryMutex">TryMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
<link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking mechanics.</para>
|
||||
|
||||
<para>For classes that model related mutex concepts, see
|
||||
<classname>mutex</classname> and <classname>timed_mutex</classname>.</para>
|
||||
|
||||
<para>For <link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
|
||||
<para>For <link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
|
||||
locking mechanics, see <classname>recursive_mutex</classname>,
|
||||
<classname>recursive_try_mutex</classname>, and <classname>recursive_timed_mutex</classname>.
|
||||
</para>
|
||||
|
||||
<para>The <classname>try_mutex</classname> class supplies the following typedefs,
|
||||
which <link linkend="thread.concepts.lock-models">model</link>
|
||||
which <link linkend="threads.concepts.lock-models">model</link>
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
<title>Supported Lock Types</title>
|
||||
<tgroup cols="2" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
@@ -137,11 +135,11 @@
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -149,7 +147,7 @@
|
||||
</para>
|
||||
|
||||
<para>The <classname>try_mutex</classname> class uses an
|
||||
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
<link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking strategy, so attempts to recursively lock a <classname>try_mutex</classname>
|
||||
object or attempts to unlock one by threads that don't own a lock on it result in
|
||||
<emphasis role="bold">undefined behavior</emphasis>.
|
||||
@@ -159,10 +157,10 @@
|
||||
<code>NDEBUG</code> is not defined.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="thread.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Thread;, <classname>try_mutex</classname> leaves the
|
||||
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
<link linkend="threads.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Threads;, <classname>try_mutex</classname> leaves the
|
||||
<link linkend="threads.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
Programmers should make no assumptions about the order in which
|
||||
waiting threads acquire a lock.</para>
|
||||
</description>
|
||||
@@ -203,29 +201,30 @@
|
||||
<class name="timed_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>timed_mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.TimedMutex">TimedMutex</link> concept.</para>
|
||||
<link linkend="threads.concepts.TimedMutex">TimedMutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>timed_mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.TimedMutex">TimedMutex</link> concept.
|
||||
<link linkend="threads.concepts.TimedMutex">TimedMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
<link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking mechanics.</para>
|
||||
|
||||
<para>For classes that model related mutex concepts, see
|
||||
<classname>mutex</classname> and <classname>try_mutex</classname>.</para>
|
||||
|
||||
<para>For <link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
|
||||
<para>For <link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
|
||||
locking mechanics, see <classname>recursive_mutex</classname>,
|
||||
<classname>recursive_try_mutex</classname>, and <classname>recursive_timed_mutex</classname>.
|
||||
</para>
|
||||
|
||||
<para>The <classname>timed_mutex</classname> class supplies the following typedefs,
|
||||
which <link linkend="thread.concepts.lock-models">model</link>
|
||||
which <link linkend="threads.concepts.lock-models">model</link>
|
||||
the specified locking strategies:
|
||||
|
||||
<informaltable>
|
||||
<title>Supported Lock Types</title>
|
||||
<tgroup cols="2" align="left">
|
||||
<thead>
|
||||
<row>
|
||||
@@ -236,15 +235,15 @@
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -252,7 +251,7 @@
|
||||
</para>
|
||||
|
||||
<para>The <classname>timed_mutex</classname> class uses an
|
||||
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
<link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking strategy, so attempts to recursively lock a <classname>timed_mutex</classname>
|
||||
object or attempts to unlock one by threads that don't own a lock on it result in
|
||||
<emphasis role="bold">undefined behavior</emphasis>.
|
||||
@@ -262,10 +261,10 @@
|
||||
<code>NDEBUG</code> is not defined.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="thread.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Thread;, <classname>timed_mutex</classname> leaves the
|
||||
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
<link linkend="threads.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Threads;, <classname>timed_mutex</classname> leaves the
|
||||
<link linkend="threads.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
Programmers should make no assumptions about the order in which
|
||||
waiting threads acquire a lock.</para>
|
||||
</description>
|
||||
@@ -306,4 +305,4 @@
|
||||
</destructor>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
</header>
|
||||
@@ -1,13 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<header name="boost/thread/once.hpp"
|
||||
last-revision="$Date$">
|
||||
<macro name="BOOST_ONCE_INIT">
|
||||
@@ -15,7 +11,7 @@
|
||||
<code>once_flag</code> type (statically initialized to
|
||||
<macroname>BOOST_ONCE_INIT</macroname>) can be used to run a
|
||||
routine exactly once. This can be used to initialize data in a
|
||||
<link linkend="thread.glossary.thread-safe">thread-safe</link>
|
||||
<link linkend="threads.glossary.thread-safe">thread-safe</link>
|
||||
manner.</purpose>
|
||||
|
||||
<description>The implementation-defined macro
|
||||
@@ -31,7 +27,7 @@
|
||||
<code>once_flag</code> type (statically initialized to
|
||||
<macroname>BOOST_ONCE_INIT</macroname>) can be used to run a
|
||||
routine exactly once. This can be used to initialize data in a
|
||||
<link linkend="thread.glossary.thread-safe">thread-safe</link>
|
||||
<link linkend="threads.glossary.thread-safe">thread-safe</link>
|
||||
manner.</purpose>
|
||||
|
||||
<description>The implementation-defined type <code>once_flag</code>
|
||||
@@ -49,7 +45,7 @@
|
||||
<code>once_flag</code> type (statically initialized to
|
||||
<macroname>BOOST_ONCE_INIT</macroname>) can be used to run a
|
||||
routine exactly once. This can be used to initialize data in a
|
||||
<link linkend="thread.glossary.thread-safe">thread-safe</link>
|
||||
<link linkend="threads.glossary.thread-safe">thread-safe</link>
|
||||
manner.</purpose>
|
||||
|
||||
<description>
|
||||
@@ -65,24 +61,26 @@ void init()
|
||||
|
||||
void thread_proc()
|
||||
{
|
||||
boost::call_once(once, &init);
|
||||
boost::call_once(&init, once);
|
||||
}</programlisting>
|
||||
</para></description>
|
||||
|
||||
<parameter name="func">
|
||||
<paramtype>void (*func)()</paramtype>
|
||||
</parameter>
|
||||
|
||||
<parameter name="flag">
|
||||
<paramtype>once_flag&</paramtype>
|
||||
</parameter>
|
||||
|
||||
<parameter name="func">
|
||||
<paramtype>Function func</paramtype>
|
||||
</parameter>
|
||||
|
||||
<requires>The function <code>func</code> shall not throw
|
||||
exceptions.</requires>
|
||||
|
||||
<effects>As if (in an atomic fashion):
|
||||
<code>if (flag == BOOST_ONCE_INIT) func();</code>. If <code>func()</code> throws an exception, it shall be as if this
|
||||
thread never invoked <code>call_once</code></effects>
|
||||
<code>if (flag == BOOST_ONCE_INIT) func();</code></effects>
|
||||
|
||||
<postconditions><code>flag != BOOST_ONCE_INIT</code> unless <code>func()</code> throws an exception.
|
||||
<postconditions><code>flag != BOOST_ONCE_INIT</code>
|
||||
</postconditions>
|
||||
</function>
|
||||
</namespace>
|
||||
</header>
|
||||
</header>
|
||||
@@ -1,23 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<section id="thread.overview" last-revision="$Date$">
|
||||
<section id="threads.overview" last-revision="$Date$">
|
||||
<title>Overview</title>
|
||||
<section id="thread.introduction">
|
||||
<section id="threads.introduction">
|
||||
<title>Introduction</title>
|
||||
<para>&Boost.Thread; allows C++ programs to execute as multiple,
|
||||
<para>&Boost.Threads; allows C++ programs to execute as multiple,
|
||||
asynchronous, independent threads-of-execution. Each thread has its own
|
||||
machine state including program instruction counter and registers. Programs
|
||||
which execute as multiple threads are called multithreaded programs to
|
||||
distinguish them from traditional single-threaded programs. The <link
|
||||
linkend="thread.glossary">glossary</link> gives a more complete description
|
||||
linkend="threads.glossary">glossary</link> gives a more complete description
|
||||
of the multithreading execution environment.</para>
|
||||
<para>Multithreading provides several advantages:
|
||||
<itemizedlist>
|
||||
@@ -48,15 +44,15 @@
|
||||
multithreaded programs are subject to additional errors:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><link linkend="thread.glossary.race-condition">Race
|
||||
<para><link linkend="threads.glossary.race-condition">Race
|
||||
conditions</link></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><link linkend="thread.glossary.deadlock">Deadlock</link>
|
||||
<para><link linkend="threads.glossary.deadlock">Deadlock</link>
|
||||
(sometimes called "deadly embrace")</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><link linkend="thread.glossary.priority-failure">Priority
|
||||
<para><link linkend="threads.glossary.priority-failure">Priority
|
||||
failures</link> (priority inversion, infinite overtaking, starvation,
|
||||
etc.)</para>
|
||||
</listitem>
|
||||
@@ -65,10 +61,10 @@
|
||||
errors. These aren't rare or exotic failures - they are virtually guaranteed
|
||||
to occur unless multithreaded code is designed to avoid them. Priority
|
||||
failures are somewhat less common, but are nonetheless serious.</para>
|
||||
<para>The <link linkend="thread.design">&Boost.Thread; design</link>
|
||||
<para>The <link linkend="threads.design">&Boost.Threads; design</link>
|
||||
attempts to minimize these errors, but they will still occur unless the
|
||||
programmer proactively designs to avoid them.</para>
|
||||
<note>Please also see <xref linkend="thread.implementation_notes"/>
|
||||
<note>Please also see <xref linkend="threads.implementation_notes"/>
|
||||
for additional, implementation-specific considerations.</note>
|
||||
</section>
|
||||
<section>
|
||||
@@ -123,11 +119,11 @@
|
||||
<title>Runtime libraries</title>
|
||||
<para>
|
||||
<emphasis role="bold">Warning:</emphasis> Multithreaded programs such as
|
||||
those using &Boost.Thread; must link to <link
|
||||
linkend="thread.glossary.thread-safe">thread-safe</link> versions of
|
||||
those using &Boost.Threads; must link to <link
|
||||
linkend="threads.glossary.thread-safe">thread-safe</link> versions of
|
||||
all runtime libraries used by the program, including the runtime library
|
||||
for the C++ Standard Library. Failure to do so will cause <link
|
||||
linkend="thread.glossary.race-condition">race conditions</link> to occur
|
||||
linkend="threads.glossary.race-condition">race conditions</link> to occur
|
||||
when multiple threads simultaneously execute runtime library functions for
|
||||
<code>new</code>, <code>delete</code>, or other language features which
|
||||
imply shared state.</para>
|
||||
@@ -173,15 +169,15 @@
|
||||
</section>
|
||||
</section>
|
||||
<section>
|
||||
<title>Common guarantees for all &Boost.Thread; components</title>
|
||||
<title>Common guarantees for all &Boost.Threads; components</title>
|
||||
<section>
|
||||
<title>Exceptions</title>
|
||||
<para>&Boost.Thread; destructors never
|
||||
<para>&Boost.Threads; destructors never
|
||||
throw exceptions. Unless otherwise specified, other
|
||||
&Boost.Thread; functions that do not have
|
||||
&Boost.Threads; functions that do not have
|
||||
an exception-specification may throw implementation-defined
|
||||
exceptions.</para>
|
||||
<para>In particular, &Boost.Thread;
|
||||
<para>In particular, &Boost.Threads;
|
||||
reports failure to allocate storage by throwing an exception of type
|
||||
<code>std::bad_alloc</code> or a class derived from
|
||||
<code>std::bad_alloc</code>, failure to obtain thread resources other than
|
||||
@@ -195,7 +191,7 @@
|
||||
</section>
|
||||
<section>
|
||||
<title>NonCopyable requirement</title>
|
||||
<para>&Boost.Thread; classes documented as
|
||||
<para>&Boost.Threads; classes documented as
|
||||
meeting the NonCopyable requirement disallow copy construction and copy
|
||||
assignment. For the sake of exposition, the synopsis of such classes show
|
||||
private derivation from <classname>boost::noncopyable</classname>. Users
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<section id="thread.rationale" last-revision="$Date$">
|
||||
<section id="threads.rationale" last-revision="$Date$">
|
||||
<title>Rationale</title>
|
||||
<para>This page explains the rationale behind various design decisions in the
|
||||
&Boost.Thread; library. Having the rationale documented here should explain
|
||||
&Boost.Threads; library. Having the rationale documented here should explain
|
||||
how we arrived at the current design as well as prevent future rehashing of
|
||||
discussions and thought processes that have already occurred. It can also give
|
||||
users a lot of insight into the design process required for this
|
||||
library.</para>
|
||||
<section id="thread.rationale.Boost.Thread">
|
||||
<title>Rationale for the Creation of &Boost.Thread;</title>
|
||||
<section id="threads.rationale.Boost.Threads">
|
||||
<title>Rationale for the Creation of &Boost.Threads;</title>
|
||||
<para>Processes often have a degree of "potential parallelism" and it can
|
||||
often be more intuitive to design systems with this in mind. Further, these
|
||||
parallel processes can result in more responsive programs. The benefits for
|
||||
@@ -37,24 +33,24 @@
|
||||
<para>What's truly needed is C++ language support for threads. However, the
|
||||
C++ standards committee needs existing practice or a good proposal as a
|
||||
starting point for adding this to the standard.</para>
|
||||
<para>The &Boost.Thread; library was developed to provide a C++ developer
|
||||
<para>The &Boost.Threads; library was developed to provide a C++ developer
|
||||
with a portable interface for writing multithreaded programs on numerous
|
||||
platforms. There's a hope that the library can be the basis for a more
|
||||
detailed proposal for the C++ standards committee to consider for inclusion
|
||||
in the next C++ standard.</para>
|
||||
</section>
|
||||
<section id="thread.rationale.primitives">
|
||||
<title>Rationale for the Low Level Primitives Supported in &Boost.Thread;</title>
|
||||
<para>The &Boost.Thread; library supplies a set of low level primitives for
|
||||
<section id="threads.rationale.primitives">
|
||||
<title>Rationale for the Low Level Primitives Supported in &Boost.Threads;</title>
|
||||
<para>The &Boost.Threads; library supplies a set of low level primitives for
|
||||
writing multithreaded programs, such as mutexes and condition variables. In
|
||||
fact, the first release of &Boost.Thread; supports only these low level
|
||||
fact, the first release of &Boost.Threads; supports only these low level
|
||||
primitives. However, computer science research has shown that use of these
|
||||
primitives is difficult since it's difficult to mathematically prove that a
|
||||
usage pattern is correct, meaning it doesn't result in race conditions or
|
||||
deadlocks. There are several algebras (such as CSP, CCS and Join calculus)
|
||||
that have been developed to help write provably correct parallel
|
||||
processes. In order to prove the correctness these processes must be coded
|
||||
using higher level abstractions. So why does &Boost.Thread; support the
|
||||
using higher level abstractions. So why does &Boost.Threads; support the
|
||||
lower level concepts?</para>
|
||||
<para>The reason is simple: the higher level concepts need to be implemented
|
||||
using at least some of the lower level concepts. So having portable lower
|
||||
@@ -68,11 +64,11 @@
|
||||
level concepts, supporting the lower level concepts provides
|
||||
greater accessibility.</para>
|
||||
</section>
|
||||
<section id="thread.rationale.locks">
|
||||
<section id="threads.rationale.locks">
|
||||
<title>Rationale for the Lock Design</title>
|
||||
<para>Programmers who are used to multithreaded programming issues will
|
||||
quickly note that the &Boost.Thread; design for mutex lock concepts is not
|
||||
<link linkend="thread.glossary.thread-safe">thread-safe</link> (this is
|
||||
quickly note that the &Boost.Threads; design for mutex lock concepts is not
|
||||
<link linkend="threads.glossary.thread-safe">thread-safe</link> (this is
|
||||
clearly documented as well). At first this may seem like a serious design
|
||||
flaw. Why have a multithreading primitive that's not thread-safe
|
||||
itself?</para>
|
||||
@@ -95,17 +91,17 @@
|
||||
since checking the state can occur only by a call after construction, we'd
|
||||
have a race condition if the lock object were shared between threads.</para>
|
||||
<para>So, to avoid the overhead of synchronizing access to the state
|
||||
information and to avoid the race condition, the &Boost.Thread; library
|
||||
information and to avoid the race condition, the &Boost.Threads; library
|
||||
simply does nothing to make lock objects thread-safe. Instead, sharing a
|
||||
lock object between threads results in undefined behavior. Since the only
|
||||
proper usage of lock objects is within block scope this isn't a problem, and
|
||||
so long as the lock object is properly used there's no danger of any
|
||||
multithreading issues.</para>
|
||||
</section>
|
||||
<section id="thread.rationale.non-copyable">
|
||||
<section id="threads.rationale.non-copyable">
|
||||
<title>Rationale for NonCopyable Thread Type</title>
|
||||
<para>Programmers who are used to C libraries for multithreaded programming
|
||||
are likely to wonder why &Boost.Thread; uses a noncopyable design for
|
||||
are likely to wonder why &Boost.Threads; uses a noncopyable design for
|
||||
<classname>boost::thread</classname>. After all, the C thread types are
|
||||
copyable, and you often have a need for copying them within user
|
||||
code. However, careful comparison of C designs to C++ designs shows a flaw
|
||||
@@ -141,7 +137,7 @@
|
||||
appear to bear them out. To illustrate the analysis we'll first provide
|
||||
pseudo-code illustrating the six typical usage patterns of a thread
|
||||
object.</para>
|
||||
<section id="thread.rationale.non-copyable.simple">
|
||||
<section id="threads.rationale.non-copyable.simple">
|
||||
<title>1. Use case: Simple creation of a thread.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -150,7 +146,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="thread.rationale.non-copyable.joined">
|
||||
<section id="threads.rationale.non-copyable.joined">
|
||||
<title>2. Use case: Creation of a thread that's later joined.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -160,7 +156,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="thread.rationale.non-copyable.loop">
|
||||
<section id="threads.rationale.non-copyable.loop">
|
||||
<title>3. Use case: Simple creation of several threads in a loop.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -170,7 +166,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="thread.rationale.non-copyable.loop-join">
|
||||
<section id="threads.rationale.non-copyable.loop-join">
|
||||
<title>4. Use case: Creation of several threads in a loop which are later joined.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -182,7 +178,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="thread.rationale.non-copyable.pass">
|
||||
<section id="threads.rationale.non-copyable.pass">
|
||||
<title>5. Use case: Creation of a thread whose ownership is passed to another object/method.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -192,7 +188,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="thread.rationale.non-copyable.shared">
|
||||
<section id="threads.rationale.non-copyable.shared">
|
||||
<title>6. Use case: Creation of a thread whose ownership is shared between multiple
|
||||
objects.</title>
|
||||
<programlisting>
|
||||
@@ -225,7 +221,7 @@
|
||||
use a concept for any of the usage patterns there would be a good argument
|
||||
for choosing the other design. So we'll code all six usage patterns using
|
||||
both designs.</para>
|
||||
<section id="thread.rationale_comparison.non-copyable.simple">
|
||||
<section id="threads.rationale_comparison.non-copyable.simple">
|
||||
<title>1. Comparison: simple creation of a thread.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -238,7 +234,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="thread.rationale_comparison.non-copyable.joined">
|
||||
<section id="threads.rationale_comparison.non-copyable.joined">
|
||||
<title>2. Comparison: creation of a thread that's later joined.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -253,7 +249,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="thread.rationale_comparison.non-copyable.loop">
|
||||
<section id="threads.rationale_comparison.non-copyable.loop">
|
||||
<title>3. Comparison: simple creation of several threads in a loop.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -268,7 +264,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="thread.rationale_comparison.non-copyable.loop-join">
|
||||
<section id="threads.rationale_comparison.non-copyable.loop-join">
|
||||
<title>4. Comparison: creation of several threads in a loop which are later joined.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -289,7 +285,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="thread.rationale_comparison.non-copyable.pass">
|
||||
<section id="threads.rationale_comparison.non-copyable.pass">
|
||||
<title>5. Comparison: creation of a thread whose ownership is passed to another object/method.</title>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -304,7 +300,7 @@
|
||||
}
|
||||
</programlisting>
|
||||
</section>
|
||||
<section id="thread.rationale_comparison.non-copyable.shared">
|
||||
<section id="threads.rationale_comparison.non-copyable.shared">
|
||||
<title>6. Comparison: creation of a thread whose ownership is shared
|
||||
between multiple objects.</title>
|
||||
<programlisting>
|
||||
@@ -325,18 +321,18 @@
|
||||
<para>This shows the usage patterns being nearly identical in complexity for
|
||||
both designs. The only actual added complexity occurs because of the use of
|
||||
operator new in
|
||||
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>,
|
||||
<link linkend="thread.rationale_comparison.non-copyable.pass">(5)</link>, and
|
||||
<link linkend="thread.rationale_comparison.non-copyable.shared">(6)</link>;
|
||||
<link linkend="threads.rationale_comparison.non-copyable.loop-join">(4)</link>,
|
||||
<link linkend="threads.rationale_comparison.non-copyable.pass">(5)</link>, and
|
||||
<link linkend="threads.rationale_comparison.non-copyable.shared">(6)</link>;
|
||||
and the use of std::auto_ptr and boost::shared_ptr in
|
||||
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link> and
|
||||
<link linkend="thread.rationale_comparison.non-copyable.shared">(6)</link>
|
||||
<link linkend="threads.rationale_comparison.non-copyable.loop-join">(4)</link> and
|
||||
<link linkend="threads.rationale_comparison.non-copyable.shared">(6)</link>
|
||||
respectively. However, that's not really
|
||||
much added complexity, and C++ programmers are used to using these idioms
|
||||
anyway. Some may dislike the presence of operator new in user code, but
|
||||
this can be eliminated by proper design of higher level concepts, such as
|
||||
the boost::thread_group class that simplifies example
|
||||
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>
|
||||
<link linkend="threads.rationale_comparison.non-copyable.loop-join">(4)</link>
|
||||
down to:</para>
|
||||
<programlisting>
|
||||
void foo()
|
||||
@@ -351,49 +347,49 @@
|
||||
design.</para>
|
||||
<para>So what about performance? Looking at the above code examples,
|
||||
we can analyze the theoretical impact to performance that both designs
|
||||
have. For <link linkend="thread.rationale_comparison.non-copyable.simple">(1)</link>
|
||||
have. For <link linkend="threads.rationale_comparison.non-copyable.simple">(1)</link>
|
||||
we can see that platforms that don't have a ref-counted native
|
||||
thread type (POSIX, for instance) will be impacted by a thread_ref
|
||||
design. Even if the native thread type is ref-counted there may be an impact
|
||||
if more state information has to be maintained for concepts foreign to the
|
||||
native API, such as clean up stacks for Win32 implementations.
|
||||
For <link linkend="thread.rationale_comparison.non-copyable.joined">(2)</link>
|
||||
and <link linkend="thread.rationale_comparison.non-copyable.loop">(3)</link>
|
||||
For <link linkend="threads.rationale_comparison.non-copyable.joined">(2)</link>
|
||||
and <link linkend="threads.rationale_comparison.non-copyable.loop">(3)</link>
|
||||
the performance impact will be identical to
|
||||
<link linkend="thread.rationale_comparison.non-copyable.simple">(1)</link>.
|
||||
For <link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>
|
||||
<link linkend="threads.rationale_comparison.non-copyable.simple">(1)</link>.
|
||||
For <link linkend="threads.rationale_comparison.non-copyable.loop-join">(4)</link>
|
||||
things get a little more interesting and we find that theoretically at least
|
||||
the thread_ref may perform faster since the thread design requires dynamic
|
||||
memory allocation/deallocation. However, in practice there may be dynamic
|
||||
allocation for the thread_ref design as well, it will just be hidden from
|
||||
the user. As long as the implementation has to do dynamic allocations the
|
||||
thread_ref loses again because of the reference management. For
|
||||
<link linkend="thread.rationale_comparison.non-copyable.pass">(5)</link> we see
|
||||
<link linkend="threads.rationale_comparison.non-copyable.pass">(5)</link> we see
|
||||
the same impact as we do for
|
||||
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>.
|
||||
For <link linkend="thread.rationale_comparison.non-copyable.shared">(6)</link>
|
||||
<link linkend="threads.rationale_comparison.non-copyable.loop-join">(4)</link>.
|
||||
For <link linkend="threads.rationale_comparison.non-copyable.shared">(6)</link>
|
||||
we still have a possible impact to
|
||||
the thread design because of dynamic allocation but thread_ref no longer
|
||||
suffers because of its reference management, and in fact, theoretically at
|
||||
least, the thread_ref may do a better job of managing the references. All of
|
||||
this indicates that thread wins for
|
||||
<link linkend="thread.rationale_comparison.non-copyable.simple">(1)</link>,
|
||||
<link linkend="thread.rationale_comparison.non-copyable.joined">(2)</link> and
|
||||
<link linkend="thread.rationale_comparison.non-copyable.loop">(3)</link>; with
|
||||
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>
|
||||
and <link linkend="thread.rationale_comparison.non-copyable.pass">(5)</link> the
|
||||
<link linkend="threads.rationale_comparison.non-copyable.simple">(1)</link>,
|
||||
<link linkend="threads.rationale_comparison.non-copyable.joined">(2)</link> and
|
||||
<link linkend="threads.rationale_comparison.non-copyable.loop">(3)</link>; with
|
||||
<link linkend="threads.rationale_comparison.non-copyable.loop-join">(4)</link>
|
||||
and <link linkend="threads.rationale_comparison.non-copyable.pass">(5)</link> the
|
||||
winner depending on the implementation and the platform but with the thread design
|
||||
probably having a better chance; and with
|
||||
<link linkend="thread.rationale_comparison.non-copyable.shared">(6)</link>
|
||||
<link linkend="threads.rationale_comparison.non-copyable.shared">(6)</link>
|
||||
it will again depend on the
|
||||
implementation and platform but this time we favor thread_ref
|
||||
slightly. Given all of this it's a narrow margin, but the thread design
|
||||
prevails.</para>
|
||||
<para>Given this analysis, and the fact that noncopyable objects for system
|
||||
resources are the normal designs that C++ programmers are used to dealing
|
||||
with, the &Boost.Thread; library has gone with a noncopyable design.</para>
|
||||
with, the &Boost.Threads; library has gone with a noncopyable design.</para>
|
||||
</section>
|
||||
<section id="thread.rationale.events">
|
||||
<section id="threads.rationale.events">
|
||||
<title>Rationale for not providing <emphasis>Event Variables</emphasis></title>
|
||||
<para><emphasis>Event variables</emphasis> are simply far too
|
||||
error-prone. <classname>boost::condition</classname> variables are a much safer
|
||||
@@ -420,13 +416,13 @@
|
||||
experiences caused them to be very careful in their use of event
|
||||
variables. Overt problems can be avoided, for example, by teaming the event
|
||||
variable with a mutex, but that may just convert a <link
|
||||
linkend="thread.glossary.race-condition">race condition</link> into another
|
||||
linkend="threads.glossary.race-condition">race condition</link> into another
|
||||
problem, such as excessive resource use. One of the most distressing aspects
|
||||
of the experience reports is the claim that many defects are latent. That
|
||||
is, the programs appear to work correctly, but contain hidden timing
|
||||
dependencies which will cause them to fail when environmental factors or
|
||||
usage patterns change, altering relative thread timings.</para>
|
||||
<para>The decision to exclude event variables from &Boost.Thread; has been
|
||||
<para>The decision to exclude event variables from &Boost.Threads; has been
|
||||
surprising to some Windows programmers. They have written programs which
|
||||
work using event variables, and wonder what the problem is. It seems similar
|
||||
to the "goto considered harmful" controversy of 30 years ago. It isn't that
|
||||
@@ -435,4 +431,4 @@
|
||||
and will be less likely to contain latent defects.</para>
|
||||
<para>[Rationale provided by Beman Dawes]</para>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
@@ -1,13 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<header name="boost/thread/read_write_mutex.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
@@ -20,13 +16,13 @@
|
||||
|
||||
<purpose>
|
||||
<para>Specifies the
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
to use when a set of threads try to obtain different types of
|
||||
locks simultaneously.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The only clock type supported by &Boost.Thread; is
|
||||
<para>The only clock type supported by &Boost.Threads; is
|
||||
<code>TIME_UTC</code>. The epoch for <code>TIME_UTC</code>
|
||||
is 1970-01-01 00:00:00.</para>
|
||||
</description>
|
||||
@@ -36,32 +32,22 @@
|
||||
<class name="read_write_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>read_write_mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.ReadWriteMutex">ReadWriteMutex</link> concept.</para>
|
||||
<note> Unfortunately it turned out that the current implementation of Read/Write Mutex has
|
||||
some serious problems. So it was decided not to put this implementation into
|
||||
release grade code. Also discussions on the mailing list led to the
|
||||
conclusion that the current concepts need to be rethought. In particular
|
||||
the schedulings <link linkend="thread.concepts.read-write-scheduling-policies.inter-class">
|
||||
Inter-Class Scheduling Policies</link> are deemed unnecessary.
|
||||
There seems to be common belief that a fair scheme suffices.
|
||||
The following documentation has been retained however, to give
|
||||
readers of this document the opportunity to study the original design.
|
||||
</note>
|
||||
<link linkend="threads.concepts.ReadWriteMutex">ReadWriteMutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>read_write_mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.ReadWriteMutex">ReadWriteMutex</link> concept.
|
||||
<link linkend="threads.concepts.ReadWriteMutex">ReadWriteMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
locking mechanics.</para>
|
||||
|
||||
<para>For classes that model related mutex concepts, see
|
||||
<classname>try_read_write_mutex</classname> and <classname>timed_read_write_mutex</classname>.</para>
|
||||
|
||||
<para>The <classname>read_write_mutex</classname> class supplies the following typedefs,
|
||||
which <link linkend="thread.concepts.read-write-lock-models">model</link>
|
||||
the specified locking strategies:
|
||||
<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:
|
||||
|
||||
<informaltable>
|
||||
<tgroup cols="2" align="left">
|
||||
@@ -73,16 +59,8 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_read_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_read_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -90,7 +68,7 @@
|
||||
</para>
|
||||
|
||||
<para>The <classname>read_write_mutex</classname> class uses an
|
||||
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
locking strategy, so attempts to recursively lock a <classname>read_write_mutex</classname>
|
||||
object or attempts to unlock one by threads that don't own a lock on it result in
|
||||
<emphasis role="bold">undefined behavior</emphasis>.
|
||||
@@ -100,20 +78,20 @@
|
||||
<code>NDEBUG</code> is not defined.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="thread.concepts.read-write-mutex-models">read/write mutex models</link>
|
||||
in &Boost.Thread;, <classname>read_write_mutex</classname> has two types of
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies">scheduling policies</link>, an
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
<link linkend="threads.concepts.read-write-mutex-models">read/write mutex models</link>
|
||||
in &Boost.Threads;, <classname>read_write_mutex</classname> has two types of
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies">scheduling policies</link>, an
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
between threads trying to obtain different types of locks and an
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link>
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link>
|
||||
between threads trying to obtain the same type of lock.
|
||||
The <classname>read_write_mutex</classname> class allows the
|
||||
programmer to choose what
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
will be used; however, like all read/write mutex models,
|
||||
<classname>read_write_mutex</classname> leaves the
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
|
||||
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>.
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
|
||||
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>.
|
||||
</para>
|
||||
|
||||
<note>Self-deadlock is virtually guaranteed if a thread tries to
|
||||
@@ -131,15 +109,7 @@
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<typedef name="scoped_read_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_read_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_write_lock">
|
||||
<typedef name="scoped_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
@@ -169,32 +139,22 @@
|
||||
<class name="try_read_write_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>try_read_write_mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.TryReadWriteMutex">TryReadWriteMutex</link> concept.</para>
|
||||
<note> Unfortunately it turned out that the current implementation of Read/Write Mutex has
|
||||
some serious problems. So it was decided not to put this implementation into
|
||||
release grade code. Also discussions on the mailing list led to the
|
||||
conclusion that the current concepts need to be rethought. In particular
|
||||
the schedulings <link linkend="thread.concepts.read-write-scheduling-policies.inter-class">
|
||||
Inter-Class Scheduling Policies</link> are deemed unnecessary.
|
||||
There seems to be common belief that a fair scheme suffices.
|
||||
The following documentation has been retained however, to give
|
||||
readers of this document the opportunity to study the original design.
|
||||
</note>
|
||||
<link linkend="threads.concepts.TryReadWriteMutex">TryReadWriteMutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>try_read_write_mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.TryReadWriteMutex">TryReadWriteMutex</link> concept.
|
||||
<link linkend="threads.concepts.TryReadWriteMutex">TryReadWriteMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
locking mechanics.</para>
|
||||
|
||||
<para>For classes that model related mutex concepts, see
|
||||
<classname>read_write_mutex</classname> and <classname>timed_read_write_mutex</classname>.</para>
|
||||
|
||||
<para>The <classname>try_read_write_mutex</classname> class supplies the following typedefs,
|
||||
which <link linkend="thread.concepts.read-write-lock-models">model</link>
|
||||
the specified locking strategies:
|
||||
which <link linkend="threads.concepts.read-write-lock-models">model</link>
|
||||
the specified locking strategy:
|
||||
|
||||
<informaltable>
|
||||
<tgroup cols="2" align="left">
|
||||
@@ -206,28 +166,12 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_read_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_read_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_read_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_read_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
<entry>scoped_try_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -235,7 +179,7 @@
|
||||
</para>
|
||||
|
||||
<para>The <classname>try_read_write_mutex</classname> class uses an
|
||||
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
locking strategy, so attempts to recursively lock a <classname>try_read_write_mutex</classname>
|
||||
object or attempts to unlock one by threads that don't own a lock on it result in
|
||||
<emphasis role="bold">undefined behavior</emphasis>.
|
||||
@@ -245,20 +189,20 @@
|
||||
<code>NDEBUG</code> is not defined.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="thread.concepts.read-write-mutex-models">read/write mutex models</link>
|
||||
in &Boost.Thread;, <classname>try_read_write_mutex</classname> has two types of
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies">scheduling policies</link>, an
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
<link linkend="threads.concepts.read-write-mutex-models">read/write mutex models</link>
|
||||
in &Boost.Threads;, <classname>try_read_write_mutex</classname> has two types of
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies">scheduling policies</link>, an
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
between threads trying to obtain different types of locks and an
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link>
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link>
|
||||
between threads trying to obtain the same type of lock.
|
||||
The <classname>try_read_write_mutex</classname> class allows the
|
||||
programmer to choose what
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
will be used; however, like all read/write mutex models,
|
||||
<classname>try_read_write_mutex</classname> leaves the
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
|
||||
<link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
|
||||
<link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
</para>
|
||||
|
||||
<note>Self-deadlock is virtually guaranteed if a thread tries to
|
||||
@@ -271,27 +215,11 @@
|
||||
<purpose>Exposition only</purpose>
|
||||
</inherit>
|
||||
|
||||
<typedef name="scoped_read_write_lock">
|
||||
<typedef name="scoped_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_read_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_read_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_read_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_write_lock">
|
||||
<typedef name="scoped_try_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
@@ -321,32 +249,22 @@
|
||||
<class name="timed_read_write_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>timed_read_write_mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.TimedReadWriteMutex">TimedReadWriteMutex</link> concept.</para>
|
||||
<note> Unfortunately it turned out that the current implementation of Read/Write Mutex has
|
||||
some serious problems. So it was decided not to put this implementation into
|
||||
release grade code. Also discussions on the mailing list led to the
|
||||
conclusion that the current concepts need to be rethought. In particular
|
||||
the schedulings <link linkend="thread.concepts.read-write-scheduling-policies.inter-class">
|
||||
Inter-Class Scheduling Policies</link> are deemed unnecessary.
|
||||
There seems to be common belief that a fair scheme suffices.
|
||||
The following documentation has been retained however, to give
|
||||
readers of this document the opportunity to study the original design.
|
||||
</note>
|
||||
<link linkend="threads.concepts.TimedReadWriteMutex">TimedReadWriteMutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>timed_read_write_mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.TimedReadWriteMutex">TimedReadWriteMutex</link> concept.
|
||||
<link linkend="threads.concepts.TimedReadWriteMutex">TimedReadWriteMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
locking mechanics.</para>
|
||||
|
||||
<para>For classes that model related mutex concepts, see
|
||||
<classname>read_write_mutex</classname> and <classname>try_read_write_mutex</classname>.</para>
|
||||
|
||||
<para>The <classname>timed_read_write_mutex</classname> class supplies the following typedefs,
|
||||
which <link linkend="thread.concepts.read-write-lock-models">model</link>
|
||||
the specified locking strategies:
|
||||
which <link linkend="threads.concepts.read-write-lock-models">model</link>
|
||||
the specified locking strategy:
|
||||
|
||||
<informaltable>
|
||||
<tgroup cols="2" align="left">
|
||||
@@ -358,40 +276,16 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_read_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_read_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
|
||||
<entry>scoped_try_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_read_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTimedReadWriteLock">ScopedTimedReadWriteLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_read_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_read_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_read_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_write_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
<entry>scoped_timed_lock</entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTimedReadWriteLock">ScopedTimedReadWriteLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -399,7 +293,7 @@
|
||||
</para>
|
||||
|
||||
<para>The <classname>timed_read_write_mutex</classname> class uses an
|
||||
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
|
||||
locking strategy, so attempts to recursively lock a <classname>timed_read_write_mutex</classname>
|
||||
object or attempts to unlock one by threads that don't own a lock on it result in
|
||||
<emphasis role="bold">undefined behavior</emphasis>.
|
||||
@@ -409,20 +303,20 @@
|
||||
<code>NDEBUG</code> is not defined.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="thread.concepts.read-write-mutex-models">read/write mutex models</link>
|
||||
in &Boost.Thread;, <classname>timed_read_write_mutex</classname> has two types of
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies">scheduling policies</link>, an
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
<link linkend="threads.concepts.read-write-mutex-models">read/write mutex models</link>
|
||||
in &Boost.Threads;, <classname>timed_read_write_mutex</classname> has two types of
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies">scheduling policies</link>, an
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
between threads trying to obtain different types of locks and an
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link>
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link>
|
||||
between threads trying to obtain the same type of lock.
|
||||
The <classname>timed_read_write_mutex</classname> class allows the
|
||||
programmer to choose what
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
|
||||
will be used; however, like all read/write mutex models,
|
||||
<classname>timed_read_write_mutex</classname> leaves the
|
||||
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
|
||||
<link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
<link linkend="threads.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
|
||||
<link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
</para>
|
||||
|
||||
<note>Self-deadlock is virtually guaranteed if a thread tries to
|
||||
@@ -430,39 +324,15 @@
|
||||
unless all locks are read-locks (but see below)</note>
|
||||
</description>
|
||||
|
||||
<typedef name="scoped_read_write_lock">
|
||||
<typedef name="scoped_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_read_write_lock">
|
||||
<typedef name="scoped_try_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_timed_read_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_read_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_read_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_timed_read_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_try_write_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
<typedef name="scoped_timed_write_lock">
|
||||
<typedef name="scoped_timed_lock">
|
||||
<type><emphasis>implementation-defined</emphasis></type>
|
||||
</typedef>
|
||||
|
||||
@@ -489,4 +359,4 @@
|
||||
</destructor>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
</header>
|
||||
@@ -1,33 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<header name="boost/thread/recursive_mutex.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
<class name="recursive_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>recursive_mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.Mutex">Mutex</link> concept.</para>
|
||||
<link linkend="threads.concepts.Mutex">Mutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>recursive_mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.Mutex">Mutex</link> concept.
|
||||
<link linkend="threads.concepts.Mutex">Mutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
|
||||
<link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
|
||||
locking mechanics.</para>
|
||||
|
||||
<para>For classes that model related mutex concepts, see
|
||||
<classname>recursive_try_mutex</classname> and <classname>recursive_timed_mutex</classname>.</para>
|
||||
|
||||
<para>For <link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
<para>For <link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking mechanics, see <classname>mutex</classname>,
|
||||
<classname>try_mutex</classname>, and <classname>timed_mutex</classname>.
|
||||
</para>
|
||||
@@ -47,7 +43,7 @@
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -55,7 +51,7 @@
|
||||
</para>
|
||||
|
||||
<para>The <classname>recursive_mutex</classname> class uses a
|
||||
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
|
||||
<link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
|
||||
locking strategy, so attempts to recursively lock a
|
||||
<classname>recursive_mutex</classname> object
|
||||
succeed and an internal "lock count" is maintained.
|
||||
@@ -64,10 +60,10 @@
|
||||
<emphasis role="bold">undefined behavior</emphasis>.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="thread.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Thread;, <classname>recursive_mutex</classname> leaves the
|
||||
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
<link linkend="threads.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Threads;, <classname>recursive_mutex</classname> leaves the
|
||||
<link linkend="threads.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
Programmers should make no assumptions about the order in which
|
||||
waiting threads acquire a lock.</para>
|
||||
</description>
|
||||
@@ -103,20 +99,20 @@
|
||||
<class name="recursive_try_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>recursive_try_mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.TryMutex">TryMutex</link> concept.</para>
|
||||
<link linkend="threads.concepts.TryMutex">TryMutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>recursive_try_mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.TryMutex">TryMutex</link> concept.
|
||||
<link linkend="threads.concepts.TryMutex">TryMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
|
||||
<link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
|
||||
locking mechanics.</para>
|
||||
|
||||
<para>For classes that model related mutex concepts, see
|
||||
<classname>recursive_mutex</classname> and <classname>recursive_timed_mutex</classname>.</para>
|
||||
|
||||
<para>For <link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
<para>For <link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking mechanics, see <classname>mutex</classname>,
|
||||
<classname>try_mutex</classname>, and <classname>timed_mutex</classname>.
|
||||
</para>
|
||||
@@ -136,11 +132,11 @@
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -148,7 +144,7 @@
|
||||
</para>
|
||||
|
||||
<para>The <classname>recursive_try_mutex</classname> class uses a
|
||||
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
|
||||
<link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
|
||||
locking strategy, so attempts to recursively lock a
|
||||
<classname>recursive_try_mutex</classname> object
|
||||
succeed and an internal "lock count" is maintained.
|
||||
@@ -157,10 +153,10 @@
|
||||
<emphasis role="bold">undefined behavior</emphasis>.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="thread.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Thread;, <classname>recursive_try_mutex</classname> leaves the
|
||||
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
<link linkend="threads.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Threads;, <classname>recursive_try_mutex</classname> leaves the
|
||||
<link linkend="threads.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
Programmers should make no assumptions about the order in which
|
||||
waiting threads acquire a lock.</para>
|
||||
</description>
|
||||
@@ -201,20 +197,20 @@
|
||||
<class name="recursive_timed_mutex">
|
||||
<purpose>
|
||||
<para>The <classname>recursive_timed_mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.TimedMutex">TimedMutex</link> concept.</para>
|
||||
<link linkend="threads.concepts.TimedMutex">TimedMutex</link> concept.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The <classname>recursive_timed_mutex</classname> class is a model of the
|
||||
<link linkend="thread.concepts.TimedMutex">TimedMutex</link> concept.
|
||||
<link linkend="threads.concepts.TimedMutex">TimedMutex</link> concept.
|
||||
It should be used to synchronize access to shared resources using
|
||||
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
|
||||
<link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
|
||||
locking mechanics.</para>
|
||||
|
||||
<para>For classes that model related mutex concepts, see
|
||||
<classname>recursive_mutex</classname> and <classname>recursive_try_mutex</classname>.</para>
|
||||
|
||||
<para>For <link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
<para>For <link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
|
||||
locking mechanics, see <classname>mutex</classname>,
|
||||
<classname>try_mutex</classname>, and <classname>timed_mutex</classname>.
|
||||
</para>
|
||||
@@ -234,15 +230,15 @@
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>scoped_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_try_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>scoped_timed_lock</entry>
|
||||
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
<entry><link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -250,7 +246,7 @@
|
||||
</para>
|
||||
|
||||
<para>The <classname>recursive_timed_mutex</classname> class uses a
|
||||
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
|
||||
<link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
|
||||
locking strategy, so attempts to recursively lock a
|
||||
<classname>recursive_timed_mutex</classname> object
|
||||
succeed and an internal "lock count" is maintained.
|
||||
@@ -259,10 +255,10 @@
|
||||
<emphasis role="bold">undefined behavior</emphasis>.</para>
|
||||
|
||||
<para>Like all
|
||||
<link linkend="thread.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Thread;, <classname>recursive_timed_mutex</classname> leaves the
|
||||
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
<link linkend="threads.concepts.mutex-models">mutex models</link>
|
||||
in &Boost.Threads;, <classname>recursive_timed_mutex</classname> leaves the
|
||||
<link linkend="threads.concepts.sheduling-policies">scheduling policy</link>
|
||||
as <link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
|
||||
Programmers should make no assumptions about the order in which
|
||||
waiting threads acquire a lock.</para>
|
||||
</description>
|
||||
@@ -303,4 +299,4 @@
|
||||
</destructor>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
</header>
|
||||
@@ -1,14 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<library-reference id="thread.reference"
|
||||
<library-reference id="threads.reference"
|
||||
last-revision="$Date$"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<xi:include href="barrier-ref.xml"/>
|
||||
@@ -17,12 +13,6 @@
|
||||
<xi:include href="mutex-ref.xml"/>
|
||||
<xi:include href="once-ref.xml"/>
|
||||
<xi:include href="recursive_mutex-ref.xml"/>
|
||||
<!--
|
||||
The read_write_mutex is held back from release, since the
|
||||
implementation suffers from a serious, yet unresolved bug.
|
||||
The implementation is likely to appear in a reworked
|
||||
form in the next release.
|
||||
-->
|
||||
<xi:include href="read_write_mutex-ref.xml"/>
|
||||
<xi:include href="thread-ref.xml"/>
|
||||
<xi:include href="tss-ref.xml"/>
|
||||
|
||||
@@ -1,75 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<section id="thread.release_notes" last-revision="$Date$">
|
||||
<section id="threads.release_notes" last-revision="$Date$">
|
||||
<title>Release Notes</title>
|
||||
<section id="thread.release_notes.boost_1_34_0">
|
||||
<title>Boost 1.34.0</title>
|
||||
|
||||
<section id="thread.release_notes.boost_1_34_0.change_log.maintainance">
|
||||
<title>New team of maintainers</title>
|
||||
|
||||
<para>
|
||||
Since the original author William E. Kempf no longer is available to
|
||||
maintain the &Boost.Thread; library, a new team has been formed
|
||||
in an attempt to continue the work on &Boost.Thread;.
|
||||
Fortunately William E. Kempf has given
|
||||
<ulink url="http://lists.boost.org/Archives/boost/2006/09/110143.php">
|
||||
permission </ulink>
|
||||
to use his work under the boost license.
|
||||
</para>
|
||||
<para>
|
||||
The team currently consists of
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
Anthony Williams, for the Win32 platform,
|
||||
</listitem>
|
||||
<listitem>
|
||||
Roland Schwarz, for the linux platform, and various "housekeeping" tasks.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
Volunteers for other platforms are welcome!
|
||||
</para>
|
||||
<para>
|
||||
As the &Boost.Thread; was kind of orphaned over the last release, this release
|
||||
attempts to fix the known bugs. Upcoming releases will bring in new things.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="thread.release_notes.boost_1_34_0.change_log.read_write_mutex">
|
||||
<title>read_write_mutex still broken</title>
|
||||
|
||||
<para>
|
||||
<note>
|
||||
It has been decided not to release the Read/Write Mutex, since the current
|
||||
implementation suffers from a serious bug. The documentation of the concepts
|
||||
has been included though, giving the interested reader an opportunity to study the
|
||||
original concepts. Please refer to the following links if you are interested
|
||||
which problems led to the decision to held back this mutex type.The issue
|
||||
has been discovered before 1.33 was released and the code has
|
||||
been omitted from that release. A reworked mutex is expected to appear in 1.35.
|
||||
Also see:
|
||||
<ulink url="http://lists.boost.org/Archives/boost/2005/08/92307.php">
|
||||
read_write_mutex bug</ulink>
|
||||
and
|
||||
<ulink url="http://lists.boost.org/Archives/boost/2005/09/93180.php">
|
||||
read_write_mutex fundamentally broken in 1.33</ulink>
|
||||
</note>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</section>
|
||||
<section id="thread.release_notes.boost_1_32_0">
|
||||
<section id="threads.release_notes.boost_1_32_0">
|
||||
<title>Boost 1.32.0</title>
|
||||
|
||||
<section id="thread.release_notes.boost_1_32_0.change_log.documentation">
|
||||
<section id="threads.release_notes.boost_1_32_0.change_log.documentation">
|
||||
<title>Documentation converted to BoostBook</title>
|
||||
|
||||
<para>The documentation was converted to BoostBook format,
|
||||
@@ -80,84 +20,58 @@
|
||||
please report them!</para>
|
||||
</section>
|
||||
|
||||
<section id="thread.release_notes.boost_1_32_0.change_log.static_link">
|
||||
<title>Statically-link build option added</title>
|
||||
<section id="threads.release_notes.boost_1_32_0.change_log.static_link">
|
||||
<title>Static-link build option added</title>
|
||||
|
||||
<para>The option to link &Boost.Thread; as a static
|
||||
library has been added (with some limitations on Win32 platforms).
|
||||
This feature was originally removed from an earlier version
|
||||
of Boost because <classname>boost::thread_specific_ptr</classname>
|
||||
required that &Boost.Thread; be dynamically linked in order
|
||||
for its cleanup functionality to work on Win32 platforms.
|
||||
Because this limitation never applied to non-Win32 platforms,
|
||||
because significant progress has been made in removing
|
||||
the limitation on Win32 platforms (many thanks to
|
||||
Aaron LaFramboise and Roland Scwarz!), and because the lack
|
||||
of static linking is one of the most common complaints of
|
||||
&Boost.Thread; users, this decision was reversed.</para>
|
||||
|
||||
<para>On non-Win32 platforms:
|
||||
To choose the dynamically linked version of &Boost.Thread;
|
||||
using Boost's auto-linking feature, #define BOOST_THREAD_USE_DLL;
|
||||
to choose the statically linked version,
|
||||
#define BOOST_THREAD_USE_LIB.
|
||||
If neither symbols is #defined, the default will be chosen.
|
||||
Currently the default is the statically linked version.</para>
|
||||
|
||||
<para>On Win32 platforms using VC++:
|
||||
Use the same #defines as for non-Win32 platforms
|
||||
(BOOST_THREAD_USE_DLL and BOOST_THREAD_USE_LIB).
|
||||
If neither is #defined, the default will be chosen.
|
||||
Currently the default is the statically linked version
|
||||
if the VC++ run-time library is set to
|
||||
"Multi-threaded" or "Multi-threaded Debug", and
|
||||
the dynamically linked version
|
||||
if the VC++ run-time library is set to
|
||||
"Multi-threaded DLL" or "Multi-threaded Debug DLL".</para>
|
||||
|
||||
<para>On Win32 platforms using compilers other than VC++:
|
||||
Use the same #defines as for non-Win32 platforms
|
||||
(BOOST_THREAD_USE_DLL and BOOST_THREAD_USE_LIB).
|
||||
If neither is #defined, the default will be chosen.
|
||||
Currently the default is the dynamically linked version
|
||||
because it has not yet been possible to implement automatic
|
||||
tss cleanup in the statically linked version for compilers
|
||||
other than VC++, although it is hoped that this will be
|
||||
possible in a future version of &Boost.Thread;.
|
||||
|
||||
Note for advanced users: &Boost.Thread; provides several "hook"
|
||||
functions to allow users to experiment with the statically
|
||||
linked version on Win32 with compilers other than VC++.
|
||||
These functions are on_process_enter(), on_process_exit(),
|
||||
on_thread_enter(), and on_thread_exit(), and are defined
|
||||
in tls_hooks.cpp. See the comments in that file for more
|
||||
information.</para>
|
||||
<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>
|
||||
</section>
|
||||
|
||||
<section id="thread.release_notes.boost_1_32_0.change_log.barrier">
|
||||
<section id="threads.release_notes.boost_1_32_0.change_log.barrier">
|
||||
<title>Barrier functionality added</title>
|
||||
|
||||
<para>A new class, <classname>boost::barrier</classname>, was added.</para>
|
||||
</section>
|
||||
|
||||
<section id="thread.release_notes.boost_1_32_0.change_log.read_write_mutex">
|
||||
<section id="threads.release_notes.boost_1_32_0.change_log.read_write_mutex">
|
||||
<title>Read/write mutex functionality added</title>
|
||||
|
||||
<para>New classes,
|
||||
<classname>boost::read_write_mutex</classname>,
|
||||
<classname>boost::try_read_write_mutex</classname>, and
|
||||
<classname>boost::timed_read_write_mutex</classname>
|
||||
were added.
|
||||
|
||||
<note>Since the read/write mutex and related classes are new,
|
||||
both interface and implementation are liable to change
|
||||
in future releases of &Boost.Thread;.
|
||||
The lock concepts and lock promotion in particular are
|
||||
still under discussion and very likely to change.</note>
|
||||
</para>
|
||||
were added.</para>
|
||||
</section>
|
||||
|
||||
<section id="thread.release_notes.boost_1_32_0.change_log.thread_specific_ptr">
|
||||
<section id="threads.release_notes.boost_1_32_0.change_log.thread_specific_ptr">
|
||||
<title>Thread-specific pointer functionality changed</title>
|
||||
|
||||
<para>The <classname>boost::thread_specific_ptr</classname>
|
||||
@@ -184,7 +98,7 @@
|
||||
is called.</para>
|
||||
</section>
|
||||
|
||||
<section id="thread.release_notes.boost_1_32_0.change_log.mutex">
|
||||
<section id="threads.release_notes.boost_1_32_0.change_log.mutex">
|
||||
<title>Mutex implementation changed for Win32</title>
|
||||
|
||||
<para>On Win32, <classname>boost::mutex</classname>,
|
||||
@@ -194,11 +108,5 @@
|
||||
<classname>boost::timed_mutex</classname> and
|
||||
<classname>boost::recursive_timed_mutex</classname> use a Win32 mutex.</para>
|
||||
</section>
|
||||
|
||||
<section id="thread.release_notes.boost_1_32_0.change_log.wince">
|
||||
<title>Windows CE support improved</title>
|
||||
|
||||
<para>Minor changes were made to make Boost.Thread work on Windows CE.</para>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<header name="boost/thread/thread.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
@@ -15,15 +11,15 @@
|
||||
<purpose>
|
||||
<para>The <classname>thread</classname> class represents threads of
|
||||
execution, and provides the functionality to create and manage
|
||||
threads within the &Boost.Thread; library. See
|
||||
<xref linkend="thread.glossary"/> for a precise description of
|
||||
<link linkend="thread.glossary.thread">thread of execution</link>,
|
||||
threads within the &Boost.Threads; library. See
|
||||
<xref linkend="threads.glossary"/> for a precise description of
|
||||
<link linkend="threads.glossary.thread">thread of execution</link>,
|
||||
and for definitions of threading-related terms and of thread states such as
|
||||
<link linkend="thread.glossary.thread-state">blocked</link>.</para>
|
||||
<link linkend="threads.glossary.thread-state">blocked</link>.</para>
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>A <link linkend="thread.glossary.thread">thread of execution</link>
|
||||
<para>A <link linkend="threads.glossary.thread">thread of execution</link>
|
||||
has an initial function. For the program's initial thread, the initial
|
||||
function is <code>main()</code>. For other threads, the initial
|
||||
function is <code>operator()</code> of the function object passed to
|
||||
@@ -40,7 +36,7 @@
|
||||
"joinable" or "non-joinable".</para>
|
||||
|
||||
<para>Except as described below, the policy used by an implementation
|
||||
of &Boost.Thread; to schedule transitions between thread states is
|
||||
of &Boost.Threads; to schedule transitions between thread states is
|
||||
unspecified.</para>
|
||||
|
||||
<para><note>Just as the lifetime of a file may be different from the
|
||||
@@ -153,7 +149,7 @@
|
||||
<notes>If <code>*this == thread()</code> the result is
|
||||
implementation-defined. If the implementation doesn't
|
||||
detect this the result will be
|
||||
<link linkend="thread.glossary.deadlock">deadlock</link>.
|
||||
<link linkend="threads.glossary.deadlock">deadlock</link>.
|
||||
</notes>
|
||||
</method>
|
||||
</method-group>
|
||||
@@ -174,7 +170,7 @@
|
||||
<type>void</type>
|
||||
|
||||
<effects>The current thread of execution is placed in the
|
||||
<link linkend="thread.glossary.thread-state">ready</link>
|
||||
<link linkend="threads.glossary.thread-state">ready</link>
|
||||
state.</effects>
|
||||
|
||||
<notes>
|
||||
@@ -233,7 +229,7 @@
|
||||
<type>void</type>
|
||||
|
||||
<parameter name="thrd">
|
||||
<paramtype><classname>thread</classname>*</paramtype>
|
||||
<paramtype><classname>thread</classname>* thrd</paramtype>
|
||||
</parameter>
|
||||
|
||||
<effects>Adds <code>thrd</code> to the
|
||||
@@ -247,7 +243,7 @@
|
||||
<type>void</type>
|
||||
|
||||
<parameter name="thrd">
|
||||
<paramtype><classname>thread</classname>*</paramtype>
|
||||
<paramtype><classname>thread</classname>* thrd</paramtype>
|
||||
</parameter>
|
||||
|
||||
<effects>Removes <code>thread</code> from <code>*this</code>'s
|
||||
@@ -267,4 +263,4 @@
|
||||
</method-group>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
</header>
|
||||
@@ -1,14 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<library name="Thread" dirname="thread" id="thread"
|
||||
<library name="Threads" dirname="thread" id="threads"
|
||||
last-revision="$Date$"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<libraryinfo>
|
||||
@@ -17,21 +13,31 @@ 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>Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)</para>
|
||||
<para>Permission to use, copy, modify, distribute and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, provided that the above copyright notice appear in all
|
||||
copies and that both that copyright notice and this permission notice
|
||||
appear in supporting documentation. William E. Kempf makes no
|
||||
representations about the suitability of this software for any purpose.
|
||||
It is provided "as is" without express or implied warranty.</para>
|
||||
</legalnotice>
|
||||
|
||||
<librarypurpose>Portable C++ multi-threading</librarypurpose>
|
||||
|
||||
<librarycategory name="category:concurrent" />
|
||||
<title>Boost.Thread</title>
|
||||
|
||||
<title>Boost.Threads</title>
|
||||
</libraryinfo>
|
||||
<title>Boost.Thread</title>
|
||||
<title>&Boost.Threads;</title>
|
||||
<xi:include href="overview.xml"/>
|
||||
<xi:include href="design.xml"/>
|
||||
<xi:include href="concepts.xml"/>
|
||||
|
||||
13
doc/thread_pool-ref.xml
Normal file
13
doc/thread_pool-ref.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<header name="boost/thread/thread_pool.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
<class name="thread_pool">
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
207
doc/thread_pool.html
Normal file
207
doc/thread_pool.html
Normal file
@@ -0,0 +1,207 @@
|
||||
<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>
|
||||
@@ -1,13 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<header name="boost/thread/tss.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
@@ -21,7 +17,7 @@
|
||||
<para>Thread specific storage is data associated with
|
||||
individual threads and is often used to make operations
|
||||
that rely on global data
|
||||
<link linkend="thread.glossary.thread-safe">thread-safe</link>.
|
||||
<link linkend="threads.glossary.thread-safe">thread-safe</link>.
|
||||
</para>
|
||||
|
||||
<para>Template <classname>thread_specific_ptr</classname>
|
||||
@@ -203,4 +199,4 @@
|
||||
</method-group>
|
||||
</class>
|
||||
</namespace>
|
||||
</header>
|
||||
</header>
|
||||
@@ -1,13 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
||||
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
|
||||
<!ENTITY % thread.entities SYSTEM "entities.xml">
|
||||
%thread.entities;
|
||||
<!ENTITY % threads.entities SYSTEM "entities.xml">
|
||||
%threads.entities;
|
||||
]>
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<header name="boost/thread/xtime.hpp"
|
||||
last-revision="$Date$">
|
||||
<namespace name="boost">
|
||||
@@ -20,7 +16,7 @@
|
||||
</purpose>
|
||||
|
||||
<description>
|
||||
<para>The only clock type supported by &Boost.Thread; is
|
||||
<para>The only clock type supported by &Boost.Threads; is
|
||||
<code>TIME_UTC</code>. The epoch for <code>TIME_UTC</code>
|
||||
is 1970-01-01 00:00:00.</para>
|
||||
</description>
|
||||
@@ -37,9 +33,9 @@
|
||||
<description>
|
||||
<simpara>The <classname>xtime</classname> type is used to represent a point on
|
||||
some time scale or a duration in time. This type may be proposed for the C standard by
|
||||
Markus Kuhn. &Boost.Thread; provides only a very minimal implementation of this
|
||||
Markus Kuhn. &Boost.Threads; provides only a very minimal implementation of this
|
||||
proposal; it is expected that a full implementation (or some other time
|
||||
library) will be provided in Boost as a separate library, at which time &Boost.Thread;
|
||||
library) will be provided in Boost as a separate library, at which time &Boost.Threads;
|
||||
will deprecate its own implementation.</simpara>
|
||||
|
||||
<simpara><emphasis role="bold">Note</emphasis> that the resolution is
|
||||
@@ -79,4 +75,4 @@
|
||||
</data-member>
|
||||
</struct>
|
||||
</namespace>
|
||||
</header>
|
||||
</header>
|
||||
2
example/.cvsignore
Normal file
2
example/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
bin
|
||||
*.pdb
|
||||
54
example/Jamfile
Normal file
54
example/Jamfile
Normal file
@@ -0,0 +1,54 @@
|
||||
# Copyright (C) 2001-2003
|
||||
# William E. Kempf
|
||||
#
|
||||
# Permission to use, copy, modify, distribute and sell this software
|
||||
# and its documentation for any purpose is hereby granted without fee,
|
||||
# provided that the above copyright notice appear in all copies and
|
||||
# that both that copyright notice and this permission notice appear
|
||||
# in supporting documentation. William E. Kempf makes no representations
|
||||
# about the suitability of this software for any purpose.
|
||||
# It is provided "as is" without express or implied warranty.
|
||||
#
|
||||
# Boost.Threads example Jamfile
|
||||
#
|
||||
# Additional configuration variables used:
|
||||
# 1. PTW32 may be used on Win32 platforms to specify that the pthreads-win32
|
||||
# library should be used instead of "native" threads. This feature is
|
||||
# mostly used for testing and it's generally recommended you use the
|
||||
# native threading libraries instead. PTW32 should be set to be a list
|
||||
# of two strings, the first specifying the installation path of the
|
||||
# pthreads-win32 library and the second specifying which library
|
||||
# variant to link against (see the pthreads-win32 documentation).
|
||||
# Example: jam -sPTW32="c:\pthreads-win32 pthreadVCE.lib"
|
||||
|
||||
# Declare the location of this subproject relative to the root.
|
||||
subproject libs/thread/example ;
|
||||
|
||||
# Include threads.jam for Boost.Threads global build information.
|
||||
# This greatly simplifies the Jam code needed to configure the build
|
||||
# for the various Win32 build types.
|
||||
import ../build/threads ;
|
||||
|
||||
{
|
||||
template example
|
||||
## sources ##
|
||||
: <template>thread_base
|
||||
<dll>../build/boost_thread
|
||||
## requirements ##
|
||||
:
|
||||
## default build ##
|
||||
:
|
||||
;
|
||||
|
||||
exe monitor : <template>example monitor.cpp ;
|
||||
exe starvephil : <template>example starvephil.cpp ;
|
||||
exe tennis : <template>example tennis.cpp ;
|
||||
exe condition : <template>example condition.cpp ;
|
||||
exe mutex : <template>example mutex.cpp ;
|
||||
exe once : <template>example once.cpp ;
|
||||
exe recursive_mutex : <template>example recursive_mutex.cpp ;
|
||||
exe thread : <template>example thread.cpp ;
|
||||
exe thread_group : <template>example thread_group.cpp ;
|
||||
exe tss : <template>example tss.cpp ;
|
||||
exe xtime : <template>example xtime.cpp ;
|
||||
}
|
||||
@@ -1,23 +1,5 @@
|
||||
# Copyright (C) 2001-2003
|
||||
# William E. Kempf
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
project boost/thread/example
|
||||
: requirements <library>../build//boost_thread <threading>multi
|
||||
exe starvephil
|
||||
: starvephil.cpp ../build/boost_thread ../../test/build/unit_test_framework
|
||||
;
|
||||
|
||||
|
||||
exe monitor : monitor.cpp ;
|
||||
exe starvephil : starvephil.cpp ;
|
||||
exe tennis : tennis.cpp ;
|
||||
exe condition : condition.cpp ;
|
||||
exe mutex : mutex.cpp ;
|
||||
exe once : once.cpp ;
|
||||
exe recursive_mutex : recursive_mutex.cpp ;
|
||||
exe thread : thread.cpp ;
|
||||
exe thread_group : thread_group.cpp ;
|
||||
exe tss : tss.cpp ;
|
||||
exe xtime : xtime.cpp ;
|
||||
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
// 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>
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
// 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,8 +1,13 @@
|
||||
// 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,8 +1,13 @@
|
||||
// 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,8 +1,13 @@
|
||||
// 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,8 +1,13 @@
|
||||
// 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>
|
||||
@@ -14,7 +19,7 @@
|
||||
namespace
|
||||
{
|
||||
boost::mutex iomx;
|
||||
} // namespace
|
||||
}
|
||||
|
||||
class canteen
|
||||
{
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
// 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,8 +1,13 @@
|
||||
// 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>
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
// 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,8 +1,13 @@
|
||||
// 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,8 +1,13 @@
|
||||
// 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>
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
// 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)
|
||||
|
||||
// See www.boost.org/libs/thread for documentation.
|
||||
|
||||
#if !defined(BOOST_THREAD_WEK01082003_HPP)
|
||||
#define BOOST_THREAD_WEK01082003_HPP
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/once.hpp>
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
#include <boost/thread/tss.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
|
||||
#endif
|
||||
@@ -1,9 +1,13 @@
|
||||
// Copyright (C) 2002-2003
|
||||
// David Moore, William E. Kempf
|
||||
// Copyright (C) 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)
|
||||
// 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
|
||||
@@ -11,48 +15,25 @@
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <boost/thread/condition.hpp>
|
||||
|
||||
namespace boost
|
||||
namespace boost {
|
||||
|
||||
class BOOST_THREAD_DECL barrier
|
||||
{
|
||||
public:
|
||||
barrier(unsigned int count);
|
||||
~barrier();
|
||||
|
||||
class barrier
|
||||
{
|
||||
public:
|
||||
barrier(unsigned int count)
|
||||
: m_threshold(count), m_count(count), m_generation(0)
|
||||
{
|
||||
if (count == 0)
|
||||
throw std::invalid_argument("count cannot be zero.");
|
||||
}
|
||||
|
||||
bool 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;
|
||||
}
|
||||
bool wait();
|
||||
|
||||
while (gen == m_generation)
|
||||
m_cond.wait(lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
mutex m_mutex;
|
||||
condition_variable m_cond;
|
||||
unsigned int m_threshold;
|
||||
unsigned int m_count;
|
||||
unsigned int m_generation;
|
||||
};
|
||||
private:
|
||||
mutex m_mutex;
|
||||
condition m_cond;
|
||||
unsigned int m_threshold;
|
||||
unsigned int m_count;
|
||||
unsigned int m_generation;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
@@ -1,16 +1,198 @@
|
||||
#ifndef BOOST_THREAD_CONDITION_HPP
|
||||
#define BOOST_THREAD_CONDITION_HPP
|
||||
// (C) Copyright 2007 Anthony Williams
|
||||
// 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/condition_variable.hpp>
|
||||
#ifndef BOOST_CONDITION_WEK070601_HPP
|
||||
#define BOOST_CONDITION_WEK070601_HPP
|
||||
|
||||
namespace boost
|
||||
{
|
||||
typedef condition_variable_any condition;
|
||||
}
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/detail/lock.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
# include "scoped_critical_region.hpp"
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct xtime;
|
||||
|
||||
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,21 +0,0 @@
|
||||
#ifndef BOOST_THREAD_CONDITION_VARIABLE_HPP
|
||||
#define BOOST_THREAD_CONDITION_VARIABLE_HPP
|
||||
|
||||
// condition_variable.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/detail/platform.hpp>
|
||||
#if defined(BOOST_THREAD_PLATFORM_WIN32)
|
||||
#include <boost/thread/win32/condition_variable.hpp>
|
||||
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
|
||||
#include <boost/thread/pthread/condition_variable.hpp>
|
||||
#else
|
||||
#error "Boost threads unavailable on this platform"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,74 +1,46 @@
|
||||
// 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.
|
||||
|
||||
#ifndef BOOST_THREAD_CONFIG_WEK01032003_HPP
|
||||
#define BOOST_THREAD_CONFIG_WEK01032003_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
|
||||
# pragma warn -8008 // Condition always true/false
|
||||
# pragma warn -8080 // Identifier declared but never used
|
||||
# pragma warn -8057 // Parameter never used
|
||||
# pragma warn -8066 // Unreachable code
|
||||
#endif
|
||||
// insist on threading support being available:
|
||||
#include <boost/config/requires_threads.hpp>
|
||||
|
||||
#include "platform.hpp"
|
||||
|
||||
// compatibility with the rest of Boost's auto-linking code:
|
||||
#if defined(BOOST_THREAD_DYN_DLL) || defined(BOOST_ALL_DYN_LINK)
|
||||
# undef BOOST_THREAD_USE_LIB
|
||||
# define BOOST_THREAD_USE_DLL
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_THREAD_BUILD_DLL) //Build dll
|
||||
#elif defined(BOOST_THREAD_BUILD_LIB) //Build lib
|
||||
#elif defined(BOOST_THREAD_USE_DLL) //Use dll
|
||||
#elif defined(BOOST_THREAD_USE_LIB) //Use lib
|
||||
#else //Use default
|
||||
# if defined(BOOST_THREAD_PLATFORM_WIN32)
|
||||
# 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_HAS_WINTHREADS)
|
||||
# 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
|
||||
# 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
|
||||
#endif // BOOST_HAS_DECLSPEC
|
||||
# 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.
|
||||
//
|
||||
// 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:
|
||||
//
|
||||
@@ -86,9 +58,3 @@
|
||||
#endif // auto-linking disabled
|
||||
|
||||
#endif // BOOST_THREAD_CONFIG_WEK1032003_HPP
|
||||
|
||||
// Change Log:
|
||||
// 22 Jan 05 Roland Schwarz (speedsnail)
|
||||
// Usage of BOOST_HAS_DECLSPEC macro.
|
||||
// Default again is static lib usage.
|
||||
// BOOST_DYN_LINK only defined when autolink included.
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// Mac Murrett
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// 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.
|
||||
|
||||
|
||||
214
include/boost/thread/detail/lock.hpp
Normal file
214
include/boost/thread/detail/lock.hpp
Normal file
@@ -0,0 +1,214 @@
|
||||
// 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_XLOCK_WEK070601_HPP
|
||||
#define BOOST_XLOCK_WEK070601_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
class condition;
|
||||
struct xtime;
|
||||
|
||||
namespace detail { namespace thread {
|
||||
|
||||
template <typename Mutex>
|
||||
class lock_ops : private noncopyable
|
||||
{
|
||||
private:
|
||||
lock_ops() { }
|
||||
|
||||
public:
|
||||
typedef typename Mutex::cv_state lock_state;
|
||||
|
||||
static void lock(Mutex& m)
|
||||
{
|
||||
m.do_lock();
|
||||
}
|
||||
static bool trylock(Mutex& m)
|
||||
{
|
||||
return m.do_trylock();
|
||||
}
|
||||
static bool timedlock(Mutex& m, const xtime& xt)
|
||||
{
|
||||
return m.do_timedlock(xt);
|
||||
}
|
||||
static void unlock(Mutex& m)
|
||||
{
|
||||
m.do_unlock();
|
||||
}
|
||||
static void lock(Mutex& m, lock_state& state)
|
||||
{
|
||||
m.do_lock(state);
|
||||
}
|
||||
static void unlock(Mutex& m, lock_state& state)
|
||||
{
|
||||
m.do_unlock(state);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Mutex>
|
||||
class scoped_lock : private noncopyable
|
||||
{
|
||||
public:
|
||||
typedef Mutex mutex_type;
|
||||
|
||||
explicit scoped_lock(Mutex& mx, bool initially_locked=true)
|
||||
: m_mutex(mx), m_locked(false)
|
||||
{
|
||||
if (initially_locked) lock();
|
||||
}
|
||||
~scoped_lock()
|
||||
{
|
||||
if (m_locked) unlock();
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if (m_locked) throw lock_error();
|
||||
lock_ops<Mutex>::lock(m_mutex);
|
||||
m_locked = true;
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if (!m_locked) throw lock_error();
|
||||
lock_ops<Mutex>::unlock(m_mutex);
|
||||
m_locked = false;
|
||||
}
|
||||
|
||||
bool locked() const { return m_locked; }
|
||||
operator const void*() const { return m_locked ? this : 0; }
|
||||
|
||||
private:
|
||||
friend class boost::condition;
|
||||
|
||||
Mutex& m_mutex;
|
||||
bool m_locked;
|
||||
};
|
||||
|
||||
template <typename TryMutex>
|
||||
class scoped_try_lock : private noncopyable
|
||||
{
|
||||
public:
|
||||
typedef TryMutex mutex_type;
|
||||
|
||||
explicit scoped_try_lock(TryMutex& mx)
|
||||
: m_mutex(mx), m_locked(false)
|
||||
{
|
||||
try_lock();
|
||||
}
|
||||
scoped_try_lock(TryMutex& mx, bool initially_locked)
|
||||
: m_mutex(mx), m_locked(false)
|
||||
{
|
||||
if (initially_locked) lock();
|
||||
}
|
||||
~scoped_try_lock()
|
||||
{
|
||||
if (m_locked) unlock();
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if (m_locked) throw lock_error();
|
||||
lock_ops<TryMutex>::lock(m_mutex);
|
||||
m_locked = true;
|
||||
}
|
||||
bool try_lock()
|
||||
{
|
||||
if (m_locked) throw lock_error();
|
||||
return (m_locked = lock_ops<TryMutex>::trylock(m_mutex));
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if (!m_locked) throw lock_error();
|
||||
lock_ops<TryMutex>::unlock(m_mutex);
|
||||
m_locked = false;
|
||||
}
|
||||
|
||||
bool locked() const { return m_locked; }
|
||||
operator const void*() const { return m_locked ? this : 0; }
|
||||
|
||||
private:
|
||||
friend class boost::condition;
|
||||
|
||||
TryMutex& m_mutex;
|
||||
bool m_locked;
|
||||
};
|
||||
|
||||
template <typename TimedMutex>
|
||||
class scoped_timed_lock : private noncopyable
|
||||
{
|
||||
public:
|
||||
typedef TimedMutex mutex_type;
|
||||
|
||||
scoped_timed_lock(TimedMutex& mx, const xtime& xt)
|
||||
: m_mutex(mx), m_locked(false)
|
||||
{
|
||||
timed_lock(xt);
|
||||
}
|
||||
scoped_timed_lock(TimedMutex& mx, bool initially_locked)
|
||||
: m_mutex(mx), m_locked(false)
|
||||
{
|
||||
if (initially_locked) lock();
|
||||
}
|
||||
~scoped_timed_lock()
|
||||
{
|
||||
if (m_locked) unlock();
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if (m_locked) throw lock_error();
|
||||
lock_ops<TimedMutex>::lock(m_mutex);
|
||||
m_locked = true;
|
||||
}
|
||||
bool try_lock()
|
||||
{
|
||||
if (m_locked) throw lock_error();
|
||||
return (m_locked = lock_ops<TimedMutex>::trylock(m_mutex));
|
||||
}
|
||||
bool timed_lock(const xtime& xt)
|
||||
{
|
||||
if (m_locked) throw lock_error();
|
||||
return (m_locked = lock_ops<TimedMutex>::timedlock(m_mutex, xt));
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if (!m_locked) throw lock_error();
|
||||
lock_ops<TimedMutex>::unlock(m_mutex);
|
||||
m_locked = false;
|
||||
}
|
||||
|
||||
bool locked() const { return m_locked; }
|
||||
operator const void*() const { return m_locked ? this : 0; }
|
||||
|
||||
private:
|
||||
friend class boost::condition;
|
||||
|
||||
TimedMutex& m_mutex;
|
||||
bool m_locked;
|
||||
};
|
||||
|
||||
} // namespace thread
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_XLOCK_WEK070601_HPP
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
|
||||
// 30 Jul 01 WEKEMPF Moved lock types into boost::detail::thread. Renamed
|
||||
// some types. Added locked() methods.
|
||||
@@ -1,31 +0,0 @@
|
||||
// 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 BOOST_THREAD_MOVE_HPP
|
||||
#define BOOST_THREAD_MOVE_HPP
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename T>
|
||||
struct thread_move_t
|
||||
{
|
||||
T& t;
|
||||
thread_move_t(T& t_):
|
||||
t(t_)
|
||||
{}
|
||||
|
||||
T* operator->() const
|
||||
{
|
||||
return &t;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
38
include/boost/thread/detail/named.hpp
Normal file
38
include/boost/thread/detail/named.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// 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_NAMED_WEK031703_HPP
|
||||
#define BOOST_NAMED_WEK031703_HPP
|
||||
|
||||
#include <boost/thread/detail/config.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
|
||||
@@ -1,71 +0,0 @@
|
||||
// Copyright 2006 Roland Schwarz.
|
||||
// (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)
|
||||
//
|
||||
// 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_PLATFORM_PTHREAD
|
||||
#else
|
||||
# if defined(BOOST_THREAD_WIN32)
|
||||
# define BOOST_THREAD_PLATFORM_WIN32
|
||||
# elif defined(BOOST_HAS_PTHREADS)
|
||||
# define BOOST_THREAD_PLATFORM_PTHREAD
|
||||
# else
|
||||
# error "Sorry, no boost threads are available for this platform."
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif // BOOST_THREAD_RS06040501_HPP
|
||||
1111
include/boost/thread/detail/read_write_lock.hpp
Normal file
1111
include/boost/thread/detail/read_write_lock.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,13 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// Mac Murrett
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// 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.
|
||||
|
||||
|
||||
35
include/boost/thread/detail/threadmon.hpp
Normal file
35
include/boost/thread/detail/threadmon.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
// 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,78 +0,0 @@
|
||||
// (C) Copyright Michael Glassford 2004.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#if !defined(BOOST_TLS_HOOKS_HPP)
|
||||
#define BOOST_TLS_HOOKS_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
|
||||
typedef void (__cdecl *thread_exit_handler)(void);
|
||||
|
||||
extern "C" BOOST_THREAD_DECL int at_thread_exit(
|
||||
thread_exit_handler exit_handler
|
||||
);
|
||||
//Add a function to the list of functions that will
|
||||
//be called when a thread is about to exit.
|
||||
//Currently only implemented for Win32, but should
|
||||
//later be implemented for all platforms.
|
||||
//Used by Win32 implementation of Boost.Threads
|
||||
//tss to perform cleanup.
|
||||
//Like the C runtime library atexit() function,
|
||||
//which it mimics, at_thread_exit() returns
|
||||
//zero if successful and a nonzero
|
||||
//value if an error occurs.
|
||||
|
||||
#endif //defined(BOOST_HAS_WINTHREADS)
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_process_enter(void);
|
||||
//Function to be called when the exe or dll
|
||||
//that uses Boost.Threads first starts
|
||||
//or is first loaded.
|
||||
//Should be called only before the first call to
|
||||
//on_thread_enter().
|
||||
//Called automatically by Boost.Threads when
|
||||
//a method for doing so has been discovered.
|
||||
//May be omitted; may be called multiple times.
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_process_exit(void);
|
||||
//Function to be called when the exe or dll
|
||||
//that uses Boost.Threads first starts
|
||||
//or is first loaded.
|
||||
//Should be called only after the last call to
|
||||
//on_exit_thread().
|
||||
//Called automatically by Boost.Threads when
|
||||
//a method for doing so has been discovered.
|
||||
//Must not be omitted; may be called multiple times.
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_thread_enter(void);
|
||||
//Function to be called just after a thread starts
|
||||
//in an exe or dll that uses Boost.Threads.
|
||||
//Must be called in the context of the thread
|
||||
//that is starting.
|
||||
//Called automatically by Boost.Threads when
|
||||
//a method for doing so has been discovered.
|
||||
//May be omitted; may be called multiple times.
|
||||
|
||||
extern "C" BOOST_THREAD_DECL void on_thread_exit(void);
|
||||
//Function to be called just be fore a thread ends
|
||||
//in an exe or dll that uses Boost.Threads.
|
||||
//Must be called in the context of the thread
|
||||
//that is ending.
|
||||
//Called automatically by Boost.Threads when
|
||||
//a method for doing so has been discovered.
|
||||
//Must not be omitted; may be called multiple times.
|
||||
|
||||
extern "C" void tss_cleanup_implemented(void);
|
||||
//Dummy function used both to detect whether tss cleanup
|
||||
//cleanup has been implemented and to force
|
||||
//it to be linked into the Boost.Threads library.
|
||||
|
||||
#endif //defined(BOOST_HAS_WINTHREADS)
|
||||
|
||||
#endif //!defined(BOOST_TLS_HOOKS_HPP)
|
||||
@@ -1,9 +1,13 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// Copyright (C) 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)
|
||||
// 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_EXCEPTIONS_PDM070801_H
|
||||
#define BOOST_THREAD_EXCEPTIONS_PDM070801_H
|
||||
@@ -16,7 +20,6 @@
|
||||
// given the include guards, but regardless it makes sense to
|
||||
// seperate this out any way.
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace boost {
|
||||
@@ -30,23 +33,14 @@ protected:
|
||||
public:
|
||||
~thread_exception() throw();
|
||||
|
||||
int native_error() const;
|
||||
int native_error() const { return m_sys_err; }
|
||||
|
||||
const char* message() const;
|
||||
|
||||
private:
|
||||
int m_sys_err;
|
||||
};
|
||||
|
||||
class condition_error:
|
||||
public std::exception
|
||||
{
|
||||
public:
|
||||
const char* what() const throw()
|
||||
{
|
||||
return "Condition error";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class BOOST_THREAD_DECL lock_error : public thread_exception
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -1,592 +0,0 @@
|
||||
// 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 BOOST_THREAD_LOCKS_HPP
|
||||
#define BOOST_THREAD_LOCKS_HPP
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <algorithm>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
struct defer_lock_t
|
||||
{};
|
||||
struct try_to_lock_t
|
||||
{};
|
||||
struct adopt_lock_t
|
||||
{};
|
||||
|
||||
const defer_lock_t defer_lock={};
|
||||
const try_to_lock_t try_to_lock={};
|
||||
const adopt_lock_t adopt_lock={};
|
||||
|
||||
template<typename Mutex>
|
||||
class shared_lock;
|
||||
|
||||
template<typename Mutex>
|
||||
class exclusive_lock;
|
||||
|
||||
template<typename Mutex>
|
||||
class upgrade_lock;
|
||||
|
||||
template<typename Mutex>
|
||||
class lock_guard
|
||||
{
|
||||
private:
|
||||
Mutex& m;
|
||||
|
||||
explicit lock_guard(lock_guard&);
|
||||
lock_guard& operator=(lock_guard&);
|
||||
public:
|
||||
explicit lock_guard(Mutex& m_):
|
||||
m(m_)
|
||||
{
|
||||
m.lock();
|
||||
}
|
||||
lock_guard(Mutex& m_,adopt_lock_t):
|
||||
m(m_)
|
||||
{}
|
||||
~lock_guard()
|
||||
{
|
||||
m.unlock();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Mutex>
|
||||
class unique_lock
|
||||
{
|
||||
private:
|
||||
Mutex* m;
|
||||
bool is_locked;
|
||||
explicit unique_lock(unique_lock&);
|
||||
unique_lock& operator=(unique_lock&);
|
||||
public:
|
||||
explicit unique_lock(Mutex& m_):
|
||||
m(&m_),is_locked(false)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
unique_lock(Mutex& m_,adopt_lock_t):
|
||||
m(&m_),is_locked(true)
|
||||
{}
|
||||
unique_lock(Mutex& m_,defer_lock_t):
|
||||
m(&m_),is_locked(false)
|
||||
{}
|
||||
unique_lock(Mutex& m_,try_to_lock_t):
|
||||
m(&m_),is_locked(false)
|
||||
{
|
||||
try_lock();
|
||||
}
|
||||
unique_lock(Mutex& m_,system_time const& target_time):
|
||||
m(&m_),is_locked(false)
|
||||
{
|
||||
timed_lock(target_time);
|
||||
}
|
||||
unique_lock(detail::thread_move_t<unique_lock<Mutex> > other):
|
||||
m(other->m),is_locked(other->is_locked)
|
||||
{
|
||||
other->is_locked=false;
|
||||
other->m=0;
|
||||
}
|
||||
unique_lock(detail::thread_move_t<upgrade_lock<Mutex> > other);
|
||||
|
||||
operator detail::thread_move_t<unique_lock<Mutex> >()
|
||||
{
|
||||
return move();
|
||||
}
|
||||
|
||||
detail::thread_move_t<unique_lock<Mutex> > move()
|
||||
{
|
||||
return detail::thread_move_t<unique_lock<Mutex> >(*this);
|
||||
}
|
||||
|
||||
unique_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other)
|
||||
{
|
||||
unique_lock temp(other);
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
unique_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other)
|
||||
{
|
||||
unique_lock temp(other);
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(unique_lock& other)
|
||||
{
|
||||
std::swap(m,other.m);
|
||||
std::swap(is_locked,other.is_locked);
|
||||
}
|
||||
void swap(detail::thread_move_t<unique_lock<Mutex> > other)
|
||||
{
|
||||
std::swap(m,other->m);
|
||||
std::swap(is_locked,other->is_locked);
|
||||
}
|
||||
|
||||
~unique_lock()
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
m->unlock();
|
||||
}
|
||||
}
|
||||
void lock()
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m->lock();
|
||||
is_locked=true;
|
||||
}
|
||||
bool try_lock()
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
is_locked=m->try_lock();
|
||||
return is_locked;
|
||||
}
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock(TimeDuration const& relative_time)
|
||||
{
|
||||
is_locked=m->timed_lock(relative_time);
|
||||
return is_locked;
|
||||
}
|
||||
|
||||
bool timed_lock(::boost::system_time const& absolute_time)
|
||||
{
|
||||
is_locked=m->timed_lock(absolute_time);
|
||||
return is_locked;
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if(!owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m->unlock();
|
||||
is_locked=false;
|
||||
}
|
||||
|
||||
typedef void (unique_lock::*bool_type)();
|
||||
operator bool_type() const
|
||||
{
|
||||
return is_locked?&unique_lock::lock:0;
|
||||
}
|
||||
bool operator!() const
|
||||
{
|
||||
return !owns_lock();
|
||||
}
|
||||
bool owns_lock() const
|
||||
{
|
||||
return is_locked;
|
||||
}
|
||||
|
||||
Mutex* mutex() const
|
||||
{
|
||||
return m;
|
||||
}
|
||||
|
||||
Mutex* release()
|
||||
{
|
||||
Mutex* const res=m;
|
||||
m=0;
|
||||
is_locked=false;
|
||||
return res;
|
||||
}
|
||||
|
||||
friend class shared_lock<Mutex>;
|
||||
friend class upgrade_lock<Mutex>;
|
||||
};
|
||||
|
||||
template<typename Mutex>
|
||||
inline detail::thread_move_t<unique_lock<Mutex> > move(unique_lock<Mutex> & x)
|
||||
{
|
||||
return x.move();
|
||||
}
|
||||
|
||||
template<typename Mutex>
|
||||
inline detail::thread_move_t<unique_lock<Mutex> > move(detail::thread_move_t<unique_lock<Mutex> > x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
template<typename Mutex>
|
||||
class shared_lock
|
||||
{
|
||||
protected:
|
||||
Mutex* m;
|
||||
bool is_locked;
|
||||
private:
|
||||
explicit shared_lock(shared_lock&);
|
||||
shared_lock& operator=(shared_lock&);
|
||||
public:
|
||||
explicit shared_lock(Mutex& m_):
|
||||
m(&m_),is_locked(false)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
shared_lock(Mutex& m_,adopt_lock_t):
|
||||
m(&m_),is_locked(true)
|
||||
{}
|
||||
shared_lock(Mutex& m_,defer_lock_t):
|
||||
m(&m_),is_locked(false)
|
||||
{}
|
||||
shared_lock(Mutex& m_,try_to_lock_t):
|
||||
m(&m_),is_locked(false)
|
||||
{
|
||||
try_lock();
|
||||
}
|
||||
shared_lock(Mutex& m_,system_time const& target_time):
|
||||
m(&m_),is_locked(false)
|
||||
{
|
||||
timed_lock(target_time);
|
||||
}
|
||||
|
||||
shared_lock(detail::thread_move_t<shared_lock<Mutex> > other):
|
||||
m(other->m),is_locked(other->is_locked)
|
||||
{
|
||||
other->is_locked=false;
|
||||
}
|
||||
|
||||
shared_lock(detail::thread_move_t<unique_lock<Mutex> > other):
|
||||
m(other->m),is_locked(other->is_locked)
|
||||
{
|
||||
other->is_locked=false;
|
||||
if(is_locked)
|
||||
{
|
||||
m->unlock_and_lock_shared();
|
||||
}
|
||||
}
|
||||
|
||||
shared_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
|
||||
m(other->m),is_locked(other->is_locked)
|
||||
{
|
||||
other->is_locked=false;
|
||||
if(is_locked)
|
||||
{
|
||||
m->unlock_upgrade_and_lock_shared();
|
||||
}
|
||||
}
|
||||
|
||||
operator detail::thread_move_t<shared_lock<Mutex> >()
|
||||
{
|
||||
return move();
|
||||
}
|
||||
|
||||
detail::thread_move_t<shared_lock<Mutex> > move()
|
||||
{
|
||||
return detail::thread_move_t<shared_lock<Mutex> >(*this);
|
||||
}
|
||||
|
||||
|
||||
shared_lock& operator=(detail::thread_move_t<shared_lock<Mutex> > other)
|
||||
{
|
||||
shared_lock temp(other);
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
shared_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other)
|
||||
{
|
||||
shared_lock temp(other);
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
shared_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other)
|
||||
{
|
||||
shared_lock temp(other);
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(shared_lock& other)
|
||||
{
|
||||
std::swap(m,other.m);
|
||||
std::swap(is_locked,other.is_locked);
|
||||
}
|
||||
|
||||
~shared_lock()
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
m->unlock_shared();
|
||||
}
|
||||
}
|
||||
void lock()
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m->lock_shared();
|
||||
is_locked=true;
|
||||
}
|
||||
bool try_lock()
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
is_locked=m->try_lock_shared();
|
||||
return is_locked;
|
||||
}
|
||||
bool timed_lock(boost::system_time const& target_time)
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
is_locked=m->timed_lock_shared(target_time);
|
||||
return is_locked;
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if(!owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m->unlock_shared();
|
||||
is_locked=false;
|
||||
}
|
||||
|
||||
typedef void (shared_lock::*bool_type)();
|
||||
operator bool_type() const
|
||||
{
|
||||
return is_locked?&shared_lock::lock:0;
|
||||
}
|
||||
bool operator!() const
|
||||
{
|
||||
return !owns_lock();
|
||||
}
|
||||
bool owns_lock() const
|
||||
{
|
||||
return is_locked;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename Mutex>
|
||||
inline detail::thread_move_t<shared_lock<Mutex> > move(shared_lock<Mutex> & x)
|
||||
{
|
||||
return x.move();
|
||||
}
|
||||
|
||||
template<typename Mutex>
|
||||
inline detail::thread_move_t<shared_lock<Mutex> > move(detail::thread_move_t<shared_lock<Mutex> > x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
template<typename Mutex>
|
||||
class upgrade_lock
|
||||
{
|
||||
protected:
|
||||
Mutex* m;
|
||||
bool is_locked;
|
||||
private:
|
||||
explicit upgrade_lock(upgrade_lock&);
|
||||
upgrade_lock& operator=(upgrade_lock&);
|
||||
public:
|
||||
explicit upgrade_lock(Mutex& m_):
|
||||
m(&m_),is_locked(false)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
upgrade_lock(Mutex& m_,bool do_lock):
|
||||
m(&m_),is_locked(false)
|
||||
{
|
||||
if(do_lock)
|
||||
{
|
||||
lock();
|
||||
}
|
||||
}
|
||||
upgrade_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
|
||||
m(other->m),is_locked(other->is_locked)
|
||||
{
|
||||
other->is_locked=false;
|
||||
}
|
||||
|
||||
upgrade_lock(detail::thread_move_t<unique_lock<Mutex> > other):
|
||||
m(other->m),is_locked(other->is_locked)
|
||||
{
|
||||
other->is_locked=false;
|
||||
if(is_locked)
|
||||
{
|
||||
m->unlock_and_lock_upgrade();
|
||||
}
|
||||
}
|
||||
|
||||
operator detail::thread_move_t<upgrade_lock<Mutex> >()
|
||||
{
|
||||
return move();
|
||||
}
|
||||
|
||||
detail::thread_move_t<upgrade_lock<Mutex> > move()
|
||||
{
|
||||
return detail::thread_move_t<upgrade_lock<Mutex> >(*this);
|
||||
}
|
||||
|
||||
|
||||
upgrade_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other)
|
||||
{
|
||||
upgrade_lock temp(other);
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
upgrade_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other)
|
||||
{
|
||||
upgrade_lock temp(other);
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(upgrade_lock& other)
|
||||
{
|
||||
std::swap(m,other.m);
|
||||
std::swap(is_locked,other.is_locked);
|
||||
}
|
||||
|
||||
~upgrade_lock()
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
m->unlock_upgrade();
|
||||
}
|
||||
}
|
||||
void lock()
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m->lock_upgrade();
|
||||
is_locked=true;
|
||||
}
|
||||
bool try_lock()
|
||||
{
|
||||
if(owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
is_locked=m->try_lock_upgrade();
|
||||
return is_locked;
|
||||
}
|
||||
void unlock()
|
||||
{
|
||||
if(!owns_lock())
|
||||
{
|
||||
throw boost::lock_error();
|
||||
}
|
||||
m->unlock_upgrade();
|
||||
is_locked=false;
|
||||
}
|
||||
|
||||
typedef void (upgrade_lock::*bool_type)();
|
||||
operator bool_type() const
|
||||
{
|
||||
return is_locked?&upgrade_lock::lock:0;
|
||||
}
|
||||
bool operator!() const
|
||||
{
|
||||
return !owns_lock();
|
||||
}
|
||||
bool owns_lock() const
|
||||
{
|
||||
return is_locked;
|
||||
}
|
||||
friend class shared_lock<Mutex>;
|
||||
friend class unique_lock<Mutex>;
|
||||
};
|
||||
|
||||
|
||||
template<typename Mutex>
|
||||
inline detail::thread_move_t<upgrade_lock<Mutex> > move(upgrade_lock<Mutex> & x)
|
||||
{
|
||||
return x.move();
|
||||
}
|
||||
|
||||
template<typename Mutex>
|
||||
inline detail::thread_move_t<upgrade_lock<Mutex> > move(detail::thread_move_t<upgrade_lock<Mutex> > x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
template<typename Mutex>
|
||||
unique_lock<Mutex>::unique_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
|
||||
m(other->m),is_locked(other->is_locked)
|
||||
{
|
||||
other->is_locked=false;
|
||||
if(is_locked)
|
||||
{
|
||||
m->unlock_upgrade_and_lock();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Mutex>
|
||||
class upgrade_to_unique_lock
|
||||
{
|
||||
private:
|
||||
upgrade_lock<Mutex>* source;
|
||||
unique_lock<Mutex> exclusive;
|
||||
|
||||
explicit upgrade_to_unique_lock(upgrade_to_unique_lock&);
|
||||
upgrade_to_unique_lock& operator=(upgrade_to_unique_lock&);
|
||||
public:
|
||||
explicit upgrade_to_unique_lock(upgrade_lock<Mutex>& m_):
|
||||
source(&m_),exclusive(move(*source))
|
||||
{}
|
||||
~upgrade_to_unique_lock()
|
||||
{
|
||||
if(source)
|
||||
{
|
||||
*source=move(exclusive);
|
||||
}
|
||||
}
|
||||
|
||||
upgrade_to_unique_lock(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other):
|
||||
source(other->source),exclusive(move(other->exclusive))
|
||||
{
|
||||
other->source=0;
|
||||
}
|
||||
|
||||
upgrade_to_unique_lock& operator=(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other)
|
||||
{
|
||||
upgrade_to_unique_lock temp(other);
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
void swap(upgrade_to_unique_lock& other)
|
||||
{
|
||||
std::swap(source,other.source);
|
||||
exclusive.swap(other.exclusive);
|
||||
}
|
||||
typedef void (upgrade_to_unique_lock::*bool_type)(upgrade_to_unique_lock&);
|
||||
operator bool_type() const
|
||||
{
|
||||
return exclusive.owns_lock()?&upgrade_to_unique_lock::swap:0;
|
||||
}
|
||||
bool operator!() const
|
||||
{
|
||||
return !owns_lock();
|
||||
}
|
||||
bool owns_lock() const
|
||||
{
|
||||
return exclusive.owns_lock();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,21 +1,171 @@
|
||||
#ifndef BOOST_THREAD_MUTEX_HPP
|
||||
#define BOOST_THREAD_MUTEX_HPP
|
||||
|
||||
// mutex.hpp
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// (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)
|
||||
// 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/platform.hpp>
|
||||
#if defined(BOOST_THREAD_PLATFORM_WIN32)
|
||||
#include <boost/thread/win32/mutex.hpp>
|
||||
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
|
||||
#include <boost/thread/pthread/mutex.hpp>
|
||||
#else
|
||||
#error "Boost threads unavailable on this platform"
|
||||
#ifndef BOOST_MUTEX_WEK070601_HPP
|
||||
#define BOOST_MUTEX_WEK070601_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/detail/lock.hpp>
|
||||
#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 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,29 +1,42 @@
|
||||
#ifndef BOOST_THREAD_ONCE_HPP
|
||||
#define BOOST_THREAD_ONCE_HPP
|
||||
|
||||
// once.hpp
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// (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)
|
||||
// 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/platform.hpp>
|
||||
#if defined(BOOST_THREAD_PLATFORM_WIN32)
|
||||
#include <boost/thread/win32/once.hpp>
|
||||
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
|
||||
#include <boost/thread/pthread/once.hpp>
|
||||
#else
|
||||
#error "Boost threads unavailable on this platform"
|
||||
#ifndef BOOST_ONCE_WEK080101_HPP
|
||||
#define BOOST_ONCE_WEK080101_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
inline void call_once(void (*func)(),once_flag& flag)
|
||||
{
|
||||
call_once(flag,func);
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
#ifndef BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP
|
||||
#define BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP
|
||||
// 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
|
||||
|
||||
#include <limits.h>
|
||||
#include <boost/assert.hpp>
|
||||
#include <algorithm>
|
||||
#include <pthread.h>
|
||||
#include "timespec.hpp"
|
||||
#include "pthread_mutex_scoped_lock.hpp"
|
||||
#include "thread_data.hpp"
|
||||
#include "condition_variable_fwd.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
inline condition_variable::condition_variable()
|
||||
{
|
||||
int const res=pthread_cond_init(&cond,NULL);
|
||||
if(res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
}
|
||||
}
|
||||
inline condition_variable::~condition_variable()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_destroy(&cond));
|
||||
}
|
||||
|
||||
inline void condition_variable::wait(unique_lock<mutex>& m)
|
||||
{
|
||||
detail::interruption_checker check_for_interruption(&cond);
|
||||
BOOST_VERIFY(!pthread_cond_wait(&cond,m.mutex()->native_handle()));
|
||||
}
|
||||
|
||||
inline bool condition_variable::timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until)
|
||||
{
|
||||
detail::interruption_checker check_for_interruption(&cond);
|
||||
struct timespec const timeout=detail::get_timespec(wait_until);
|
||||
int const cond_res=pthread_cond_timedwait(&cond,m.mutex()->native_handle(),&timeout);
|
||||
if(cond_res==ETIMEDOUT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
BOOST_ASSERT(!cond_res);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void condition_variable::notify_one()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_signal(&cond));
|
||||
}
|
||||
|
||||
inline void condition_variable::notify_all()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&cond));
|
||||
}
|
||||
|
||||
class condition_variable_any
|
||||
{
|
||||
pthread_mutex_t internal_mutex;
|
||||
pthread_cond_t cond;
|
||||
|
||||
condition_variable_any(condition_variable&);
|
||||
condition_variable_any& operator=(condition_variable&);
|
||||
|
||||
public:
|
||||
condition_variable_any()
|
||||
{
|
||||
int const res=pthread_mutex_init(&internal_mutex,NULL);
|
||||
if(res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
}
|
||||
int const res2=pthread_cond_init(&cond,NULL);
|
||||
if(res2)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
|
||||
throw thread_resource_error();
|
||||
}
|
||||
}
|
||||
~condition_variable_any()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
|
||||
BOOST_VERIFY(!pthread_cond_destroy(&cond));
|
||||
}
|
||||
|
||||
template<typename lock_type>
|
||||
void wait(lock_type& m)
|
||||
{
|
||||
int res=0;
|
||||
{
|
||||
detail::interruption_checker check_for_interruption(&cond);
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
|
||||
m.unlock();
|
||||
res=pthread_cond_wait(&cond,&internal_mutex);
|
||||
}
|
||||
m.lock();
|
||||
}
|
||||
if(res)
|
||||
{
|
||||
throw condition_error();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
void wait(lock_type& m,predicate_type pred)
|
||||
{
|
||||
while(!pred()) wait(m);
|
||||
}
|
||||
|
||||
template<typename lock_type>
|
||||
bool timed_wait(lock_type& m,boost::system_time const& wait_until)
|
||||
{
|
||||
struct timespec const timeout=detail::get_timespec(wait_until);
|
||||
int res=0;
|
||||
{
|
||||
detail::interruption_checker check_for_interruption(&cond);
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
|
||||
m.unlock();
|
||||
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
|
||||
}
|
||||
m.lock();
|
||||
}
|
||||
if(res==ETIMEDOUT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(res)
|
||||
{
|
||||
throw condition_error();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred)
|
||||
{
|
||||
while (!pred())
|
||||
{
|
||||
if(!timed_wait(m, wait_until))
|
||||
return pred();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,xtime const& wait_until,predicate_type pred)
|
||||
{
|
||||
return timed_wait(m,system_time(wait_until),pred);
|
||||
}
|
||||
|
||||
template<typename lock_type,typename duration_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
|
||||
{
|
||||
return timed_wait(m,get_system_time()+wait_duration,pred);
|
||||
}
|
||||
|
||||
void notify_one()
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
|
||||
BOOST_VERIFY(!pthread_cond_signal(&cond));
|
||||
}
|
||||
|
||||
void notify_all()
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&cond));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,66 +0,0 @@
|
||||
#ifndef BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_HPP
|
||||
#define BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_HPP
|
||||
// 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
|
||||
|
||||
#include <pthread.h>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#include <boost/thread/xtime.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class condition_variable
|
||||
{
|
||||
private:
|
||||
pthread_cond_t cond;
|
||||
|
||||
condition_variable(condition_variable&);
|
||||
condition_variable& operator=(condition_variable&);
|
||||
|
||||
public:
|
||||
condition_variable();
|
||||
~condition_variable();
|
||||
|
||||
void wait(unique_lock<mutex>& m);
|
||||
|
||||
template<typename predicate_type>
|
||||
void wait(unique_lock<mutex>& m,predicate_type pred)
|
||||
{
|
||||
while(!pred()) wait(m);
|
||||
}
|
||||
|
||||
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until);
|
||||
|
||||
template<typename predicate_type>
|
||||
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until,predicate_type pred)
|
||||
{
|
||||
while (!pred())
|
||||
{
|
||||
if(!timed_wait(m, wait_until))
|
||||
return pred();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename predicate_type>
|
||||
bool timed_wait(unique_lock<mutex>& m,xtime const& wait_until,predicate_type pred)
|
||||
{
|
||||
return timed_wait(m,system_time(wait_until),pred);
|
||||
}
|
||||
|
||||
template<typename duration_type,typename predicate_type>
|
||||
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
|
||||
{
|
||||
return timed_wait(m,get_system_time()+wait_duration,pred);
|
||||
}
|
||||
|
||||
void notify_one();
|
||||
void notify_all();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,197 +0,0 @@
|
||||
#ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP
|
||||
#define BOOST_THREAD_PTHREAD_MUTEX_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 <pthread.h>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include "timespec.hpp"
|
||||
#include "pthread_mutex_scoped_lock.hpp"
|
||||
|
||||
#ifdef _POSIX_TIMEOUTS
|
||||
#if _POSIX_TIMEOUTS >= 0
|
||||
#define BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class mutex:
|
||||
boost::noncopyable
|
||||
{
|
||||
private:
|
||||
pthread_mutex_t m;
|
||||
public:
|
||||
mutex()
|
||||
{
|
||||
int const res=pthread_mutex_init(&m,NULL);
|
||||
if(res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
}
|
||||
}
|
||||
~mutex()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_lock(&m));
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(&m));
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
int const res=pthread_mutex_trylock(&m);
|
||||
BOOST_ASSERT(!res || res==EBUSY);
|
||||
return !res;
|
||||
}
|
||||
|
||||
typedef pthread_mutex_t* native_handle_type;
|
||||
native_handle_type native_handle()
|
||||
{
|
||||
return &m;
|
||||
}
|
||||
|
||||
typedef unique_lock<mutex> scoped_lock;
|
||||
typedef scoped_lock scoped_try_lock;
|
||||
};
|
||||
|
||||
typedef mutex try_mutex;
|
||||
|
||||
class timed_mutex:
|
||||
boost::noncopyable
|
||||
{
|
||||
private:
|
||||
pthread_mutex_t m;
|
||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
pthread_cond_t cond;
|
||||
bool is_locked;
|
||||
#endif
|
||||
public:
|
||||
timed_mutex()
|
||||
{
|
||||
int const res=pthread_mutex_init(&m,NULL);
|
||||
if(res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
}
|
||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
int const res2=pthread_cond_init(&cond,NULL);
|
||||
if(res2)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
throw thread_resource_error();
|
||||
}
|
||||
is_locked=false;
|
||||
#endif
|
||||
}
|
||||
~timed_mutex()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
BOOST_VERIFY(!pthread_cond_destroy(&cond));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock(get_system_time()+relative_time);
|
||||
}
|
||||
|
||||
#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
void lock()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_lock(&m));
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(&m));
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
int const res=pthread_mutex_trylock(&m);
|
||||
BOOST_ASSERT(!res || res==EBUSY);
|
||||
return !res;
|
||||
}
|
||||
bool timed_lock(system_time const & abs_time)
|
||||
{
|
||||
struct timespec const timeout=detail::get_timespec(abs_time);
|
||||
int const res=pthread_mutex_timedlock(&m,&timeout);
|
||||
BOOST_ASSERT(!res || res==EBUSY);
|
||||
return !res;
|
||||
}
|
||||
#else
|
||||
void lock()
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||
while(is_locked)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
|
||||
}
|
||||
is_locked=true;
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||
is_locked=false;
|
||||
BOOST_VERIFY(!pthread_cond_signal(&cond));
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||
if(is_locked)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
is_locked=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool timed_lock(system_time const & abs_time)
|
||||
{
|
||||
struct timespec const timeout=detail::get_timespec(abs_time);
|
||||
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||
while(is_locked)
|
||||
{
|
||||
int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
|
||||
if(cond_res==ETIMEDOUT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
BOOST_ASSERT(!cond_res);
|
||||
}
|
||||
is_locked=true;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef unique_lock<timed_mutex> scoped_timed_lock;
|
||||
typedef scoped_timed_lock scoped_try_lock;
|
||||
typedef scoped_timed_lock scoped_lock;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,85 +0,0 @@
|
||||
#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/detail/config.hpp>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <boost/assert.hpp>
|
||||
#include "pthread_mutex_scoped_lock.hpp"
|
||||
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct once_flag
|
||||
{
|
||||
boost::uintmax_t epoch;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
BOOST_THREAD_DECL boost::uintmax_t& get_once_per_thread_epoch();
|
||||
BOOST_THREAD_DECL extern boost::uintmax_t once_global_epoch;
|
||||
BOOST_THREAD_DECL extern pthread_mutex_t once_epoch_mutex;
|
||||
BOOST_THREAD_DECL extern pthread_cond_t once_epoch_cv;
|
||||
}
|
||||
|
||||
#define BOOST_ONCE_INITIAL_FLAG_VALUE 0
|
||||
#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
|
||||
|
||||
|
||||
// Based on Mike Burrows fast_pthread_once algorithm as described in
|
||||
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html
|
||||
template<typename Function>
|
||||
void call_once(once_flag& flag,Function f)
|
||||
{
|
||||
static boost::uintmax_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
|
||||
static boost::uintmax_t const being_initialized=uninitialized_flag+1;
|
||||
boost::uintmax_t const epoch=flag.epoch;
|
||||
boost::uintmax_t& this_thread_epoch=detail::get_once_per_thread_epoch();
|
||||
|
||||
if(epoch<this_thread_epoch)
|
||||
{
|
||||
pthread::pthread_mutex_scoped_lock lk(&detail::once_epoch_mutex);
|
||||
|
||||
while(flag.epoch<=being_initialized)
|
||||
{
|
||||
if(flag.epoch==uninitialized_flag)
|
||||
{
|
||||
flag.epoch=being_initialized;
|
||||
try
|
||||
{
|
||||
pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex);
|
||||
f();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
flag.epoch=uninitialized_flag;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
|
||||
throw;
|
||||
}
|
||||
flag.epoch=--detail::once_global_epoch;
|
||||
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
|
||||
}
|
||||
else
|
||||
{
|
||||
while(flag.epoch==being_initialized)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_wait(&detail::once_epoch_cv,&detail::once_epoch_mutex));
|
||||
}
|
||||
}
|
||||
}
|
||||
this_thread_epoch=detail::once_global_epoch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,50 +0,0 @@
|
||||
#ifndef BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP
|
||||
#define BOOST_PTHREAD_MUTEX_SCOPED_LOCK_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 <pthread.h>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace pthread
|
||||
{
|
||||
class pthread_mutex_scoped_lock
|
||||
{
|
||||
pthread_mutex_t* m;
|
||||
public:
|
||||
explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_):
|
||||
m(m_)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_lock(m));
|
||||
}
|
||||
~pthread_mutex_scoped_lock()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class pthread_mutex_scoped_unlock
|
||||
{
|
||||
pthread_mutex_t* m;
|
||||
public:
|
||||
explicit pthread_mutex_scoped_unlock(pthread_mutex_t* m_):
|
||||
m(m_)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(m));
|
||||
}
|
||||
~pthread_mutex_scoped_unlock()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_lock(m));
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,249 +0,0 @@
|
||||
#ifndef BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
|
||||
#define BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_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 <pthread.h>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <boost/date_time/posix_time/conversion.hpp>
|
||||
#include <errno.h>
|
||||
#include "timespec.hpp"
|
||||
#include "pthread_mutex_scoped_lock.hpp"
|
||||
|
||||
#ifdef _POSIX_TIMEOUTS
|
||||
#if _POSIX_TIMEOUTS >= 0
|
||||
#define BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class recursive_mutex:
|
||||
boost::noncopyable
|
||||
{
|
||||
private:
|
||||
pthread_mutex_t m;
|
||||
public:
|
||||
recursive_mutex()
|
||||
{
|
||||
pthread_mutexattr_t attr;
|
||||
|
||||
int const init_attr_res=pthread_mutexattr_init(&attr);
|
||||
if(init_attr_res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
}
|
||||
int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
|
||||
if(set_attr_res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
}
|
||||
|
||||
int const res=pthread_mutex_init(&m,&attr);
|
||||
if(res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
}
|
||||
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
|
||||
}
|
||||
~recursive_mutex()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_lock(&m));
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(&m));
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
int const res=pthread_mutex_trylock(&m);
|
||||
BOOST_ASSERT(!res || res==EBUSY);
|
||||
return !res;
|
||||
}
|
||||
typedef unique_lock<recursive_mutex> scoped_lock;
|
||||
typedef scoped_lock scoped_try_lock;
|
||||
};
|
||||
|
||||
typedef recursive_mutex recursive_try_mutex;
|
||||
|
||||
class recursive_timed_mutex:
|
||||
boost::noncopyable
|
||||
{
|
||||
private:
|
||||
pthread_mutex_t m;
|
||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
pthread_cond_t cond;
|
||||
bool is_locked;
|
||||
pthread_t owner;
|
||||
unsigned count;
|
||||
#endif
|
||||
public:
|
||||
recursive_timed_mutex()
|
||||
{
|
||||
#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
pthread_mutexattr_t attr;
|
||||
|
||||
int const init_attr_res=pthread_mutexattr_init(&attr);
|
||||
if(init_attr_res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
}
|
||||
int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
|
||||
if(set_attr_res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
}
|
||||
|
||||
int const res=pthread_mutex_init(&m,&attr);
|
||||
if(res)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
|
||||
throw thread_resource_error();
|
||||
}
|
||||
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
|
||||
#else
|
||||
int const res=pthread_mutex_init(&m,NULL);
|
||||
if(res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
}
|
||||
int const res2=pthread_cond_init(&cond,NULL);
|
||||
if(res2)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
throw thread_resource_error();
|
||||
}
|
||||
is_locked=false;
|
||||
count=0;
|
||||
#endif
|
||||
}
|
||||
~recursive_timed_mutex()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_destroy(&m));
|
||||
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
BOOST_VERIFY(!pthread_cond_destroy(&cond));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename TimeDuration>
|
||||
bool timed_lock(TimeDuration const & relative_time)
|
||||
{
|
||||
return timed_lock(get_system_time()+relative_time);
|
||||
}
|
||||
|
||||
#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
|
||||
void lock()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_lock(&m));
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
BOOST_VERIFY(!pthread_mutex_unlock(&m));
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
int const res=pthread_mutex_trylock(&m);
|
||||
BOOST_ASSERT(!res || res==EBUSY);
|
||||
return !res;
|
||||
}
|
||||
bool timed_lock(system_time const & abs_time)
|
||||
{
|
||||
struct timespec const timeout=detail::get_timespec(abs_time);
|
||||
int const res=pthread_mutex_timedlock(&m,&timeout);
|
||||
BOOST_ASSERT(!res || res==EBUSY);
|
||||
return !res;
|
||||
}
|
||||
#else
|
||||
void lock()
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||
if(is_locked && pthread_equal(owner,pthread_self()))
|
||||
{
|
||||
++count;
|
||||
return;
|
||||
}
|
||||
|
||||
while(is_locked)
|
||||
{
|
||||
BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
|
||||
}
|
||||
is_locked=true;
|
||||
++count;
|
||||
owner=pthread_self();
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||
if(!--count)
|
||||
{
|
||||
is_locked=false;
|
||||
}
|
||||
BOOST_VERIFY(!pthread_cond_signal(&cond));
|
||||
}
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||
if(is_locked && !pthread_equal(owner,pthread_self()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
is_locked=true;
|
||||
++count;
|
||||
owner=pthread_self();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool timed_lock(system_time const & abs_time)
|
||||
{
|
||||
struct timespec const timeout=detail::get_timespec(abs_time);
|
||||
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
|
||||
if(is_locked && pthread_equal(owner,pthread_self()))
|
||||
{
|
||||
++count;
|
||||
return true;
|
||||
}
|
||||
while(is_locked)
|
||||
{
|
||||
int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
|
||||
if(cond_res==ETIMEDOUT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
BOOST_ASSERT(!cond_res);
|
||||
}
|
||||
is_locked=true;
|
||||
++count;
|
||||
owner=pthread_self();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
|
||||
typedef scoped_timed_lock scoped_try_lock;
|
||||
typedef scoped_timed_lock scoped_lock;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,307 +0,0 @@
|
||||
#ifndef BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
|
||||
#define BOOST_THREAD_PTHREAD_SHARED_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/thread.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class shared_mutex
|
||||
{
|
||||
private:
|
||||
struct state_data
|
||||
{
|
||||
unsigned shared_count;
|
||||
bool exclusive;
|
||||
bool upgrade;
|
||||
bool exclusive_waiting_blocked;
|
||||
};
|
||||
|
||||
|
||||
|
||||
state_data state;
|
||||
boost::mutex state_change;
|
||||
boost::condition_variable shared_cond;
|
||||
boost::condition_variable exclusive_cond;
|
||||
boost::condition_variable upgrade_cond;
|
||||
|
||||
void release_waiters()
|
||||
{
|
||||
exclusive_cond.notify_one();
|
||||
shared_cond.notify_all();
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
shared_mutex()
|
||||
{
|
||||
state_data state_={0};
|
||||
state=state_;
|
||||
}
|
||||
|
||||
~shared_mutex()
|
||||
{
|
||||
}
|
||||
|
||||
void lock_shared()
|
||||
{
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
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_shared()
|
||||
{
|
||||
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_shared(system_time const& timeout)
|
||||
{
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
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_shared()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
bool const last_reader=!--state.shared_count;
|
||||
|
||||
if(last_reader)
|
||||
{
|
||||
if(state.upgrade)
|
||||
{
|
||||
state.upgrade=false;
|
||||
state.exclusive=true;
|
||||
upgrade_cond.notify_one();
|
||||
}
|
||||
else
|
||||
{
|
||||
state.exclusive_waiting_blocked=false;
|
||||
}
|
||||
release_waiters();
|
||||
}
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
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(system_time const& timeout)
|
||||
{
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
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_upgrade()
|
||||
{
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
while(true)
|
||||
{
|
||||
if(!state.exclusive && !state.exclusive_waiting_blocked && !state.upgrade)
|
||||
{
|
||||
++state.shared_count;
|
||||
state.upgrade=true;
|
||||
return;
|
||||
}
|
||||
|
||||
shared_cond.wait(lock);
|
||||
}
|
||||
}
|
||||
|
||||
bool timed_lock_upgrade(system_time const& timeout)
|
||||
{
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
while(true)
|
||||
{
|
||||
if(!state.exclusive && !state.exclusive_waiting_blocked && !state.upgrade)
|
||||
{
|
||||
++state.shared_count;
|
||||
state.upgrade=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!shared_cond.timed_wait(lock,timeout))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool try_lock_upgrade()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
++state.shared_count;
|
||||
state.upgrade=true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void unlock_upgrade()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
state.upgrade=false;
|
||||
bool const last_reader=!--state.shared_count;
|
||||
|
||||
if(last_reader)
|
||||
{
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
}
|
||||
}
|
||||
|
||||
void unlock_upgrade_and_lock()
|
||||
{
|
||||
boost::this_thread::disable_interruption do_not_disturb;
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
--state.shared_count;
|
||||
while(true)
|
||||
{
|
||||
if(!state.shared_count)
|
||||
{
|
||||
state.upgrade=false;
|
||||
state.exclusive=true;
|
||||
break;
|
||||
}
|
||||
upgrade_cond.wait(lock);
|
||||
}
|
||||
}
|
||||
|
||||
void unlock_and_lock_upgrade()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
state.exclusive=false;
|
||||
state.upgrade=true;
|
||||
++state.shared_count;
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
}
|
||||
|
||||
void unlock_and_lock_shared()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
state.exclusive=false;
|
||||
++state.shared_count;
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
}
|
||||
|
||||
void unlock_upgrade_and_lock_shared()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(state_change);
|
||||
state.upgrade=false;
|
||||
state.exclusive_waiting_blocked=false;
|
||||
release_waiters();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,316 +0,0 @@
|
||||
#ifndef BOOST_THREAD_THREAD_PTHREAD_HPP
|
||||
#define BOOST_THREAD_THREAD_PTHREAD_HPP
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// Copyright (C) 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/detail/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition_variable.hpp>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include "thread_data.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class thread;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class thread_id;
|
||||
}
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
BOOST_THREAD_DECL detail::thread_id get_id();
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class thread_id
|
||||
{
|
||||
private:
|
||||
detail::thread_data_ptr thread_data;
|
||||
|
||||
thread_id(detail::thread_data_ptr thread_data_):
|
||||
thread_data(thread_data_)
|
||||
{}
|
||||
friend class boost::thread;
|
||||
friend thread_id this_thread::get_id();
|
||||
public:
|
||||
thread_id():
|
||||
thread_data()
|
||||
{}
|
||||
|
||||
bool operator==(const thread_id& y) const
|
||||
{
|
||||
return thread_data==y.thread_data;
|
||||
}
|
||||
|
||||
bool operator!=(const thread_id& y) const
|
||||
{
|
||||
return thread_data!=y.thread_data;
|
||||
}
|
||||
|
||||
bool operator<(const thread_id& y) const
|
||||
{
|
||||
return thread_data<y.thread_data;
|
||||
}
|
||||
|
||||
bool operator>(const thread_id& y) const
|
||||
{
|
||||
return y.thread_data<thread_data;
|
||||
}
|
||||
|
||||
bool operator<=(const thread_id& y) const
|
||||
{
|
||||
return !(y.thread_data<thread_data);
|
||||
}
|
||||
|
||||
bool operator>=(const thread_id& y) const
|
||||
{
|
||||
return !(thread_data<y.thread_data);
|
||||
}
|
||||
|
||||
template<class charT, class traits>
|
||||
friend std::basic_ostream<charT, traits>&
|
||||
operator<<(std::basic_ostream<charT, traits>& os, const thread_id& x)
|
||||
{
|
||||
if(x.thread_data)
|
||||
{
|
||||
return os<<x.thread_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return os<<"{Not-any-thread}";
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
struct xtime;
|
||||
class BOOST_THREAD_DECL thread
|
||||
{
|
||||
private:
|
||||
thread(thread&);
|
||||
thread& operator=(thread&);
|
||||
|
||||
template<typename F>
|
||||
struct thread_data:
|
||||
detail::thread_data_base
|
||||
{
|
||||
F f;
|
||||
|
||||
thread_data(F f_):
|
||||
f(f_)
|
||||
{}
|
||||
thread_data(detail::thread_move_t<F> f_):
|
||||
f(f_)
|
||||
{}
|
||||
|
||||
void run()
|
||||
{
|
||||
f();
|
||||
}
|
||||
};
|
||||
|
||||
mutable boost::mutex thread_info_mutex;
|
||||
detail::thread_data_ptr thread_info;
|
||||
|
||||
void start_thread();
|
||||
|
||||
explicit thread(detail::thread_data_ptr data);
|
||||
|
||||
detail::thread_data_ptr get_thread_info() const;
|
||||
|
||||
public:
|
||||
thread();
|
||||
~thread();
|
||||
|
||||
template <class F>
|
||||
explicit thread(F f):
|
||||
thread_info(new thread_data<F>(f))
|
||||
{
|
||||
start_thread();
|
||||
}
|
||||
template <class F>
|
||||
thread(detail::thread_move_t<F> f):
|
||||
thread_info(new thread_data<F>(f))
|
||||
{
|
||||
start_thread();
|
||||
}
|
||||
|
||||
thread(detail::thread_move_t<thread> x);
|
||||
thread& operator=(detail::thread_move_t<thread> x);
|
||||
operator detail::thread_move_t<thread>();
|
||||
detail::thread_move_t<thread> move();
|
||||
|
||||
void swap(thread& x);
|
||||
|
||||
typedef detail::thread_id id;
|
||||
|
||||
id get_id() const;
|
||||
|
||||
bool joinable() const;
|
||||
void join();
|
||||
bool timed_join(const system_time& wait_until);
|
||||
|
||||
template<typename TimeDuration>
|
||||
inline bool timed_join(TimeDuration const& rel_time)
|
||||
{
|
||||
return timed_join(get_system_time()+rel_time);
|
||||
}
|
||||
void detach();
|
||||
|
||||
static unsigned hardware_concurrency();
|
||||
|
||||
// backwards compatibility
|
||||
bool operator==(const thread& other) const;
|
||||
bool operator!=(const thread& other) const;
|
||||
|
||||
static void sleep(const system_time& xt);
|
||||
static void yield();
|
||||
|
||||
// extensions
|
||||
void interrupt();
|
||||
bool interruption_requested() const;
|
||||
};
|
||||
|
||||
inline detail::thread_move_t<thread> move(thread& x)
|
||||
{
|
||||
return x.move();
|
||||
}
|
||||
|
||||
inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
template<typename F>
|
||||
struct thread::thread_data<boost::reference_wrapper<F> >:
|
||||
detail::thread_data_base
|
||||
{
|
||||
F& f;
|
||||
|
||||
thread_data(boost::reference_wrapper<F> f_):
|
||||
f(f_)
|
||||
{}
|
||||
|
||||
void run()
|
||||
{
|
||||
f();
|
||||
}
|
||||
};
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
class BOOST_THREAD_DECL disable_interruption
|
||||
{
|
||||
disable_interruption(const disable_interruption&);
|
||||
disable_interruption& operator=(const disable_interruption&);
|
||||
|
||||
bool interruption_was_enabled;
|
||||
friend class restore_interruption;
|
||||
public:
|
||||
disable_interruption();
|
||||
~disable_interruption();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL restore_interruption
|
||||
{
|
||||
restore_interruption(const restore_interruption&);
|
||||
restore_interruption& operator=(const restore_interruption&);
|
||||
public:
|
||||
explicit restore_interruption(disable_interruption& d);
|
||||
~restore_interruption();
|
||||
};
|
||||
|
||||
BOOST_THREAD_DECL thread::id get_id();
|
||||
|
||||
BOOST_THREAD_DECL void interruption_point();
|
||||
BOOST_THREAD_DECL bool interruption_enabled();
|
||||
BOOST_THREAD_DECL bool interruption_requested();
|
||||
|
||||
inline void yield()
|
||||
{
|
||||
thread::yield();
|
||||
}
|
||||
|
||||
template<typename TimeDuration>
|
||||
inline void sleep(TimeDuration const& rel_time)
|
||||
{
|
||||
thread::sleep(get_system_time()+rel_time);
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct thread_exit_function_base
|
||||
{
|
||||
virtual ~thread_exit_function_base()
|
||||
{}
|
||||
virtual void operator()() const=0;
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
struct thread_exit_function:
|
||||
thread_exit_function_base
|
||||
{
|
||||
F f;
|
||||
|
||||
thread_exit_function(F f_):
|
||||
f(f_)
|
||||
{}
|
||||
|
||||
void operator()() const
|
||||
{
|
||||
f();
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_THREAD_DECL void add_thread_exit_function(thread_exit_function_base*);
|
||||
}
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
template<typename F>
|
||||
inline void at_thread_exit(F f)
|
||||
{
|
||||
detail::thread_exit_function_base* const thread_exit_func=new detail::thread_exit_function<F>(f);
|
||||
detail::add_thread_exit_function(thread_exit_func);
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
void interrupt_all();
|
||||
int size() const;
|
||||
|
||||
private:
|
||||
std::list<thread*> m_threads;
|
||||
mutex m_mutex;
|
||||
};
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,100 +0,0 @@
|
||||
#ifndef BOOST_THREAD_PTHREAD_THREAD_DATA_HPP
|
||||
#define BOOST_THREAD_PTHREAD_THREAD_DATA_HPP
|
||||
// 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
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <pthread.h>
|
||||
#include "condition_variable_fwd.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class thread_interrupted
|
||||
{};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct thread_exit_callback_node;
|
||||
struct tss_data_node;
|
||||
|
||||
struct thread_data_base;
|
||||
typedef boost::shared_ptr<thread_data_base> thread_data_ptr;
|
||||
|
||||
struct thread_data_base:
|
||||
enable_shared_from_this<thread_data_base>
|
||||
{
|
||||
thread_data_ptr self;
|
||||
pthread_t thread_handle;
|
||||
boost::mutex data_mutex;
|
||||
boost::condition_variable done_condition;
|
||||
boost::mutex sleep_mutex;
|
||||
boost::condition_variable sleep_condition;
|
||||
bool done;
|
||||
bool join_started;
|
||||
bool joined;
|
||||
boost::detail::thread_exit_callback_node* thread_exit_callbacks;
|
||||
boost::detail::tss_data_node* tss_data;
|
||||
bool interrupt_enabled;
|
||||
bool interrupt_requested;
|
||||
pthread_cond_t* current_cond;
|
||||
|
||||
thread_data_base():
|
||||
done(false),join_started(false),joined(false),
|
||||
thread_exit_callbacks(0),tss_data(0),
|
||||
interrupt_enabled(true),
|
||||
interrupt_requested(false),
|
||||
current_cond(0)
|
||||
{}
|
||||
virtual ~thread_data_base()
|
||||
{}
|
||||
|
||||
virtual void run()=0;
|
||||
};
|
||||
|
||||
BOOST_THREAD_DECL thread_data_base* get_current_thread_data();
|
||||
|
||||
class interruption_checker
|
||||
{
|
||||
thread_data_base* const thread_info;
|
||||
|
||||
void check_for_interruption()
|
||||
{
|
||||
if(thread_info->interrupt_requested)
|
||||
{
|
||||
thread_info->interrupt_requested=false;
|
||||
throw thread_interrupted();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
explicit interruption_checker(pthread_cond_t* cond):
|
||||
thread_info(detail::get_current_thread_data())
|
||||
{
|
||||
if(thread_info && thread_info->interrupt_enabled)
|
||||
{
|
||||
lock_guard<mutex> guard(thread_info->data_mutex);
|
||||
check_for_interruption();
|
||||
thread_info->current_cond=cond;
|
||||
}
|
||||
}
|
||||
~interruption_checker()
|
||||
{
|
||||
if(thread_info && thread_info->interrupt_enabled)
|
||||
{
|
||||
lock_guard<mutex> guard(thread_info->data_mutex);
|
||||
thread_info->current_cond=NULL;
|
||||
check_for_interruption();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,28 +0,0 @@
|
||||
#ifndef BOOST_THREAD_PTHREAD_TIMESPEC_HPP
|
||||
#define BOOST_THREAD_PTHREAD_TIMESPEC_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/thread_time.hpp>
|
||||
#include <boost/date_time/posix_time/conversion.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
inline struct timespec get_timespec(boost::system_time const& abs_time)
|
||||
{
|
||||
struct timespec timeout={0};
|
||||
boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0);
|
||||
|
||||
timeout.tv_sec=time_since_epoch.total_seconds();
|
||||
timeout.tv_nsec=time_since_epoch.fractional_seconds()*(1000000000/time_since_epoch.ticks_per_second());
|
||||
return timeout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,103 +0,0 @@
|
||||
#ifndef BOOST_THREAD_PTHREAD_TSS_HPP
|
||||
#define BOOST_THREAD_PTHREAD_TSS_HPP
|
||||
|
||||
// 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
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct tss_cleanup_function
|
||||
{
|
||||
virtual ~tss_cleanup_function()
|
||||
{}
|
||||
|
||||
virtual void operator()(void* data)=0;
|
||||
};
|
||||
|
||||
BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
|
||||
BOOST_THREAD_DECL void* get_tss_data(void const* key);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class thread_specific_ptr
|
||||
{
|
||||
private:
|
||||
thread_specific_ptr(thread_specific_ptr&);
|
||||
thread_specific_ptr& operator=(thread_specific_ptr&);
|
||||
|
||||
struct delete_data:
|
||||
detail::tss_cleanup_function
|
||||
{
|
||||
void operator()(void* data)
|
||||
{
|
||||
delete static_cast<T*>(data);
|
||||
}
|
||||
};
|
||||
|
||||
struct run_custom_cleanup_function:
|
||||
detail::tss_cleanup_function
|
||||
{
|
||||
void (*cleanup_function)(T*);
|
||||
|
||||
explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)):
|
||||
cleanup_function(cleanup_function_)
|
||||
{}
|
||||
|
||||
void operator()(void* data)
|
||||
{
|
||||
cleanup_function(static_cast<T*>(data));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
boost::shared_ptr<detail::tss_cleanup_function> cleanup;
|
||||
|
||||
public:
|
||||
thread_specific_ptr():
|
||||
cleanup(new delete_data)
|
||||
{}
|
||||
explicit thread_specific_ptr(void (*func_)(T*)):
|
||||
cleanup(new run_custom_cleanup_function(func_))
|
||||
{}
|
||||
~thread_specific_ptr()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
T* get() const
|
||||
{
|
||||
return static_cast<T*>(detail::get_tss_data(this));
|
||||
}
|
||||
T* operator->() const
|
||||
{
|
||||
return get();
|
||||
}
|
||||
T& operator*() const
|
||||
{
|
||||
return *get();
|
||||
}
|
||||
T* release()
|
||||
{
|
||||
T* const temp=get();
|
||||
detail::set_tss_data(this,0,0,false);
|
||||
return temp;
|
||||
}
|
||||
void reset(T* new_value=0)
|
||||
{
|
||||
T* const current_value=get();
|
||||
if(current_value!=new_value)
|
||||
{
|
||||
detail::set_tss_data(this,cleanup,new_value,true);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
271
include/boost/thread/read_write_mutex.hpp
Normal file
271
include/boost/thread/read_write_mutex.hpp
Normal file
@@ -0,0 +1,271 @@
|
||||
// Copyright (C) 2002-2003
|
||||
// David Moore, William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. David Moore makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
// A Boost::threads implementation of a synchronization
|
||||
// primitive which can allow multiple readers or a single
|
||||
// writer to have access to a shared resource.
|
||||
|
||||
#ifndef BOOST_READ_WRITE_MUTEX_JDM030602_HPP
|
||||
#define BOOST_READ_WRITE_MUTEX_JDM030602_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/detail/lock.hpp>
|
||||
#include <boost/thread/detail/read_write_lock.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace read_write_scheduling_policy {
|
||||
enum read_write_scheduling_policy_enum
|
||||
{
|
||||
writer_priority, //Prefer writers; can starve readers
|
||||
reader_priority, //Prefer readers; can starve writers
|
||||
alternating_many_reads, //Alternate readers and writers; before a writer, release all queued readers
|
||||
alternating_single_read //Alternate readers and writers; before a writer, release only on queued reader
|
||||
};
|
||||
} // namespace read_write_scheduling_policy
|
||||
|
||||
namespace detail {
|
||||
|
||||
namespace thread {
|
||||
|
||||
// Shared implementation construct for explicit Scheduling Policies
|
||||
// This implementation is susceptible to self-deadlock, though....
|
||||
template<typename Mutex>
|
||||
struct read_write_mutex_impl
|
||||
{
|
||||
typedef Mutex mutex_type;
|
||||
typedef detail::thread::scoped_lock<Mutex> scoped_lock;
|
||||
typedef detail::thread::scoped_try_lock<Mutex> scoped_try_lock;
|
||||
typedef detail::thread::scoped_timed_lock<Mutex> scoped_timed_lock;
|
||||
|
||||
read_write_mutex_impl(read_write_scheduling_policy::read_write_scheduling_policy_enum sp)
|
||||
: m_num_waiting_writers(0),
|
||||
m_num_waiting_readers(0),
|
||||
m_num_readers_to_wake(0),
|
||||
m_state_waiting_promotion(false),
|
||||
m_state(0),
|
||||
m_sp(sp),
|
||||
m_readers_next(true) { }
|
||||
|
||||
Mutex m_prot;
|
||||
boost::condition m_waiting_writers;
|
||||
boost::condition m_waiting_readers;
|
||||
int m_num_waiting_writers;
|
||||
int m_num_waiting_readers;
|
||||
int m_num_readers_to_wake;
|
||||
boost::condition m_waiting_promotion;
|
||||
bool m_state_waiting_promotion;
|
||||
int m_state; // -1 = excl locked
|
||||
// 0 = unlocked
|
||||
// 1-> INT_MAX - shared locked
|
||||
const read_write_scheduling_policy::read_write_scheduling_policy_enum m_sp;
|
||||
bool m_readers_next;
|
||||
|
||||
void do_read_lock();
|
||||
void do_write_lock();
|
||||
void do_write_unlock();
|
||||
void do_read_unlock();
|
||||
bool do_try_write_lock();
|
||||
bool do_try_read_lock();
|
||||
bool do_timed_write_lock(const xtime &xt);
|
||||
bool do_timed_read_lock(const xtime &xt);
|
||||
|
||||
void do_demote_to_read_lock();
|
||||
bool do_try_demote_to_read_lock();
|
||||
bool do_timed_demote_to_read_lock(const xtime &xt);
|
||||
|
||||
void do_promote_to_write_lock();
|
||||
bool do_try_promote_to_write_lock();
|
||||
bool do_timed_promote_to_write_lock(const xtime &xt);
|
||||
|
||||
bool locked();
|
||||
read_write_lock_state::read_write_lock_state_enum state();
|
||||
|
||||
private:
|
||||
|
||||
void do_unlock_scheduling_impl();
|
||||
void do_demote_scheduling_impl();
|
||||
void do_scheduling_impl();
|
||||
bool do_demote_to_read_lock_impl();
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace thread
|
||||
|
||||
class BOOST_THREAD_DECL read_write_mutex : private noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
read_write_mutex(read_write_scheduling_policy::read_write_scheduling_policy_enum sp) : m_impl(sp) { }
|
||||
~read_write_mutex() { }
|
||||
|
||||
read_write_scheduling_policy::read_write_scheduling_policy_enum policy() const { return m_impl.m_sp; }
|
||||
|
||||
friend class detail::thread::read_write_lock_ops<read_write_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_read_write_lock<
|
||||
read_write_mutex> scoped_read_write_lock;
|
||||
|
||||
typedef detail::thread::scoped_read_lock<
|
||||
read_write_mutex> scoped_read_lock;
|
||||
|
||||
typedef detail::thread::scoped_write_lock<
|
||||
read_write_mutex> scoped_write_lock;
|
||||
|
||||
private:
|
||||
|
||||
// Operations that will eventually be done only
|
||||
// via lock types
|
||||
void do_write_lock();
|
||||
void do_read_lock();
|
||||
void do_write_unlock();
|
||||
void do_read_unlock();
|
||||
|
||||
void do_demote_to_read_lock();
|
||||
|
||||
void do_promote_to_write_lock();
|
||||
|
||||
bool locked();
|
||||
read_write_lock_state::read_write_lock_state_enum state();
|
||||
|
||||
detail::thread::read_write_mutex_impl<mutex> m_impl;
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL try_read_write_mutex : private noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
try_read_write_mutex(read_write_scheduling_policy::read_write_scheduling_policy_enum sp) : m_impl(sp) { }
|
||||
~try_read_write_mutex() { }
|
||||
|
||||
read_write_scheduling_policy::read_write_scheduling_policy_enum policy() const { return m_impl.m_sp; }
|
||||
|
||||
friend class detail::thread::read_write_lock_ops<try_read_write_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_read_write_lock<
|
||||
try_read_write_mutex> scoped_read_write_lock;
|
||||
typedef detail::thread::scoped_try_read_write_lock<
|
||||
try_read_write_mutex> scoped_try_read_write_lock;
|
||||
|
||||
typedef detail::thread::scoped_read_lock<
|
||||
try_read_write_mutex> scoped_read_lock;
|
||||
typedef detail::thread::scoped_try_read_lock<
|
||||
try_read_write_mutex> scoped_try_read_lock;
|
||||
|
||||
typedef detail::thread::scoped_write_lock<
|
||||
try_read_write_mutex> scoped_write_lock;
|
||||
typedef detail::thread::scoped_try_write_lock<
|
||||
try_read_write_mutex> scoped_try_write_lock;
|
||||
|
||||
private:
|
||||
|
||||
// Operations that will eventually be done only
|
||||
// via lock types
|
||||
void do_write_lock();
|
||||
void do_read_lock();
|
||||
void do_write_unlock();
|
||||
void do_read_unlock();
|
||||
bool do_try_write_lock();
|
||||
bool do_try_read_lock();
|
||||
|
||||
|
||||
void do_demote_to_read_lock();
|
||||
bool do_try_demote_to_read_lock();
|
||||
|
||||
void do_promote_to_write_lock();
|
||||
bool do_try_promote_to_write_lock();
|
||||
|
||||
bool locked();
|
||||
read_write_lock_state::read_write_lock_state_enum state();
|
||||
|
||||
detail::thread::read_write_mutex_impl<try_mutex> m_impl;
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL timed_read_write_mutex : private noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
timed_read_write_mutex(read_write_scheduling_policy::read_write_scheduling_policy_enum sp) : m_impl(sp) { }
|
||||
~timed_read_write_mutex() { }
|
||||
|
||||
read_write_scheduling_policy::read_write_scheduling_policy_enum policy() const { return m_impl.m_sp; }
|
||||
|
||||
friend class detail::thread::read_write_lock_ops<timed_read_write_mutex>;
|
||||
|
||||
typedef detail::thread::scoped_read_write_lock<
|
||||
timed_read_write_mutex> scoped_read_write_lock;
|
||||
typedef detail::thread::scoped_try_read_write_lock<
|
||||
timed_read_write_mutex> scoped_try_read_write_lock;
|
||||
typedef detail::thread::scoped_timed_read_write_lock<
|
||||
timed_read_write_mutex> scoped_timed_read_write_lock;
|
||||
|
||||
typedef detail::thread::scoped_read_lock<
|
||||
timed_read_write_mutex> scoped_read_lock;
|
||||
typedef detail::thread::scoped_try_read_lock<
|
||||
timed_read_write_mutex> scoped_try_read_lock;
|
||||
typedef detail::thread::scoped_timed_read_lock<
|
||||
timed_read_write_mutex> scoped_timed_read_lock;
|
||||
|
||||
typedef detail::thread::scoped_write_lock<
|
||||
timed_read_write_mutex> scoped_write_lock;
|
||||
typedef detail::thread::scoped_try_write_lock<
|
||||
timed_read_write_mutex> scoped_try_write_lock;
|
||||
typedef detail::thread::scoped_timed_write_lock<
|
||||
timed_read_write_mutex> scoped_timed_write_lock;
|
||||
|
||||
private:
|
||||
|
||||
// Operations that will eventually be done only
|
||||
// via lock types
|
||||
void do_write_lock();
|
||||
void do_read_lock();
|
||||
void do_write_unlock();
|
||||
void do_read_unlock();
|
||||
bool do_try_write_lock();
|
||||
bool do_try_read_lock();
|
||||
bool do_timed_write_lock(const xtime &xt);
|
||||
bool do_timed_read_lock(const xtime &xt);
|
||||
|
||||
void do_demote_to_read_lock();
|
||||
bool do_try_demote_to_read_lock();
|
||||
bool do_timed_demote_to_read_lock(const xtime &xt);
|
||||
|
||||
void do_promote_to_write_lock();
|
||||
bool do_try_promote_to_write_lock();
|
||||
bool do_timed_promote_to_write_lock(const xtime &xt);
|
||||
|
||||
bool locked();
|
||||
read_write_lock_state::read_write_lock_state_enum state();
|
||||
|
||||
detail::thread::read_write_mutex_impl<timed_mutex> m_impl;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
// Change Log:
|
||||
// 10 Mar 02
|
||||
// Original version.
|
||||
// 4 May 04 GlassfordM
|
||||
// Implement lock promotion and demotion.
|
||||
// Add locked() and state() member functions for debugging
|
||||
// (should these be made public?).
|
||||
// Rename to improve consistency and eliminate abbreviations:
|
||||
// Use "read" and "write" instead of "shared" and "exclusive".
|
||||
// Change "rd" to "read", "wr" to "write", "rw" to "read_write".
|
||||
// Add mutex_type typdef.
|
||||
@@ -1,21 +1,186 @@
|
||||
#ifndef BOOST_THREAD_RECURSIVE_MUTEX_HPP
|
||||
#define BOOST_THREAD_RECURSIVE_MUTEX_HPP
|
||||
|
||||
// recursive_mutex.hpp
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// (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)
|
||||
// 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/platform.hpp>
|
||||
#if defined(BOOST_THREAD_PLATFORM_WIN32)
|
||||
#include <boost/thread/win32/recursive_mutex.hpp>
|
||||
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
|
||||
#include <boost/thread/pthread/recursive_mutex.hpp>
|
||||
#else
|
||||
#error "Boost threads unavailable on this platform"
|
||||
#ifndef BOOST_RECURSIVE_MUTEX_WEK070601_HPP
|
||||
#define BOOST_RECURSIVE_MUTEX_WEK070601_HPP
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/detail/lock.hpp>
|
||||
#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.
|
||||
58
include/boost/thread/shared_memory.hpp
Normal file
58
include/boost/thread/shared_memory.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
// 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,21 +0,0 @@
|
||||
#ifndef BOOST_THREAD_SHARED_MUTEX_HPP
|
||||
#define BOOST_THREAD_SHARED_MUTEX_HPP
|
||||
|
||||
// shared_mutex.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/detail/platform.hpp>
|
||||
#if defined(BOOST_THREAD_PLATFORM_WIN32)
|
||||
#include <boost/thread/win32/shared_mutex.hpp>
|
||||
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
|
||||
#include <boost/thread/pthread/shared_mutex.hpp>
|
||||
#else
|
||||
#error "Boost threads unavailable on this platform"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,22 +1,193 @@
|
||||
#ifndef BOOST_THREAD_THREAD_HPP
|
||||
#define BOOST_THREAD_THREAD_HPP
|
||||
|
||||
// thread.hpp
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// (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)
|
||||
// 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/platform.hpp>
|
||||
#ifndef BOOST_THREAD_WEK070601_HPP
|
||||
#define BOOST_THREAD_WEK070601_HPP
|
||||
|
||||
#if defined(BOOST_THREAD_PLATFORM_WIN32)
|
||||
#include <boost/thread/win32/thread.hpp>
|
||||
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
|
||||
#include <boost/thread/pthread/thread.hpp>
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
# include <boost/thread/condition.hpp>
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
# include <Multiprocessing.h>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct xtime;
|
||||
|
||||
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
|
||||
#error "Boost threads unavailable on this platform"
|
||||
typedef const void* id_type;
|
||||
#endif
|
||||
|
||||
#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.
|
||||
|
||||
44
include/boost/thread/thread_pool.hpp
Normal file
44
include/boost/thread/thread_pool.hpp
Normal file
@@ -0,0 +1,44 @@
|
||||
// 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,46 +0,0 @@
|
||||
#ifndef BOOST_THREAD_TIME_HPP
|
||||
#define BOOST_THREAD_TIME_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/date_time/microsec_time_clock.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
typedef boost::posix_time::ptime system_time;
|
||||
|
||||
inline system_time get_system_time()
|
||||
{
|
||||
return boost::date_time::microsec_clock<system_time>::universal_time();
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
inline system_time get_system_time_sentinel()
|
||||
{
|
||||
return system_time(boost::posix_time::pos_infin);
|
||||
}
|
||||
|
||||
inline unsigned long get_milliseconds_until(system_time const& target_time)
|
||||
{
|
||||
if(target_time.is_pos_infinity())
|
||||
{
|
||||
return ~(unsigned long)0;
|
||||
}
|
||||
system_time const now=get_system_time();
|
||||
if(target_time<=now)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return static_cast<unsigned long>((target_time-now).total_milliseconds()+1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,18 +1,121 @@
|
||||
// Copyright (C) 2007 Anthony Williams
|
||||
// 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.
|
||||
|
||||
#ifndef BOOST_THREAD_TSS_HPP
|
||||
#define BOOST_THREAD_TSS_HPP
|
||||
#ifndef BOOST_TSS_WEK070601_HPP
|
||||
#define BOOST_TSS_WEK070601_HPP
|
||||
|
||||
#include <boost/thread/detail/platform.hpp>
|
||||
#if defined(BOOST_THREAD_PLATFORM_WIN32)
|
||||
#include <boost/thread/win32/tss.hpp>
|
||||
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
|
||||
#include <boost/thread/pthread/tss.hpp>
|
||||
#else
|
||||
#error "Boost threads unavailable on this platform"
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS)
|
||||
# include <pthread.h>
|
||||
#elif defined(BOOST_HAS_MPTASKS)
|
||||
# include <Multiprocessing.h>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class 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().
|
||||
@@ -1,126 +0,0 @@
|
||||
#ifndef BOOST_BASIC_RECURSIVE_MUTEX_WIN32_HPP
|
||||
#define BOOST_BASIC_RECURSIVE_MUTEX_WIN32_HPP
|
||||
|
||||
// basic_recursive_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 "thread_primitives.hpp"
|
||||
#include "basic_timed_mutex.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::system_time const& target)
|
||||
{
|
||||
long const current_thread_id=win32::GetCurrentThreadId();
|
||||
return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target);
|
||||
}
|
||||
template<typename Duration>
|
||||
bool timed_lock(Duration const& timeout)
|
||||
{
|
||||
return timed_lock(get_system_time()+timeout);
|
||||
}
|
||||
|
||||
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_acquire(&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::system_time 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
|
||||
@@ -1,163 +0,0 @@
|
||||
#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 "thread_primitives.hpp"
|
||||
#include "interlocked_read.hpp"
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#include <boost/detail/interlocked.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct basic_timed_mutex
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(long,lock_flag_value=0x80000000);
|
||||
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=active_count&~lock_flag_value;
|
||||
do
|
||||
{
|
||||
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;
|
||||
}
|
||||
while(!(old_count&lock_flag_value));
|
||||
return false;
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
|
||||
}
|
||||
bool timed_lock(::boost::system_time const& wait_until)
|
||||
{
|
||||
long old_count=active_count;
|
||||
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(wait_until))!=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;
|
||||
}
|
||||
|
||||
template<typename Duration>
|
||||
bool timed_lock(Duration const& timeout)
|
||||
{
|
||||
return timed_lock(get_system_time()+timeout);
|
||||
}
|
||||
|
||||
long get_active_count()
|
||||
{
|
||||
return ::boost::detail::interlocked_read_acquire(&active_count);
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
long const offset=lock_flag_value+1;
|
||||
long old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,(~offset)+1);
|
||||
|
||||
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_acquire(&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
|
||||
@@ -1,361 +0,0 @@
|
||||
#ifndef BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP
|
||||
#define BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP
|
||||
// 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
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include "thread_primitives.hpp"
|
||||
#include <limits.h>
|
||||
#include <boost/assert.hpp>
|
||||
#include <algorithm>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#include "interlocked_read.hpp"
|
||||
#include <boost/thread/xtime.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
class basic_condition_variable
|
||||
{
|
||||
boost::mutex internal_mutex;
|
||||
long total_count;
|
||||
unsigned active_generation_count;
|
||||
|
||||
struct list_entry
|
||||
{
|
||||
detail::win32::handle semaphore;
|
||||
long count;
|
||||
bool notified;
|
||||
|
||||
list_entry():
|
||||
semaphore(0),count(0),notified(0)
|
||||
{}
|
||||
};
|
||||
|
||||
BOOST_STATIC_CONSTANT(unsigned,generation_count=3);
|
||||
|
||||
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()
|
||||
{
|
||||
list_entry* const last_active_entry=std::remove_if(generations,generations+generation_count,no_waiters);
|
||||
if(last_active_entry==generations+generation_count)
|
||||
{
|
||||
broadcast_entry(generations[generation_count-1],false);
|
||||
}
|
||||
else
|
||||
{
|
||||
active_generation_count=(last_active_entry-generations)+1;
|
||||
}
|
||||
|
||||
std::copy_backward(generations,generations+active_generation_count-1,generations+active_generation_count);
|
||||
generations[0]=list_entry();
|
||||
}
|
||||
|
||||
void broadcast_entry(list_entry& entry,bool wake)
|
||||
{
|
||||
long const count_to_wake=entry.count;
|
||||
detail::interlocked_write_release(&total_count,total_count-count_to_wake);
|
||||
if(wake)
|
||||
{
|
||||
detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0);
|
||||
}
|
||||
detail::win32::ReleaseSemaphore(entry.semaphore,count_to_wake,0);
|
||||
entry.count=0;
|
||||
dispose_entry(entry);
|
||||
}
|
||||
|
||||
|
||||
void dispose_entry(list_entry& entry)
|
||||
{
|
||||
if(entry.semaphore)
|
||||
{
|
||||
BOOST_VERIFY(detail::win32::CloseHandle(entry.semaphore));
|
||||
entry.semaphore=0;
|
||||
}
|
||||
entry.notified=false;
|
||||
}
|
||||
|
||||
template<typename lock_type>
|
||||
struct relocker
|
||||
{
|
||||
lock_type& lock;
|
||||
bool unlocked;
|
||||
|
||||
relocker(lock_type& lock_):
|
||||
lock(lock_),unlocked(false)
|
||||
{}
|
||||
void unlock()
|
||||
{
|
||||
lock.unlock();
|
||||
unlocked=true;
|
||||
}
|
||||
~relocker()
|
||||
{
|
||||
if(unlocked)
|
||||
{
|
||||
lock.lock();
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename lock_type>
|
||||
void start_wait_loop_first_time(relocker<lock_type>& locker,
|
||||
detail::win32::handle_manager& local_wake_sem)
|
||||
{
|
||||
locker.unlock();
|
||||
if(!wake_sem)
|
||||
{
|
||||
wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
||||
BOOST_ASSERT(wake_sem);
|
||||
}
|
||||
local_wake_sem=detail::win32::duplicate_handle(wake_sem);
|
||||
|
||||
if(generations[0].notified)
|
||||
{
|
||||
shift_generations_down();
|
||||
}
|
||||
else if(!active_generation_count)
|
||||
{
|
||||
active_generation_count=1;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename lock_type>
|
||||
void start_wait_loop(relocker<lock_type>& locker,
|
||||
detail::win32::handle_manager& local_wake_sem,
|
||||
detail::win32::handle_manager& sem)
|
||||
{
|
||||
boost::mutex::scoped_lock internal_lock(internal_mutex);
|
||||
detail::interlocked_write_release(&total_count,total_count+1);
|
||||
if(!local_wake_sem)
|
||||
{
|
||||
start_wait_loop_first_time(locker,local_wake_sem);
|
||||
}
|
||||
if(!generations[0].semaphore)
|
||||
{
|
||||
generations[0].semaphore=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
||||
BOOST_ASSERT(generations[0].semaphore);
|
||||
}
|
||||
++generations[0].count;
|
||||
sem=detail::win32::duplicate_handle(generations[0].semaphore);
|
||||
}
|
||||
|
||||
protected:
|
||||
template<typename lock_type>
|
||||
bool do_wait(lock_type& lock,timeout wait_until)
|
||||
{
|
||||
detail::win32::handle_manager local_wake_sem;
|
||||
detail::win32::handle_manager sem;
|
||||
bool woken=false;
|
||||
|
||||
relocker<lock_type> locker(lock);
|
||||
|
||||
while(!woken)
|
||||
{
|
||||
start_wait_loop(locker,local_wake_sem,sem);
|
||||
|
||||
if(!this_thread::interruptible_wait(sem,wait_until))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return woken;
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
bool do_wait(lock_type& m,timeout const& wait_until,predicate_type pred)
|
||||
{
|
||||
while (!pred())
|
||||
{
|
||||
if(!do_wait(m, wait_until))
|
||||
return pred();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
basic_condition_variable(const basic_condition_variable& other);
|
||||
basic_condition_variable& operator=(const basic_condition_variable& other);
|
||||
public:
|
||||
basic_condition_variable():
|
||||
total_count(0),active_generation_count(0),wake_sem(0)
|
||||
{}
|
||||
|
||||
~basic_condition_variable()
|
||||
{
|
||||
for(unsigned i=0;i<generation_count;++i)
|
||||
{
|
||||
dispose_entry(generations[i]);
|
||||
}
|
||||
detail::win32::CloseHandle(wake_sem);
|
||||
}
|
||||
|
||||
|
||||
void notify_one()
|
||||
{
|
||||
if(detail::interlocked_read_acquire(&total_count))
|
||||
{
|
||||
boost::mutex::scoped_lock internal_lock(internal_mutex);
|
||||
detail::win32::ReleaseSemaphore(wake_sem,1,0);
|
||||
for(unsigned generation=active_generation_count;generation!=0;--generation)
|
||||
{
|
||||
list_entry& entry=generations[generation-1];
|
||||
if(entry.count)
|
||||
{
|
||||
detail::interlocked_write_release(&total_count,total_count-1);
|
||||
entry.notified=true;
|
||||
detail::win32::ReleaseSemaphore(entry.semaphore,1,0);
|
||||
if(!--entry.count)
|
||||
{
|
||||
dispose_entry(entry);
|
||||
if(generation==active_generation_count)
|
||||
{
|
||||
--active_generation_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void notify_all()
|
||||
{
|
||||
if(detail::interlocked_read_acquire(&total_count))
|
||||
{
|
||||
boost::mutex::scoped_lock internal_lock(internal_mutex);
|
||||
for(unsigned generation=active_generation_count;generation!=0;--generation)
|
||||
{
|
||||
list_entry& entry=generations[generation-1];
|
||||
if(entry.count)
|
||||
{
|
||||
broadcast_entry(entry,true);
|
||||
}
|
||||
}
|
||||
active_generation_count=0;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
class condition_variable:
|
||||
public detail::basic_condition_variable
|
||||
{
|
||||
public:
|
||||
void wait(unique_lock<mutex>& m)
|
||||
{
|
||||
do_wait(m,detail::timeout::sentinel());
|
||||
}
|
||||
|
||||
template<typename predicate_type>
|
||||
void wait(unique_lock<mutex>& m,predicate_type pred)
|
||||
{
|
||||
while(!pred()) wait(m);
|
||||
}
|
||||
|
||||
|
||||
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until)
|
||||
{
|
||||
return do_wait(m,wait_until);
|
||||
}
|
||||
|
||||
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& wait_until)
|
||||
{
|
||||
return do_wait(m,system_time(wait_until));
|
||||
}
|
||||
template<typename duration_type>
|
||||
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration)
|
||||
{
|
||||
return do_wait(m,wait_duration.total_milliseconds());
|
||||
}
|
||||
|
||||
template<typename predicate_type>
|
||||
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until,predicate_type pred)
|
||||
{
|
||||
return do_wait(m,wait_until,pred);
|
||||
}
|
||||
template<typename predicate_type>
|
||||
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& wait_until,predicate_type pred)
|
||||
{
|
||||
return do_wait(m,system_time(wait_until),pred);
|
||||
}
|
||||
template<typename duration_type,typename predicate_type>
|
||||
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
|
||||
{
|
||||
return do_wait(m,wait_duration.total_milliseconds(),pred);
|
||||
}
|
||||
};
|
||||
|
||||
class condition_variable_any:
|
||||
public detail::basic_condition_variable
|
||||
{
|
||||
public:
|
||||
template<typename lock_type>
|
||||
void wait(lock_type& m)
|
||||
{
|
||||
do_wait(m,detail::timeout::sentinel());
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
void wait(lock_type& m,predicate_type pred)
|
||||
{
|
||||
while(!pred()) wait(m);
|
||||
}
|
||||
|
||||
template<typename lock_type>
|
||||
bool timed_wait(lock_type& m,boost::system_time const& wait_until)
|
||||
{
|
||||
return do_wait(m,wait_until);
|
||||
}
|
||||
|
||||
template<typename lock_type>
|
||||
bool timed_wait(lock_type& m,boost::xtime const& wait_until)
|
||||
{
|
||||
return do_wait(m,system_time(wait_until));
|
||||
}
|
||||
|
||||
template<typename lock_type,typename duration_type>
|
||||
bool timed_wait(lock_type& m,duration_type const& wait_duration)
|
||||
{
|
||||
return do_wait(m,wait_duration.total_milliseconds());
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred)
|
||||
{
|
||||
return do_wait(m,wait_until,pred);
|
||||
}
|
||||
|
||||
template<typename lock_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,boost::xtime const& wait_until,predicate_type pred)
|
||||
{
|
||||
return do_wait(m,system_time(wait_until),pred);
|
||||
}
|
||||
|
||||
template<typename lock_type,typename duration_type,typename predicate_type>
|
||||
bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
|
||||
{
|
||||
return do_wait(m,wait_duration.total_milliseconds(),pred);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,77 +0,0 @@
|
||||
#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)
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
inline void interlocked_write_release(long volatile* x,long value)
|
||||
{
|
||||
_ReadWriteBarrier();
|
||||
*x=value;
|
||||
}
|
||||
inline void interlocked_write_release(void* volatile* x,void* value)
|
||||
{
|
||||
_ReadWriteBarrier();
|
||||
*x=value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <boost/detail/interlocked.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
inline long interlocked_read_acquire(long volatile* x)
|
||||
{
|
||||
return BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,0,0);
|
||||
}
|
||||
inline void* interlocked_read_acquire(void* volatile* x)
|
||||
{
|
||||
return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(x,0,0);
|
||||
}
|
||||
inline void interlocked_write_release(long volatile* x,long value)
|
||||
{
|
||||
BOOST_INTERLOCKED_EXCHANGE(x,value);
|
||||
}
|
||||
inline void interlocked_write_release(void* volatile* x,void* value)
|
||||
{
|
||||
BOOST_INTERLOCKED_EXCHANGE_POINTER(x,value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,61 +0,0 @@
|
||||
#ifndef BOOST_THREAD_WIN32_MUTEX_HPP
|
||||
#define BOOST_THREAD_WIN32_MUTEX_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 "basic_timed_mutex.hpp"
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
typedef ::boost::detail::basic_timed_mutex underlying_mutex;
|
||||
}
|
||||
|
||||
class mutex:
|
||||
boost::noncopyable,
|
||||
public ::boost::detail::underlying_mutex
|
||||
{
|
||||
public:
|
||||
mutex()
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
~mutex()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
typedef unique_lock<mutex> scoped_lock;
|
||||
typedef scoped_lock scoped_try_lock;
|
||||
};
|
||||
|
||||
typedef mutex try_mutex;
|
||||
|
||||
class timed_mutex:
|
||||
boost::noncopyable,
|
||||
public ::boost::detail::basic_timed_mutex
|
||||
{
|
||||
public:
|
||||
timed_mutex()
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
~timed_mutex()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
typedef unique_lock<timed_mutex> scoped_timed_lock;
|
||||
typedef scoped_timed_lock scoped_try_lock;
|
||||
typedef scoped_timed_lock scoped_lock;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,130 +0,0 @@
|
||||
#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 ::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_)
|
||||
{
|
||||
BOOST_VERIFY(!win32::WaitForSingleObject(mutex_handle,win32::infinite));
|
||||
}
|
||||
~win32_mutex_scoped_lock()
|
||||
{
|
||||
BOOST_VERIFY(win32::ReleaseMutex(mutex_handle)!=0);
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef BOOST_NO_ANSI_APIS
|
||||
template <class I>
|
||||
void int_to_string(I p, wchar_t* buf)
|
||||
{
|
||||
for(unsigned i=0; i < sizeof(I)*2; ++i,++buf)
|
||||
{
|
||||
*buf = L'A' + static_cast<wchar_t>((p >> (i*4)) & 0x0f);
|
||||
}
|
||||
*buf = 0;
|
||||
}
|
||||
#else
|
||||
template <class I>
|
||||
void int_to_string(I p, char* buf)
|
||||
{
|
||||
for(unsigned i=0; i < sizeof(I)*2; ++i,++buf)
|
||||
{
|
||||
*buf = 'A' + static_cast<char>((p >> (i*4)) & 0x0f);
|
||||
}
|
||||
*buf = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// 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(void* flag_address)
|
||||
{
|
||||
|
||||
#ifdef BOOST_NO_ANSI_APIS
|
||||
typedef wchar_t char_type;
|
||||
static const char_type fixed_mutex_name[]=L"{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
|
||||
#else
|
||||
typedef char char_type;
|
||||
static const char_type fixed_mutex_name[]="{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
|
||||
#endif
|
||||
unsigned const once_mutex_name_fixed_buffer_size=sizeof(fixed_mutex_name)/sizeof(char_type);
|
||||
unsigned const once_mutex_name_fixed_length=once_mutex_name_fixed_buffer_size-1;
|
||||
unsigned const once_mutex_name_length=once_mutex_name_fixed_buffer_size+sizeof(void*)*2+sizeof(unsigned long)*2;
|
||||
char_type mutex_name[once_mutex_name_length];
|
||||
|
||||
std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name));
|
||||
|
||||
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);
|
||||
|
||||
#ifdef BOOST_NO_ANSI_APIS
|
||||
return win32::CreateMutexW(0, 0, mutex_name);
|
||||
#else
|
||||
return win32::CreateMutexA(0, 0, mutex_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<typename Function>
|
||||
void call_once(once_flag& flag,Function f)
|
||||
{
|
||||
// Try for a quick win: if the procedure 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)
|
||||
{
|
||||
void* const mutex_handle(::boost::detail::create_once_mutex(&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
|
||||
@@ -1,61 +0,0 @@
|
||||
#ifndef BOOST_RECURSIVE_MUTEX_WIN32_HPP
|
||||
#define BOOST_RECURSIVE_MUTEX_WIN32_HPP
|
||||
|
||||
// recursive_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/utility.hpp>
|
||||
#include "basic_recursive_mutex.hpp"
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class recursive_mutex:
|
||||
boost::noncopyable,
|
||||
public ::boost::detail::basic_recursive_mutex
|
||||
{
|
||||
public:
|
||||
recursive_mutex()
|
||||
{
|
||||
::boost::detail::basic_recursive_mutex::initialize();
|
||||
}
|
||||
~recursive_mutex()
|
||||
{
|
||||
::boost::detail::basic_recursive_mutex::destroy();
|
||||
}
|
||||
|
||||
typedef unique_lock<recursive_mutex> scoped_lock;
|
||||
typedef scoped_lock scoped_try_lock;
|
||||
};
|
||||
|
||||
typedef recursive_mutex recursive_try_mutex;
|
||||
|
||||
class recursive_timed_mutex:
|
||||
boost::noncopyable,
|
||||
public ::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();
|
||||
}
|
||||
|
||||
typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
|
||||
typedef scoped_timed_lock scoped_try_lock;
|
||||
typedef scoped_timed_lock scoped_lock;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,509 +0,0 @@
|
||||
#ifndef BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
|
||||
#define BOOST_THREAD_WIN32_SHARED_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/detail/interlocked.hpp>
|
||||
#include <boost/thread/win32/thread_primitives.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <limits.h>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class shared_mutex:
|
||||
private boost::noncopyable
|
||||
{
|
||||
private:
|
||||
struct state_data
|
||||
{
|
||||
unsigned shared_count:11;
|
||||
unsigned shared_waiting:11;
|
||||
unsigned exclusive:1;
|
||||
unsigned upgrade:1;
|
||||
unsigned exclusive_waiting:7;
|
||||
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;
|
||||
detail::win32::handle semaphores[2];
|
||||
detail::win32::handle &unlock_sem;
|
||||
detail::win32::handle &exclusive_sem;
|
||||
detail::win32::handle upgrade_sem;
|
||||
|
||||
void release_waiters(state_data old_state)
|
||||
{
|
||||
if(old_state.exclusive_waiting)
|
||||
{
|
||||
BOOST_VERIFY(detail::win32::ReleaseSemaphore(exclusive_sem,1,0)!=0);
|
||||
}
|
||||
|
||||
if(old_state.shared_waiting || old_state.exclusive_waiting)
|
||||
{
|
||||
BOOST_VERIFY(detail::win32::ReleaseSemaphore(unlock_sem,old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
shared_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);
|
||||
upgrade_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
|
||||
state_data state_={0};
|
||||
state=state_;
|
||||
}
|
||||
|
||||
~shared_mutex()
|
||||
{
|
||||
detail::win32::CloseHandle(upgrade_sem);
|
||||
detail::win32::CloseHandle(unlock_sem);
|
||||
detail::win32::CloseHandle(exclusive_sem);
|
||||
}
|
||||
|
||||
bool try_lock_shared()
|
||||
{
|
||||
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_shared()
|
||||
{
|
||||
BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel()));
|
||||
}
|
||||
|
||||
bool timed_lock_shared(boost::system_time const& wait_until)
|
||||
{
|
||||
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 true;
|
||||
}
|
||||
|
||||
unsigned long const res=detail::win32::WaitForSingleObject(unlock_sem,::boost::detail::get_milliseconds_until(wait_until));
|
||||
if(res==detail::win32::timeout)
|
||||
{
|
||||
do
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
|
||||
{
|
||||
if(new_state.shared_waiting)
|
||||
{
|
||||
--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 true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(res==0);
|
||||
}
|
||||
}
|
||||
|
||||
void unlock_shared()
|
||||
{
|
||||
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.upgrade)
|
||||
{
|
||||
new_state.upgrade=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.upgrade)
|
||||
{
|
||||
BOOST_VERIFY(detail::win32::ReleaseSemaphore(upgrade_sem,1,0)!=0);
|
||||
}
|
||||
else
|
||||
{
|
||||
release_waiters(old_state);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
while(true);
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
|
||||
}
|
||||
|
||||
bool timed_lock(boost::system_time const& wait_until)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
unsigned long const wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,true,::boost::detail::get_milliseconds_until(wait_until));
|
||||
if(wait_res==detail::win32::timeout)
|
||||
{
|
||||
do
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
if(new_state.shared_count || new_state.exclusive)
|
||||
{
|
||||
if(new_state.exclusive_waiting)
|
||||
{
|
||||
--new_state.exclusive_waiting;
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
BOOST_ASSERT(wait_res<2);
|
||||
}
|
||||
}
|
||||
|
||||
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_upgrade()
|
||||
{
|
||||
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.upgrade)
|
||||
{
|
||||
++new_state.shared_waiting;
|
||||
}
|
||||
else
|
||||
{
|
||||
++new_state.shared_count;
|
||||
new_state.upgrade=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.upgrade))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BOOST_VERIFY(!detail::win32::WaitForSingleObject(unlock_sem,detail::win32::infinite));
|
||||
}
|
||||
}
|
||||
|
||||
void unlock_upgrade()
|
||||
{
|
||||
state_data old_state=state;
|
||||
do
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
new_state.upgrade=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_upgrade_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.upgrade=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)
|
||||
{
|
||||
BOOST_VERIFY(!detail::win32::WaitForSingleObject(upgrade_sem,detail::win32::infinite));
|
||||
}
|
||||
break;
|
||||
}
|
||||
old_state=current_state;
|
||||
}
|
||||
while(true);
|
||||
}
|
||||
|
||||
void unlock_and_lock_upgrade()
|
||||
{
|
||||
state_data old_state=state;
|
||||
do
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
new_state.exclusive=false;
|
||||
new_state.upgrade=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_shared()
|
||||
{
|
||||
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_upgrade_and_lock_shared()
|
||||
{
|
||||
state_data old_state=state;
|
||||
do
|
||||
{
|
||||
state_data new_state=old_state;
|
||||
new_state.upgrade=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);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,513 +0,0 @@
|
||||
#ifndef BOOST_THREAD_THREAD_WIN32_HPP
|
||||
#define BOOST_THREAD_THREAD_WIN32_HPP
|
||||
// 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
|
||||
|
||||
#include <exception>
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <ostream>
|
||||
#include <boost/thread/detail/move.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#include "thread_primitives.hpp"
|
||||
#include "thread_heap_alloc.hpp"
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class thread_interrupted
|
||||
{};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct thread_exit_callback_node;
|
||||
struct tss_data_node;
|
||||
|
||||
struct thread_data_base
|
||||
{
|
||||
long count;
|
||||
detail::win32::handle_manager thread_handle;
|
||||
detail::win32::handle_manager interruption_handle;
|
||||
boost::detail::thread_exit_callback_node* thread_exit_callbacks;
|
||||
boost::detail::tss_data_node* tss_data;
|
||||
bool interruption_enabled;
|
||||
unsigned id;
|
||||
|
||||
thread_data_base():
|
||||
count(0),thread_handle(detail::win32::invalid_handle_value),
|
||||
interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)),
|
||||
thread_exit_callbacks(0),tss_data(0),
|
||||
interruption_enabled(true),
|
||||
id(0)
|
||||
{}
|
||||
virtual ~thread_data_base()
|
||||
{}
|
||||
|
||||
friend void intrusive_ptr_add_ref(thread_data_base * p)
|
||||
{
|
||||
BOOST_INTERLOCKED_INCREMENT(&p->count);
|
||||
}
|
||||
|
||||
friend void intrusive_ptr_release(thread_data_base * p)
|
||||
{
|
||||
if(!BOOST_INTERLOCKED_DECREMENT(&p->count))
|
||||
{
|
||||
detail::heap_delete(p);
|
||||
}
|
||||
}
|
||||
|
||||
void interrupt()
|
||||
{
|
||||
BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0);
|
||||
}
|
||||
|
||||
|
||||
virtual void run()=0;
|
||||
};
|
||||
|
||||
typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr;
|
||||
|
||||
struct timeout
|
||||
{
|
||||
unsigned long start;
|
||||
uintmax_t milliseconds;
|
||||
bool relative;
|
||||
boost::system_time abs_time;
|
||||
|
||||
static unsigned long const max_non_infinite_wait=0xfffffffe;
|
||||
|
||||
timeout(uintmax_t milliseconds_):
|
||||
start(win32::GetTickCount()),
|
||||
milliseconds(milliseconds_),
|
||||
relative(true),
|
||||
abs_time(boost::get_system_time())
|
||||
{}
|
||||
|
||||
timeout(boost::system_time const& abs_time_):
|
||||
start(win32::GetTickCount()),
|
||||
milliseconds(0),
|
||||
relative(false),
|
||||
abs_time(abs_time_)
|
||||
{}
|
||||
|
||||
struct remaining_time
|
||||
{
|
||||
bool more;
|
||||
unsigned long milliseconds;
|
||||
|
||||
remaining_time(uintmax_t remaining):
|
||||
more(remaining>max_non_infinite_wait),
|
||||
milliseconds(more?max_non_infinite_wait:(unsigned long)remaining)
|
||||
{}
|
||||
};
|
||||
|
||||
remaining_time remaining_milliseconds() const
|
||||
{
|
||||
if(is_sentinel())
|
||||
{
|
||||
return remaining_time(win32::infinite);
|
||||
}
|
||||
else if(relative)
|
||||
{
|
||||
unsigned long const now=win32::GetTickCount();
|
||||
unsigned long const elapsed=now-start;
|
||||
return remaining_time((elapsed<milliseconds)?(milliseconds-elapsed):0);
|
||||
}
|
||||
else
|
||||
{
|
||||
system_time const now=get_system_time();
|
||||
if(abs_time<=now)
|
||||
{
|
||||
return remaining_time(0);
|
||||
}
|
||||
return remaining_time((abs_time-now).total_milliseconds()+1);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_sentinel() const
|
||||
{
|
||||
return milliseconds==~uintmax_t(0);
|
||||
}
|
||||
|
||||
|
||||
static timeout sentinel()
|
||||
{
|
||||
return timeout(sentinel_type());
|
||||
}
|
||||
private:
|
||||
struct sentinel_type
|
||||
{};
|
||||
|
||||
explicit timeout(sentinel_type):
|
||||
start(0),milliseconds(~uintmax_t(0)),relative(true)
|
||||
{}
|
||||
};
|
||||
}
|
||||
|
||||
class BOOST_THREAD_DECL thread
|
||||
{
|
||||
private:
|
||||
thread(thread&);
|
||||
thread& operator=(thread&);
|
||||
|
||||
void release_handle();
|
||||
|
||||
template<typename F>
|
||||
struct thread_data:
|
||||
detail::thread_data_base
|
||||
{
|
||||
F f;
|
||||
|
||||
thread_data(F f_):
|
||||
f(f_)
|
||||
{}
|
||||
thread_data(detail::thread_move_t<F> f_):
|
||||
f(f_)
|
||||
{}
|
||||
|
||||
void run()
|
||||
{
|
||||
f();
|
||||
}
|
||||
};
|
||||
|
||||
mutable boost::mutex thread_info_mutex;
|
||||
detail::thread_data_ptr thread_info;
|
||||
|
||||
static unsigned __stdcall thread_start_function(void* param);
|
||||
|
||||
void start_thread();
|
||||
|
||||
explicit thread(detail::thread_data_ptr data);
|
||||
|
||||
detail::thread_data_ptr get_thread_info() const;
|
||||
public:
|
||||
thread();
|
||||
~thread();
|
||||
|
||||
template <class F>
|
||||
explicit thread(F f):
|
||||
thread_info(detail::heap_new<thread_data<F> >(f))
|
||||
{
|
||||
start_thread();
|
||||
}
|
||||
template <class F>
|
||||
thread(detail::thread_move_t<F> f):
|
||||
thread_info(detail::heap_new<thread_data<F> >(f))
|
||||
{
|
||||
start_thread();
|
||||
}
|
||||
|
||||
thread(detail::thread_move_t<thread> x);
|
||||
thread& operator=(detail::thread_move_t<thread> x);
|
||||
operator detail::thread_move_t<thread>();
|
||||
detail::thread_move_t<thread> move();
|
||||
|
||||
void swap(thread& x);
|
||||
|
||||
class id;
|
||||
id get_id() const;
|
||||
|
||||
|
||||
bool joinable() const;
|
||||
void join();
|
||||
bool timed_join(const system_time& wait_until);
|
||||
|
||||
template<typename TimeDuration>
|
||||
inline bool timed_join(TimeDuration const& rel_time)
|
||||
{
|
||||
return timed_join(get_system_time()+rel_time);
|
||||
}
|
||||
void detach();
|
||||
|
||||
static unsigned hardware_concurrency();
|
||||
|
||||
typedef detail::win32::handle native_handle_type;
|
||||
native_handle_type native_handle();
|
||||
|
||||
// backwards compatibility
|
||||
bool operator==(const thread& other) const;
|
||||
bool operator!=(const thread& other) const;
|
||||
|
||||
static void yield();
|
||||
static void sleep(const system_time& xt);
|
||||
|
||||
// extensions
|
||||
void interrupt();
|
||||
bool interruption_requested() const;
|
||||
};
|
||||
|
||||
inline detail::thread_move_t<thread> move(thread& x)
|
||||
{
|
||||
return x.move();
|
||||
}
|
||||
|
||||
inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
struct thread::thread_data<boost::reference_wrapper<F> >:
|
||||
detail::thread_data_base
|
||||
{
|
||||
F& f;
|
||||
|
||||
thread_data(boost::reference_wrapper<F> f_):
|
||||
f(f_)
|
||||
{}
|
||||
|
||||
void run()
|
||||
{
|
||||
f();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
class BOOST_THREAD_DECL disable_interruption
|
||||
{
|
||||
disable_interruption(const disable_interruption&);
|
||||
disable_interruption& operator=(const disable_interruption&);
|
||||
|
||||
bool interruption_was_enabled;
|
||||
friend class restore_interruption;
|
||||
public:
|
||||
disable_interruption();
|
||||
~disable_interruption();
|
||||
};
|
||||
|
||||
class BOOST_THREAD_DECL restore_interruption
|
||||
{
|
||||
restore_interruption(const restore_interruption&);
|
||||
restore_interruption& operator=(const restore_interruption&);
|
||||
public:
|
||||
explicit restore_interruption(disable_interruption& d);
|
||||
~restore_interruption();
|
||||
};
|
||||
|
||||
thread::id BOOST_THREAD_DECL get_id();
|
||||
|
||||
bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
|
||||
inline bool interruptible_wait(unsigned long milliseconds)
|
||||
{
|
||||
return interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
|
||||
}
|
||||
|
||||
void BOOST_THREAD_DECL interruption_point();
|
||||
bool BOOST_THREAD_DECL interruption_enabled();
|
||||
bool BOOST_THREAD_DECL interruption_requested();
|
||||
|
||||
void BOOST_THREAD_DECL yield();
|
||||
template<typename TimeDuration>
|
||||
void sleep(TimeDuration const& rel_time)
|
||||
{
|
||||
interruptible_wait(static_cast<unsigned long>(rel_time.total_milliseconds()));
|
||||
}
|
||||
}
|
||||
|
||||
class thread::id
|
||||
{
|
||||
private:
|
||||
detail::thread_data_ptr thread_data;
|
||||
|
||||
id(detail::thread_data_ptr thread_data_):
|
||||
thread_data(thread_data_)
|
||||
{}
|
||||
friend class thread;
|
||||
friend id this_thread::get_id();
|
||||
public:
|
||||
id():
|
||||
thread_data(0)
|
||||
{}
|
||||
|
||||
bool operator==(const id& y) const
|
||||
{
|
||||
return thread_data==y.thread_data;
|
||||
}
|
||||
|
||||
bool operator!=(const id& y) const
|
||||
{
|
||||
return thread_data!=y.thread_data;
|
||||
}
|
||||
|
||||
bool operator<(const id& y) const
|
||||
{
|
||||
return thread_data<y.thread_data;
|
||||
}
|
||||
|
||||
bool operator>(const id& y) const
|
||||
{
|
||||
return y.thread_data<thread_data;
|
||||
}
|
||||
|
||||
bool operator<=(const id& y) const
|
||||
{
|
||||
return !(y.thread_data<thread_data);
|
||||
}
|
||||
|
||||
bool operator>=(const id& y) const
|
||||
{
|
||||
return !(thread_data<y.thread_data);
|
||||
}
|
||||
|
||||
template<class charT, class traits>
|
||||
friend std::basic_ostream<charT, traits>&
|
||||
operator<<(std::basic_ostream<charT, traits>& os, const id& x)
|
||||
{
|
||||
if(x.thread_data)
|
||||
{
|
||||
return os<<x.thread_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return os<<"{Not-any-thread}";
|
||||
}
|
||||
}
|
||||
|
||||
void interrupt()
|
||||
{
|
||||
if(thread_data)
|
||||
{
|
||||
thread_data->interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
inline bool thread::operator==(const thread& other) const
|
||||
{
|
||||
return get_id()==other.get_id();
|
||||
}
|
||||
|
||||
inline bool thread::operator!=(const thread& other) const
|
||||
{
|
||||
return get_id()!=other.get_id();
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct thread_exit_function_base
|
||||
{
|
||||
virtual ~thread_exit_function_base()
|
||||
{}
|
||||
virtual void operator()() const=0;
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
struct thread_exit_function:
|
||||
thread_exit_function_base
|
||||
{
|
||||
F f;
|
||||
|
||||
thread_exit_function(F f_):
|
||||
f(f_)
|
||||
{}
|
||||
|
||||
void operator()() const
|
||||
{
|
||||
f();
|
||||
}
|
||||
};
|
||||
|
||||
void add_thread_exit_function(thread_exit_function_base*);
|
||||
}
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
template<typename F>
|
||||
void at_thread_exit(F f)
|
||||
{
|
||||
detail::thread_exit_function_base* const thread_exit_func=detail::heap_new<detail::thread_exit_function<F> >(f);
|
||||
detail::add_thread_exit_function(thread_exit_func);
|
||||
}
|
||||
}
|
||||
|
||||
class thread_group:
|
||||
private noncopyable
|
||||
{
|
||||
public:
|
||||
~thread_group()
|
||||
{
|
||||
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
|
||||
it!=end;
|
||||
++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
thread* create_thread(F threadfunc)
|
||||
{
|
||||
boost::lock_guard<mutex> guard(m);
|
||||
thread* const new_thread=new thread(threadfunc);
|
||||
threads.push_back(new_thread);
|
||||
return new_thread;
|
||||
}
|
||||
|
||||
void add_thread(thread* thrd)
|
||||
{
|
||||
if(thrd)
|
||||
{
|
||||
boost::lock_guard<mutex> guard(m);
|
||||
threads.push_back(thrd);
|
||||
}
|
||||
}
|
||||
|
||||
void remove_thread(thread* thrd)
|
||||
{
|
||||
boost::lock_guard<mutex> guard(m);
|
||||
std::list<thread*>::iterator const it=std::find(threads.begin(),threads.end(),thrd);
|
||||
if(it!=threads.end())
|
||||
{
|
||||
threads.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void join_all()
|
||||
{
|
||||
boost::lock_guard<mutex> guard(m);
|
||||
|
||||
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
|
||||
it!=end;
|
||||
++it)
|
||||
{
|
||||
(*it)->join();
|
||||
}
|
||||
}
|
||||
|
||||
void interrupt_all()
|
||||
{
|
||||
boost::lock_guard<mutex> guard(m);
|
||||
|
||||
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
|
||||
it!=end;
|
||||
++it)
|
||||
{
|
||||
(*it)->interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
int size() const
|
||||
{
|
||||
boost::lock_guard<mutex> guard(m);
|
||||
return threads.size();
|
||||
}
|
||||
|
||||
private:
|
||||
std::list<thread*> threads;
|
||||
mutable mutex m;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,170 +0,0 @@
|
||||
// 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 THREAD_HEAP_ALLOC_HPP
|
||||
#define THREAD_HEAP_ALLOC_HPP
|
||||
#include <new>
|
||||
#include "thread_primitives.hpp"
|
||||
#include <stdexcept>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#if defined( BOOST_USE_WINDOWS_H )
|
||||
# include <windows.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
namespace win32
|
||||
{
|
||||
using ::GetProcessHeap;
|
||||
using ::HeapAlloc;
|
||||
using ::HeapFree;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# ifdef HeapAlloc
|
||||
# undef HeapAlloc
|
||||
# endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
namespace win32
|
||||
{
|
||||
extern "C"
|
||||
{
|
||||
__declspec(dllimport) handle __stdcall GetProcessHeap();
|
||||
__declspec(dllimport) void* __stdcall HeapAlloc(handle,unsigned long,ulong_ptr);
|
||||
__declspec(dllimport) int __stdcall HeapFree(handle,unsigned long,void*);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
inline BOOST_THREAD_DECL void* allocate_raw_heap_memory(unsigned size)
|
||||
{
|
||||
void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,size);
|
||||
if(!heap_memory)
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
return heap_memory;
|
||||
}
|
||||
|
||||
inline BOOST_THREAD_DECL void free_raw_heap_memory(void* heap_memory)
|
||||
{
|
||||
BOOST_VERIFY(detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,heap_memory)!=0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* heap_new()
|
||||
{
|
||||
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
|
||||
try
|
||||
{
|
||||
T* const data=new (heap_memory) T();
|
||||
return data;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
free_raw_heap_memory(heap_memory);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T,typename A1>
|
||||
T* heap_new(A1 a1)
|
||||
{
|
||||
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
|
||||
try
|
||||
{
|
||||
T* const data=new (heap_memory) T(a1);
|
||||
return data;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
free_raw_heap_memory(heap_memory);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T,typename A1,typename A2>
|
||||
T* heap_new(A1 a1,A2 a2)
|
||||
{
|
||||
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
|
||||
try
|
||||
{
|
||||
T* const data=new (heap_memory) T(a1,a2);
|
||||
return data;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
free_raw_heap_memory(heap_memory);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T,typename A1,typename A2,typename A3>
|
||||
T* heap_new(A1 a1,A2 a2,A3 a3)
|
||||
{
|
||||
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
|
||||
try
|
||||
{
|
||||
T* const data=new (heap_memory) T(a1,a2,a3);
|
||||
return data;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
free_raw_heap_memory(heap_memory);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T,typename A1,typename A2,typename A3,typename A4>
|
||||
T* heap_new(A1 a1,A2 a2,A3 a3,A4 a4)
|
||||
{
|
||||
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
|
||||
try
|
||||
{
|
||||
T* const data=new (heap_memory) T(a1,a2,a3,a4);
|
||||
return data;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
free_raw_heap_memory(heap_memory);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void heap_delete(T* data)
|
||||
{
|
||||
data->~T();
|
||||
free_raw_heap_memory(data);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct do_heap_delete
|
||||
{
|
||||
void operator()(T* data) const
|
||||
{
|
||||
detail::heap_delete(data);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,281 +0,0 @@
|
||||
#ifndef BOOST_WIN32_THREAD_PRIMITIVES_HPP
|
||||
#define BOOST_WIN32_THREAD_PRIMITIVES_HPP
|
||||
|
||||
// win32_thread_primitives.hpp
|
||||
//
|
||||
// (C) Copyright 2005-7 Anthony Williams
|
||||
// (C) Copyright 2007 David Deakins
|
||||
//
|
||||
// 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>
|
||||
#include <algorithm>
|
||||
|
||||
#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;
|
||||
handle const invalid_handle_value=INVALID_HANDLE_VALUE;
|
||||
|
||||
# ifdef BOOST_NO_ANSI_APIS
|
||||
using ::CreateMutexW;
|
||||
using ::CreateEventW;
|
||||
using ::CreateSemaphoreW;
|
||||
# else
|
||||
using ::CreateMutexA;
|
||||
using ::CreateEventA;
|
||||
using ::CreateSemaphoreA;
|
||||
# endif
|
||||
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 ::Sleep;
|
||||
using ::QueueUserAPC;
|
||||
using ::GetTickCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
|
||||
|
||||
# ifdef UNDER_CE
|
||||
# ifndef WINAPI
|
||||
# ifndef _WIN32_WCE_EMULATION
|
||||
# define WINAPI __cdecl // Note this doesn't match the desktop definition
|
||||
# else
|
||||
# define WINAPI __stdcall
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
typedef int BOOL;
|
||||
typedef unsigned long DWORD;
|
||||
typedef void* HANDLE;
|
||||
|
||||
# include <kfuncs.h>
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
# endif
|
||||
|
||||
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;
|
||||
handle const invalid_handle_value=(handle)(-1);
|
||||
|
||||
extern "C"
|
||||
{
|
||||
struct _SECURITY_ATTRIBUTES;
|
||||
# ifdef BOOST_NO_ANSI_APIS
|
||||
__declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*);
|
||||
__declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*);
|
||||
__declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*);
|
||||
# else
|
||||
__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*);
|
||||
# endif
|
||||
__declspec(dllimport) int __stdcall CloseHandle(void*);
|
||||
__declspec(dllimport) int __stdcall ReleaseMutex(void*);
|
||||
__declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void*,unsigned long);
|
||||
__declspec(dllimport) unsigned long __stdcall WaitForMultipleObjects(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds);
|
||||
__declspec(dllimport) int __stdcall ReleaseSemaphore(void*,long,long*);
|
||||
__declspec(dllimport) int __stdcall DuplicateHandle(void*,void*,void*,void**,unsigned long,int,unsigned long);
|
||||
__declspec(dllimport) unsigned long __stdcall SleepEx(unsigned long,int);
|
||||
__declspec(dllimport) void __stdcall Sleep(unsigned long);
|
||||
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) unsigned long __stdcall GetTickCount();
|
||||
|
||||
# ifndef UNDER_CE
|
||||
__declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
|
||||
__declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
|
||||
__declspec(dllimport) void* __stdcall GetCurrentThread();
|
||||
__declspec(dllimport) void* __stdcall GetCurrentProcess();
|
||||
__declspec(dllimport) int __stdcall SetEvent(void*);
|
||||
__declspec(dllimport) int __stdcall ResetEvent(void*);
|
||||
# else
|
||||
using ::GetCurrentProcessId;
|
||||
using ::GetCurrentThreadId;
|
||||
using ::GetCurrentThread;
|
||||
using ::GetCurrentProcess;
|
||||
using ::SetEvent;
|
||||
using ::ResetEvent;
|
||||
# endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#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)
|
||||
{
|
||||
#if !defined(BOOST_NO_ANSI_APIS)
|
||||
handle const res=win32::CreateEventA(0,type,state,0);
|
||||
#else
|
||||
handle const res=win32::CreateEventW(0,type,state,0);
|
||||
#endif
|
||||
if(!res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
inline handle create_anonymous_semaphore(long initial_count,long max_count)
|
||||
{
|
||||
#if !defined(BOOST_NO_ANSI_APIS)
|
||||
handle const res=CreateSemaphoreA(0,initial_count,max_count,0);
|
||||
#else
|
||||
handle const res=CreateSemaphoreW(0,initial_count,max_count,0);
|
||||
#endif
|
||||
if(!res)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
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;
|
||||
if(!success)
|
||||
{
|
||||
throw thread_resource_error();
|
||||
}
|
||||
return new_handle;
|
||||
}
|
||||
|
||||
inline void release_semaphore(handle semaphore,long count)
|
||||
{
|
||||
BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0);
|
||||
}
|
||||
|
||||
class handle_manager
|
||||
{
|
||||
private:
|
||||
handle handle_to_manage;
|
||||
handle_manager(handle_manager&);
|
||||
handle_manager& operator=(handle_manager&);
|
||||
|
||||
void cleanup()
|
||||
{
|
||||
if(handle_to_manage && handle_to_manage!=invalid_handle_value)
|
||||
{
|
||||
BOOST_VERIFY(CloseHandle(handle_to_manage));
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator handle() const
|
||||
{
|
||||
return handle_to_manage;
|
||||
}
|
||||
|
||||
handle duplicate() const
|
||||
{
|
||||
return duplicate_handle(handle_to_manage);
|
||||
}
|
||||
|
||||
void swap(handle_manager& other)
|
||||
{
|
||||
std::swap(handle_to_manage,other.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
|
||||
@@ -1,103 +0,0 @@
|
||||
#ifndef BOOST_THREAD_WIN32_TSS_HPP
|
||||
#define BOOST_THREAD_WIN32_TSS_HPP
|
||||
// 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
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include "thread_heap_alloc.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct tss_cleanup_function
|
||||
{
|
||||
virtual ~tss_cleanup_function()
|
||||
{}
|
||||
|
||||
virtual void operator()(void* data)=0;
|
||||
};
|
||||
|
||||
BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
|
||||
BOOST_THREAD_DECL void* get_tss_data(void const* key);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class thread_specific_ptr
|
||||
{
|
||||
private:
|
||||
thread_specific_ptr(thread_specific_ptr&);
|
||||
thread_specific_ptr& operator=(thread_specific_ptr&);
|
||||
|
||||
struct delete_data:
|
||||
detail::tss_cleanup_function
|
||||
{
|
||||
void operator()(void* data)
|
||||
{
|
||||
delete static_cast<T*>(data);
|
||||
}
|
||||
};
|
||||
|
||||
struct run_custom_cleanup_function:
|
||||
detail::tss_cleanup_function
|
||||
{
|
||||
void (*cleanup_function)(T*);
|
||||
|
||||
explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)):
|
||||
cleanup_function(cleanup_function_)
|
||||
{}
|
||||
|
||||
void operator()(void* data)
|
||||
{
|
||||
cleanup_function(static_cast<T*>(data));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
boost::shared_ptr<detail::tss_cleanup_function> cleanup;
|
||||
|
||||
public:
|
||||
thread_specific_ptr():
|
||||
cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
|
||||
{}
|
||||
explicit thread_specific_ptr(void (*func_)(T*)):
|
||||
cleanup(detail::heap_new<run_custom_cleanup_function>(func_),detail::do_heap_delete<run_custom_cleanup_function>())
|
||||
{}
|
||||
~thread_specific_ptr()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
T* get() const
|
||||
{
|
||||
return static_cast<T*>(detail::get_tss_data(this));
|
||||
}
|
||||
T* operator->() const
|
||||
{
|
||||
return get();
|
||||
}
|
||||
T& operator*() const
|
||||
{
|
||||
return *get();
|
||||
}
|
||||
T* release()
|
||||
{
|
||||
T* const temp=get();
|
||||
detail::set_tss_data(this,0,0,false);
|
||||
return temp;
|
||||
}
|
||||
void reset(T* new_value=0)
|
||||
{
|
||||
T* const current_value=get();
|
||||
if(current_value!=new_value)
|
||||
{
|
||||
detail::set_tss_data(this,cleanup,new_value,true);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,9 +1,13 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
// Copyright (C) 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)
|
||||
// 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_XTIME_WEK070601_HPP
|
||||
#define BOOST_XTIME_WEK070601_HPP
|
||||
@@ -11,8 +15,6 @@
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/thread/thread_time.hpp>
|
||||
#include <boost/date_time/posix_time/conversion.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
@@ -31,58 +33,26 @@ enum xtime_clock_types
|
||||
struct xtime
|
||||
{
|
||||
#if defined(BOOST_NO_INT64_T)
|
||||
typedef int_fast32_t xtime_sec_t; //INT_FAST32_MIN <= sec <= INT_FAST32_MAX
|
||||
int_fast32_t sec;
|
||||
#else
|
||||
typedef int_fast64_t xtime_sec_t; //INT_FAST64_MIN <= sec <= INT_FAST64_MAX
|
||||
int_fast64_t sec;
|
||||
#endif
|
||||
|
||||
typedef int_fast32_t xtime_nsec_t; //0 <= xtime.nsec < NANOSECONDS_PER_SECOND
|
||||
|
||||
xtime_sec_t sec;
|
||||
xtime_nsec_t nsec;
|
||||
|
||||
operator system_time() const
|
||||
{
|
||||
return boost::posix_time::from_time_t(0)+
|
||||
boost::posix_time::seconds(static_cast<long>(sec))+
|
||||
#ifdef BOOST_DATE_TIME_HAS_NANOSECONDS
|
||||
boost::posix_time::nanoseconds(nsec);
|
||||
#else
|
||||
boost::posix_time::microseconds((nsec+500)/1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
int_fast32_t nsec;
|
||||
};
|
||||
|
||||
inline xtime get_xtime(boost::system_time const& abs_time)
|
||||
{
|
||||
xtime res={0};
|
||||
boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0);
|
||||
|
||||
res.sec=static_cast<xtime::xtime_sec_t>(time_since_epoch.total_seconds());
|
||||
res.nsec=static_cast<xtime::xtime_nsec_t>(time_since_epoch.fractional_seconds()*(1000000000/time_since_epoch.ticks_per_second()));
|
||||
return res;
|
||||
}
|
||||
|
||||
inline int xtime_get(struct xtime* xtp, int clock_type)
|
||||
{
|
||||
if (clock_type == TIME_UTC)
|
||||
{
|
||||
*xtp=get_xtime(get_system_time());
|
||||
return clock_type;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
int res = (int)(xt1.sec - xt2.sec);
|
||||
if (res == 0)
|
||||
res = (int)(xt1.nsec - xt2.nsec);
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif //BOOST_XTIME_WEK070601_HPP
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
|
||||
#endif // BOOST_XTIME_WEK070601_HPP
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
<!-- Copyright (c) 2002-2003 William E. Kempf.
|
||||
Subject to the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=doc/index.html">
|
||||
@@ -10,4 +5,4 @@
|
||||
<body>
|
||||
Automatic redirection failed, please go to <a href="doc/index.html">doc/index.html</a>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user