2
0
mirror of https://github.com/boostorg/thread.git synced 2026-02-03 09:42:16 +00:00

Compare commits

...

81 Commits

Author SHA1 Message Date
Beman Dawes
560e8320d1 Branch for development of boost.system related changes
[SVN r40931]
2007-11-08 14:20:16 +00:00
Anthony Williams
5de1582a0a Added missing licence and copyright
[SVN r40884]
2007-11-07 12:10:17 +00:00
Anthony Williams
39c864e31f use condition so we know when threads have unblocked, to avoid hard-coding a delay
[SVN r40846]
2007-11-06 17:15:50 +00:00
Anthony Williams
320cb63df4 Use BOOST_VERIFY instead of BOOST_ASSERT in many places in order to avoid unused variable warnings
[SVN r40792]
2007-11-05 16:47:25 +00:00
Roland Schwarz
c246222ded Cosmetic change to please gcc.
[SVN r40791]
2007-11-05 16:22:17 +00:00
Roland Schwarz
b7edb2873c Usage requirements added.
[SVN r40790]
2007-11-05 16:12:49 +00:00
Anthony Williams
89f2032c0d Use pthread_equal for comparing pthread_t IDs; use BOOST_VERIFY instead of BOOST_ASSERT in many places in order to avoid unused variable warnings
[SVN r40787]
2007-11-05 14:16:21 +00:00
Anthony Williams
d2f8230093 threadapi is a composite feature again
[SVN r40774]
2007-11-05 10:15:24 +00:00
Roland Schwarz
9f6b5d169a Get rid of "unsused variable" warnings by making use of BOOST_VERIFY.
This changeset is for pthread only.


[SVN r40742]
2007-11-04 17:17:01 +00:00
Anthony Williams
e56708d4aa added missing include
[SVN r40730]
2007-11-03 22:00:12 +00:00
Anthony Williams
304156c20e Fixed typo with interruption change
[SVN r40692]
2007-11-02 18:19:49 +00:00
Anthony Williams
31e1566e1d renamed cancellation to interruption
[SVN r40685]
2007-11-02 14:58:48 +00:00
Anthony Williams
3908637056 rewrite xtime_get in terms of get_system_time to ensure clock consistency, and fix Borland test failures
[SVN r40680]
2007-11-02 11:47:56 +00:00
Anthony Williams
abee301f3d Added changes from David Deakins to enable compilation on Windows CE
[SVN r40679]
2007-11-02 09:17:02 +00:00
Roland Schwarz
9b1d3f8f3c New thread Jamfile. Requirement <threading>multi now correctly handled, even when requested with <threading>single. New project specific feature <threadapi> with values win32 and pthread available.
[SVN r40677]
2007-11-02 08:40:11 +00:00
Anthony Williams
3513eaf701 added timed_join to thread
[SVN r40653]
2007-11-01 18:04:55 +00:00
Anthony Williams
08a840afe4 shared_mutex lock functions are not cancellation points
[SVN r40650]
2007-11-01 17:18:54 +00:00
Anthony Williams
370f5d461c condition wait and sleep are now cancellation points
[SVN r40647]
2007-11-01 17:07:47 +00:00
Anthony Williams
8efc8458e1 Added specialization for reference_wrapper to allow use of boost::ref with boost::thread (again)
[SVN r40609]
2007-10-30 17:16:24 +00:00
Anthony Williams
6485717c52 improved lifetime management of thread data
[SVN r40478]
2007-10-26 10:46:01 +00:00
Anthony Williams
1d5bbd11a8 disable_cancellation and restore_cancellation need to be declared BOOST_THREAD_DECL to work with DLLs with pthread-win32
[SVN r40477]
2007-10-26 09:53:10 +00:00
Anthony Williams
bc403742b5 disable_cancellation and restore_cancellation need to be declared BOOST_THREAD_DECL to work with DLLs
[SVN r40476]
2007-10-26 09:45:46 +00:00
Vladimir Prus
c7f963f57e Make sure every library can be installed by using
bjam stage|install

in libs/<library>/build.


[SVN r40475]
2007-10-26 09:04:25 +00:00
Anthony Williams
afb6684bde added tests for cancellation
[SVN r40472]
2007-10-26 07:33:22 +00:00
Anthony Williams
ee3d772235 thread move constructor is not explicit, so self() compiles for MSVC8 and Intel; thread_exit_callback_node constructor added to remove warnings on MSVC8; thread destructor no longer calls cancel
[SVN r40456]
2007-10-25 07:17:20 +00:00
Anthony Williams
1af08f7085 updated pthreads code to support move and multiple joins
[SVN r40424]
2007-10-24 15:39:14 +00:00
Anthony Williams
ccf23fa273 updated thread move semantics to work with Borland
[SVN r40412]
2007-10-24 12:00:14 +00:00
Anthony Williams
f701defc5f thrd-api is no longer a symmetric feature
[SVN r40407]
2007-10-24 09:36:51 +00:00
Anthony Williams
c606f05bf8 added real default constructor to condition::list_entry
[SVN r40406]
2007-10-24 09:32:29 +00:00
Anthony Williams
a646153615 platform split for pthread and win32 builds so can use pthread-win32 library on Windows with <thrd-api>pthread feature; new C++0x-alike thread class interface on win32.
[SVN r40348]
2007-10-23 08:57:17 +00:00
Markus Schöpflin
60380afe15 Fix compilation.
[SVN r40277]
2007-10-22 07:54:08 +00:00
Anthony Williams
d4b0a977c9 New condition_variable and condition_variable_any as per proposed C++0x interface
[SVN r40191]
2007-10-19 17:40:04 +00:00
Anthony Williams
f86156ad10 more tweaks to remove warnings
[SVN r40189]
2007-10-19 15:31:35 +00:00
Anthony Williams
1836ee854f small changes to reduce warnings; extracted pthread_mutex_scoped_lock to its own file
[SVN r40187]
2007-10-19 14:52:52 +00:00
Anthony Williams
c37cdeec9f removed lock_ops as no longer needed
[SVN r40080]
2007-10-16 11:08:17 +00:00
Anthony Williams
b0b2b17908 added missing include to basic_timed_mutex.hpp
[SVN r40041]
2007-10-15 09:18:32 +00:00
Anthony Williams
2918732481 read_write_mutex makes a comeback --- as shared_mutex
[SVN r39891]
2007-10-10 15:33:49 +00:00
Anthony Williams
5a4d5ddb9d fixed more has-timed-lock backwards conditions
[SVN r39841]
2007-10-09 14:44:37 +00:00
Anthony Williams
55afcf678d fixed typo in pthread_cond_timedwait and ETIMEDOUT
[SVN r39839]
2007-10-09 14:08:22 +00:00
Anthony Williams
16c7cf9b5e fixed typo in pthread_cond_timedwait and ETIMEDOUT
[SVN r39838]
2007-10-09 12:45:46 +00:00
Anthony Williams
432bd29c1c fixed direction of conditional
[SVN r39836]
2007-10-09 12:23:09 +00:00
Anthony Williams
a87914ef23 added missing move.hpp header
[SVN r39832]
2007-10-09 06:59:14 +00:00
Anthony Williams
041530a953 added backwards-compatibility overload for call_once
[SVN r39785]
2007-10-08 15:44:13 +00:00
Anthony Williams
9d4c55161a New mutex implementations, more akin to C++0x
[SVN r39784]
2007-10-08 15:41:05 +00:00
Anthony Williams
a706d1df00 call_once passes exceptions to caller and leaves flag unset
[SVN r39781]
2007-10-08 09:55:56 +00:00
Anthony Williams
b15b2e666f added extended test for new call_once
[SVN r39780]
2007-10-08 09:48:57 +00:00
Anthony Williams
5d4678364e Use InterlockedCompareExchange when _ReadWriteBarrier not available
[SVN r39777]
2007-10-08 07:18:27 +00:00
Anthony Williams
9590526430 include config header from right place for pthread/once.hpp
[SVN r39705]
2007-10-05 12:50:29 +00:00
Anthony Williams
1c6dfda83c added platform dispatcher
[SVN r39703]
2007-10-05 12:21:55 +00:00
Anthony Williams
a8be12940e added platform-specific call_once implementations
[SVN r39702]
2007-10-05 12:20:50 +00:00
Anthony Williams
4b5046366b Changed call_once to header-only template that takes arbitrary function objects; this changes parameter order
[SVN r39701]
2007-10-05 12:10:06 +00:00
Anthony Williams
a0fff90c26 Updated in line with RC 1.34
[SVN r39693]
2007-10-05 09:46:00 +00:00
Vladimir Prus
a8daedac5e Revive V1 Jamfile to please asio
[SVN r38837]
2007-08-22 12:40:34 +00:00
Vladimir Prus
5fa26fb3ac Update to V2
[SVN r38531]
2007-08-08 19:47:16 +00:00
Vladimir Prus
ea3e297175 Remove V1 Jamfiles
[SVN r38516]
2007-08-08 19:02:26 +00:00
Rene Rivera
a11bd6ebd9 Put in the build support for using the doxproc, Python based, Doxygen to BoostBook translator.
[SVN r37457]
2007-04-17 04:44:59 +00:00
Roland Schwarz
9889bf50a2 FAQ Entry: Passing parameters during thread creation.
[SVN r36922]
2007-02-11 13:52:28 +00:00
Roland Schwarz
d75fb2deda Applying long outstanding patch.
See:http://thread.gmane.org/gmane.comp.lib.boost.devel/118863/focus=118912


[SVN r36920]
2007-02-11 12:00:38 +00:00
Roland Schwarz
6355a5b28d Changes for WINCE
[SVN r36484]
2006-12-22 09:40:17 +00:00
Roland Schwarz
595bbee41e Converted back to CHECK since warnings not showing up in regression tables.
[SVN r36386]
2006-12-14 17:49:21 +00:00
Roland Schwarz
cb3f3a1f64 Fixed the missing tss_nul file for testing.
[SVN r36331]
2006-12-11 19:22:40 +00:00
Vladimir Prus
0e44838905 Allow building of shared versions of some Boost.Test libraries.
Adjust tests to use always use static linking to Boost.Test, since
linking to the shared version requires test changes.

Patch from Juergen Hunold.


[SVN r35989]
2006-11-10 19:09:56 +00:00
Roland Schwarz
64cd268fc7 Get rid of dll import warnings for nocopyable classes
[SVN r35796]
2006-10-30 19:27:51 +00:00
Roland Schwarz
f048dd81f2 Merged changes from RC_1_34_0
[SVN r35616]
2006-10-15 10:27:28 +00:00
Roland Schwarz
5746f2214c cosmetics
[SVN r35615]
2006-10-15 10:10:47 +00:00
Roland Schwarz
099af669d4 Made fail of cleanup test for native API a warning.
[SVN r35614]
2006-10-15 10:03:35 +00:00
Roland Schwarz
79cac706a7 Unified spelling of thread library in documentation. (singular)
[SVN r35590]
2006-10-13 16:48:50 +00:00
Roland Schwarz
df229074ac Made size() a constant member function.
[SVN r35589]
2006-10-13 16:41:51 +00:00
Anthony Williams
191c27e856 Added missing #include
[SVN r35577]
2006-10-12 16:30:27 +00:00
Anthony Williams
e5ee01b43c Remove spurious #endif
[SVN r35576]
2006-10-12 14:52:43 +00:00
Anthony Williams
c46b040f6f Applied some of David Deakins' patches for WinCE
[SVN r35532]
2006-10-10 07:34:48 +00:00
Roland Schwarz
72e4794f5b Removed the "intentional memory leak" of the TSS implementation
[SVN r35426]
2006-09-29 19:24:19 +00:00
Anthony Williams
c30b65a0ea Added #ifdef _WIN64 around a direct call to InterlockedCompareExchange rather than the existing call through ice_wrapper. The
platform SDK library for Win64 doesn't include a library version of InterlockedCompareExchange which the ice_wrapper code requires.


[SVN r35340]
2006-09-26 16:31:41 +00:00
Hartmut Kaiser
1cb08ff60c Changed Boost.Thread to use the Boost license.
[SVN r35115]
2006-09-14 23:02:29 +00:00
Anthony Williams
d3d7fd9317 Added call to TlsFree
[SVN r34843]
2006-08-07 16:34:54 +00:00
Peter Dimov
acf0f97663 Simplification, avoids a false leak report
[SVN r34706]
2006-07-24 19:00:30 +00:00
Peter Dimov
34bd87cea7 Moved the on_thread_exit call to a destructor
[SVN r34469]
2006-07-06 19:47:12 +00:00
Peter Dimov
228f11262e Removed the infamous catch(...)
[SVN r34467]
2006-07-06 13:45:13 +00:00
Anthony Williams
9683e0f1cc Added patch from http://lists.boost.org/Archives/boost/2005/05/86395.php to fix bug
https://sourceforge.net/tracker/index.php?func=detail&aid=1424965&group_id=7586&atid=107586


[SVN r33802]
2006-04-25 10:06:38 +00:00
Vladimir Prus
674ae6d571 Remove declaration of 'pthread'. It was hack
[SVN r33596]
2006-04-07 14:00:27 +00:00
Vladimir Prus
690d44e2e6 Setup usage requirements for dllimport/dllexport.
[SVN r33431]
2006-03-22 08:49:42 +00:00
166 changed files with 8609 additions and 11977 deletions

View File

@@ -1,127 +0,0 @@
# Copyright (C) 2001-2003
# William E. Kempf
#
# Permission to use, copy, modify, distribute and sell this software
# and its documentation for any purpose is hereby granted without fee,
# provided that the above copyright notice appear in all copies and
# that both that copyright notice and this permission notice appear
# in supporting documentation. William E. Kempf makes no representations
# about the suitability of this software for any purpose.
# It is provided "as is" without express or implied warranty.
#
# Boost.Threads build Jamfile
#
# Additional configuration variables used:
# See threads.jam.
# 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
once
recursive_mutex
read_write_mutex
thread
tss_hooks
tss_dll
tss_pe
tss
xtime
;
template boost_thread_lib_base
: ## sources ##
<template>thread_base
../src/$(CPP_SOURCES).cpp
: ## requirements ##
<sysinclude>$(BOOST_ROOT) #:should be unnecessary (because already included in thread_base)
<define>BOOST_THREAD_BUILD_LIB=1
# the common names rule ensures that the library will
# be named according to the rules used by the install
# and auto-link features:
common-variant-tag
: ## default build ##
;
template boost_thread_dll_base
: ## sources ##
<template>thread_base
../src/$(CPP_SOURCES).cpp
: ## requirements ##
<sysinclude>$(BOOST_ROOT) #:should be unnecessary (because already included in thread_base)
<define>BOOST_THREAD_BUILD_DLL=1
<runtime-link>dynamic
# the common names rule ensures that the library will
# be named according to the rules used by the install
# and auto-link features:
common-variant-tag
: ## default build ##
;
lib $(boost_thread_lib_name)
: ## sources ##
<template>boost_thread_lib_base
: ## requirements ##
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name)
: ## default build ##
;
dll $(boost_thread_lib_name)
: ## sources ##
<template>boost_thread_dll_base
: ## requirements ##
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name)
: ## default build ##
;
stage bin-stage
: <dll>$(boost_thread_lib_name)
<lib>$(boost_thread_lib_name)
;
install thread lib
: <dll>$(boost_thread_lib_name)
<lib>$(boost_thread_lib_name)
;
if $(boost_thread_lib_settings_ptw32)
{
lib $(boost_thread_lib_name_ptw32)
: ## sources ##
<template>boost_thread_lib_base
: ## requirements ##
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name_ptw32)
$(boost_thread_lib_settings_ptw32)
: ## default build ##
;
dll $(boost_thread_lib_name_ptw32)
: ## sources ##
<template>boost_thread_dll_base
: ## requirements ##
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name_ptw32)
$(boost_thread_lib_settings_ptw32)
: ## default build ##
;
stage bin-stage
: <dll>$(boost_thread_lib_name_ptw32)
<lib>$(boost_thread_lib_name_ptw32)
;
install thread lib
: <dll>$(boost_thread_lib_name_ptw32)
<lib>$(boost_thread_lib_name_ptw32)
;
}
}

View File

@@ -1,41 +1,207 @@
import os ;
# $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)
if [ os.name ] = NT
{
reqts = <link>shared:<define>BOOST_THREAD_BUILD_DLL=1 ;
}
else
{
# Declare the uses system library
lib pthread : : <name>pthread ;
usage = <library>pthread ;
}
#########################################################################
# 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 ;
project boost/thread
: source-location ../src
: usage-requirements $(usage)
: requirements $(reqts) <threading>multi
: 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
;
CPP_SOURCES =
barrier
condition
exceptions
mutex
once
recursive_mutex
read_write_mutex
thread
tss_hooks
tss_dll
tss_pe
tss
xtime
local rule default_threadapi ( )
{
local api = pthread ;
if [ os.name ] = "NT" { api = win32 ; }
return $(api) ;
}
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.cpp
win32/tss_hooks.cpp
win32/tss_dll.cpp
win32/tss_pe.cpp
: ## requirements ##
<threadapi>win32
;
alias thread_sources
: ## pthread sources ##
pthread/thread.cpp
pthread/exceptions.cpp
pthread/tss.cpp
: ## requirements ##
<threadapi>pthread
;
explicit thread_sources ;
lib boost_thread
: $(CPP_SOURCES).cpp
: <link>shared:<define>BOOST_THREAD_BUILD_DLL=1
<link>static:<define>BOOST_THREAD_BUILD_LIB=1
;
: thread_sources
: <conditional>@requirements
:
: <conditional>@usage-requirements
;

View File

@@ -1,70 +0,0 @@
# Copyright (C) 2001-2003
# William E. Kempf
#
# Permission to use, copy, modify, distribute and sell this software
# and its documentation for any purpose is hereby granted without fee,
# provided that the above copyright notice appear in all copies and
# that both that copyright notice and this permission notice appear
# in supporting documentation. William E. Kempf makes no representations
# about the suitability of this software for any purpose.
# It is provided "as is" without express or implied warranty.
# Additional configuration variables used:
# 1. PTW32_DIR and PTW32_LIB may be used on Win32 platforms to specify that
# a version of Boost.Threads should be built that uses the
# the pthreads-win32 library instead of the Win32 native threading APIs.
# This feature is mostly used for testing and it's generally recommended
# that you use the Win32 native threading libraries instead.
#
# PTW32_Dir should be set to the installation path of the
# pthreads-win32 library and PTW32_LIB should be set to the name of the
# library variant to link against (see the pthreads-win32 documentation).
# Example: jam -sPTW32_DIR="c:\pthreads-win32" -sPTW32_LIB="pthreadVCE.lib"
# Alternately, environment variables having the names PTW32_DIR and PTW32_LIB
# can be set instead of passing these values on the command line.
#
# In either case, libraries having the names boost_thread_ptw32<tags>.dll
# and libboost_thread_ptw32<tags>.lib will be built
# in addition to the usual boost_thread<tags>.dll and
# libboost_thread<tags>.lib. Link with one of the ptw32 versions
# of the Boost.Threads libraries to use the version of Boost.Threads
# that is implemented using pthreads-win32 (you will need to #define
# BOOST_THREAD_NO_LIB or BOOST_ALL_NO_LIB to disable auto-linking
# if your platform supports auto-linking in order to prevent
# your build from attempting to link to two different versions of
# the Boost.Threads library).
# Do some OS-specific setup
{
#thread library name
boost_thread_lib_name = boost_thread ;
#thread library name with "pthreads-win32" library
boost_thread_lib_name_ptw32 = boost_thread_ptw32 ;
if $(NT)
{
if $(PTW32_DIR)
{
if $(PTW32_LIB)
{
boost_thread_lib_settings_ptw32 =
<define>BOOST_HAS_PTHREADS
<define>PtW32NoCatchWarn
<include>$(PTW32_DIR)/pre-built/include
<library-file>$(PTW32_DIR)/pre-built/lib/$(PTW32_LIB)
;
}
}
}
template thread_base
: ## sources ##
: ## requirements ##
<sysinclude>$(BOOST_ROOT)
<threading>multi
<borland><*><cxxflags>-w-8004
<borland><*><cxxflags>-w-8057
: ## default build ##
;
}

Binary file not shown.

View File

@@ -1,3 +1,8 @@
# Copyright (C) 2001-2003
# William E. Kempf
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import toolset ;
toolset.using doxygen ;

View File

@@ -1,14 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<section id="thread.acknowledgements"
last-revision="$Date$">
<title>Acknowledgements</title>
<para>William E. Kempf was the architect, designer, and implementor of
&Boost.Threads;.</para>
&Boost.Thread;.</para>
<para>Mac OS Carbon implementation written by Mac Murrett.</para>
<para>Dave Moore provided initial submissions and further comments on the
<code>barrier</code>
@@ -28,7 +32,7 @@ last-revision="$Date$">
on the design), Paul Mclachlan, Thomas Matelich and Iain Hanson (for help
in trying to get the build to work on other platforms), and Kevin S. Van
Horn (for several updates/corrections to the documentation).</para>
<para>Mike Glassford finished changes to &Boost.Threads; that were begun
<para>Mike Glassford finished changes to &Boost.Thread; that were begun
by William Kempf and moved them into the main CVS branch.
He also addressed a number of issues that were brought up on the Boost
developer's mailing list and provided some additions and changes to the
@@ -38,7 +42,7 @@ last-revision="$Date$">
Mike Glassford finished William Kempf's conversion of the documentation to
BoostBook format and added a number of new sections.</para>
<para>Discussions on the boost.org mailing list were essential in the
development of &Boost.Threads;
development of &Boost.Thread;
. As of August 1, 2001, participants included Alan Griffiths, Albrecht
Fritzsche, Aleksey Gurtovoy, Alexander Terekhov, Andrew Green, Andy Sawyer,
Asger Alstrup Nielsen, Beman Dawes, Bill Klein, Bill Rutiser, Bill Wade,
@@ -59,6 +63,11 @@ 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>

View File

@@ -1,9 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/barrier.hpp"
last-revision="$Date$">
<namespace name="boost">
@@ -32,9 +36,9 @@
and reset the barrier. This functionality allows the same set of N threads to re-use
a barrier object to synchronize their execution at multiple points during their
execution.</para>
<para>See <xref linkend="threads.glossary"/> for definitions of thread
states <link linkend="threads.glossary.thread-state">blocked</link>
and <link linkend="threads.glossary.thread-state">ready</link>.
<para>See <xref linkend="thread.glossary"/> for definitions of thread
states <link linkend="thread.glossary.thread-state">blocked</link>
and <link linkend="thread.glossary.thread-state">ready</link>.
Note that "waiting" is a synonym for blocked.</para>
</description>

View File

@@ -1,14 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<bibliography id="threads.bibliography"
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<bibliography id="thread.bibliography"
last-revision="$Date$">
<title>Bibliography</title>
<biblioentry id="threads.bib.AndrewsSchneider83">
<abbrev id="threads.bib.AndrewsSchneider83.abbrev">AndrewsSchnieder83</abbrev>
<biblioentry id="thread.bib.AndrewsSchneider83">
<abbrev id="thread.bib.AndrewsSchneider83.abbrev">AndrewsSchnieder83</abbrev>
<biblioset relation="journal">
<title>ACM Computing Surveys</title>
<volumenum>Vol. 15</volumenum>
@@ -38,18 +42,18 @@ last-revision="$Date$">
Expressions, Message Passing, and Remote Procedure Call in addition to the
basics</para>
</biblioentry>
<biblioentry id="threads.bib.Boost">
<abbrev id="threads.bib.Boost.abbrev">Boost</abbrev>
<biblioentry id="thread.bib.Boost">
<abbrev id="thread.bib.Boost.abbrev">Boost</abbrev>
<bibliomisc>The <emphasis>Boost</emphasis> world wide web site.
<ulink url="http:/www.boost.org">http://www.boost.org</ulink></bibliomisc>
<para>&Boost.Threads; is one of many Boost libraries. The Boost web
<para>&Boost.Thread; is one of many Boost libraries. The Boost web
site includes a great deal of documentation and general information which
applies to all Boost libraries. Current copies of the libraries including
documentation and test programs may be downloaded from the web
site.</para>
</biblioentry>
<biblioentry id="threads.bib.Hansen73">
<abbrev id="threads.bib.Hansen73.abbrev">Hansen73</abbrev>
<biblioentry id="thread.bib.Hansen73">
<abbrev id="thread.bib.Hansen73.abbrev">Hansen73</abbrev>
<biblioset relation="journal">
<title>ACM Computing Surveys</title>
<volumenum>Vol. 5</volumenum>
@@ -74,8 +78,8 @@ last-revision="$Date$">
Brinch Hansen was years ahead of others in recognizing pattern concepts
applied to software, too.</para>
</biblioentry>
<biblioentry id="threads.bib.Butenhof97">
<abbrev id="threads.bib.Butenhof97.abbrev">Butenhof97</abbrev>
<biblioentry id="thread.bib.Butenhof97">
<abbrev id="thread.bib.Butenhof97.abbrev">Butenhof97</abbrev>
<title>
<ulink url="http://cseng.aw.com/book/0,3828,0201633922,00.html"
>Programming with POSIX Threads </ulink>
@@ -92,8 +96,8 @@ last-revision="$Date$">
them. Many of the insights given apply to all multithreaded programming, not
just POSIX Threads</para>
</biblioentry>
<biblioentry id="threads.bib.Hoare74">
<abbrev id="threads.bib.Hoare74.abbrev">Hoare74</abbrev>
<biblioentry id="thread.bib.Hoare74">
<abbrev id="thread.bib.Hoare74.abbrev">Hoare74</abbrev>
<biblioset relation="journal">
<title>Communications of the ACM</title>
<volumenum>Vol. 17</volumenum>
@@ -115,8 +119,8 @@ last-revision="$Date$">
multithreading patterns. This is one of the most often referenced papers in
all of computer science, and with good reason.</para>
</biblioentry>
<biblioentry id="threads.bib.ISO98">
<abbrev id="threads.bib.ISO98.abbrev">ISO98</abbrev>
<biblioentry id="thread.bib.ISO98">
<abbrev id="thread.bib.ISO98.abbrev">ISO98</abbrev>
<title>
<ulink url="http://www.ansi.org">Programming Language C++</ulink>
</title>
@@ -125,8 +129,8 @@ last-revision="$Date$">
<para>This is the official C++ Standards document. Available from the ANSI
(American National Standards Institute) Electronic Standards Store.</para>
</biblioentry>
<biblioentry id="threads.bib.McDowellHelmbold89">
<abbrev id="threads.bib.McDowellHelmbold89.abbrev">McDowellHelmbold89</abbrev>
<biblioentry id="thread.bib.McDowellHelmbold89">
<abbrev id="thread.bib.McDowellHelmbold89.abbrev">McDowellHelmbold89</abbrev>
<biblioset relation="journal">
<title>Communications of the ACM</title>
<volumenum>Vol. 21</volumenum>
@@ -153,8 +157,8 @@ last-revision="$Date$">
<para>Identifies many of the unique failure modes and debugging difficulties
associated with concurrent programs.</para>
</biblioentry>
<biblioentry id="threads.bib.SchmidtPyarali">
<abbrev id="threads.bib.SchmidtPyarali.abbrev">SchmidtPyarali</abbrev>
<biblioentry id="thread.bib.SchmidtPyarali">
<abbrev id="thread.bib.SchmidtPyarali.abbrev">SchmidtPyarali</abbrev>
<title>
<ulink url="http://www.cs.wustl.edu/~schmidt/win32-cv-1.html8"
>Strategies for Implementing POSIX Condition Variables on Win32</ulink>
@@ -172,14 +176,14 @@ last-revision="$Date$">
</authorgroup>
<orgname>Department of Computer Science, Washington University, St. Louis,
Missouri</orgname>
<para>Rationale for understanding &Boost.Threads; condition
<para>Rationale for understanding &Boost.Thread; condition
variables. Note that Alexander Terekhov found some bugs in the
implementation given in this article, so pthreads-win32 and &Boost.Threads;
implementation given in this article, so pthreads-win32 and &Boost.Thread;
are even more complicated yet.</para>
</biblioentry>
<biblioentry id="threads.bib.SchmidtStalRohnertBuschmann">
<biblioentry id="thread.bib.SchmidtStalRohnertBuschmann">
<abbrev
id="threads.bib.SchmidtStalRohnertBuschmann.abbrev">SchmidtStalRohnertBuschmann</abbrev>
id="thread.bib.SchmidtStalRohnertBuschmann.abbrev">SchmidtStalRohnertBuschmann</abbrev>
<title>
<ulink
url="http://www.wiley.com/Corporate/Website/Objects/Products/0,9049,104671,00.html"
@@ -210,11 +214,11 @@ last-revision="$Date$">
<copyright><year>2000</year></copyright>
<para>This is a very good explanation of how to apply several patterns
useful for concurrent programming. Among the patterns documented is the
Monitor Pattern mentioned frequently in the &Boost.Threads;
Monitor Pattern mentioned frequently in the &Boost.Thread;
documentation.</para>
</biblioentry>
<biblioentry id="threads.bib.Stroustrup">
<abbrev id="threads.bib.Stroustrup.abbrev">Stroustrup</abbrev>
<biblioentry id="thread.bib.Stroustrup">
<abbrev id="thread.bib.Stroustrup.abbrev">Stroustrup</abbrev>
<title>
<ulink url="http://cseng.aw.com/book/0,3828,0201700735,00.html"
>The C++ Programming Language</ulink>

View File

@@ -1,58 +1,137 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Copyright (c) 2007 Roland Schwarz
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<section id="thread.build" last-revision="$Date$">
<title>Build</title>
<para>
How you build the &Boost.Threads; libraries, and how you build your own applications
How you build the &Boost.Thread; libraries, and how you build your own applications
that use those libraries, are some of the most frequently asked questions. Build
processes are difficult to deal with in a portable manner. That's one reason
why &Boost.Threads; makes use of &Boost.Build;.
why &Boost.Thread; makes use of &Boost.Build;.
In general you should refer to the documentation for &Boost.Build;.
This document will only supply you with some simple usage examples for how to
use <emphasis>bjam</emphasis> to build and test &Boost.Threads;. In addition, this document
use <emphasis>bjam</emphasis> to build and test &Boost.Thread;. In addition, this document
will try to explain the build requirements so that users may create their own
build processes (for instance, create an IDE specific project), both for building
and testing &Boost.Threads;, as well as for building their own projects using
&Boost.Threads;.
and testing &Boost.Thread;, as well as for building their own projects using
&Boost.Thread;.
</para>
<section id="thread.build.building">
<title>Building the &Boost.Threads; Libraries</title>
<para>
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>
<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.Threads; Libraries</title>
<title>Testing the &Boost.Thread; 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>
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>
</para>
</section>
</section>

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/condition.hpp"
last-revision="$Date$">
<namespace name="boost">
@@ -21,12 +25,12 @@
<description>
<para>A <classname>condition</classname> object is always used in
conjunction with a <link linkend="threads.concepts.mutexes">mutex</link>
conjunction with a <link linkend="thread.concepts.mutexes">mutex</link>
object (an object whose type is a model of a <link
linkend="threads.concepts.Mutex">Mutex</link> or one of its
linkend="thread.concepts.Mutex">Mutex</link> or one of its
refinements). The mutex object must be locked prior to waiting on the
condition, which is verified by passing a lock object (an object whose
type is a model of <link linkend="threads.concepts.Lock">Lock</link> or
type is a model of <link linkend="thread.concepts.Lock">Lock</link> or
one of its refinements) to the <classname>condition</classname> object's
wait functions. Upon blocking on the <classname>condition</classname>
object, the thread unlocks the mutex object. When the thread returns
@@ -39,8 +43,8 @@
&cite.SchmidtStalRohnertBuschmann; and &cite.Hoare74;). Monitors are one
of the most important patterns for creating reliable multithreaded
programs.</para>
<para>See <xref linkend="threads.glossary"/> for definitions of <link
linkend="threads.glossary.thread-state">thread states</link>
<para>See <xref linkend="thread.glossary"/> for definitions of <link
linkend="thread.glossary.thread-state">thread states</link>
blocked and ready. Note that "waiting" is a synonym for blocked.</para>
</description>
@@ -87,10 +91,10 @@
</parameter>
<requires><simpara><code>ScopedLock</code> meets the <link
linkend="threads.concepts.ScopedLock">ScopedLock</link>
linkend="thread.concepts.ScopedLock">ScopedLock</link>
requirements.</simpara></requires>
<effects><simpara>Releases the lock on the <link
linkend="threads.concepts.mutexes">mutex object</link>
linkend="thread.concepts.mutexes">mutex object</link>
associated with <code>lock</code>, blocks the current thread of execution
until readied by a call to <code>this->notify_one()</code>
or<code> this->notify_all()</code>, and then reacquires the
@@ -116,7 +120,7 @@
</parameter>
<requires><simpara><code>ScopedLock</code> meets the <link
linkend="threads.concepts.ScopedLock">ScopedLock</link>
linkend="thread.concepts.ScopedLock">ScopedLock</link>
requirements and the return from <code>pred()</code> is
convertible to <code>bool</code>.</simpara></requires>
<effects><simpara>As if: <code>while (!pred())
@@ -141,10 +145,10 @@
</parameter>
<requires><simpara><code>ScopedLock</code> meets the <link
linkend="threads.concepts.ScopedLock">ScopedLock</link>
linkend="thread.concepts.ScopedLock">ScopedLock</link>
requirements.</simpara></requires>
<effects><simpara>Releases the lock on the <link
linkend="threads.concepts.mutexes">mutex object</link>
linkend="thread.concepts.mutexes">mutex object</link>
associated with <code>lock</code>, blocks the current thread of execution
until readied by a call to <code>this->notify_one()</code>
or<code> this->notify_all()</code>, or until time <code>xt</code>
@@ -176,7 +180,7 @@
</parameter>
<requires><simpara><code>ScopedLock</code> meets the <link
linkend="threads.concepts.ScopedLock">ScopedLock</link>
linkend="thread.concepts.ScopedLock">ScopedLock</link>
requirements and the return from <code>pred()</code> is
convertible to <code>bool</code>.</simpara></requires>
<effects><simpara>As if: <code>while (!pred()) { if (!timed_wait(lock,

View File

@@ -1,19 +1,23 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<section id="thread.configuration" last-revision="$Date$">
<title>Configuration</title>
<para>&Boost.Threads; uses several configuration macros in &lt;boost/config.hpp&gt;,
<para>&Boost.Thread; uses several configuration macros in &lt;boost/config.hpp&gt;,
as well as configuration macros meant to be supplied by the application. These
macros are documented here.
</para>
<section id="thread.configuration.public">
<title>Library Defined Public Macros</title>
<para>
These macros are defined by &Boost.Threads; but are expected to be used
These macros are defined by &Boost.Thread; but are expected to be used
by application code.
</para>
<informaltable>
@@ -29,9 +33,9 @@
<entry>BOOST_HAS_THREADS</entry>
<entry>
Indicates that threading support is available. This means both that there
is a platform specific implementation for &Boost.Threads; and that
is a platform specific implementation for &Boost.Thread; and that
threading support has been enabled in a platform specific manner. For instance,
on the Win32 platform there&#39;s an implementation for &Boost.Threads;
on the Win32 platform there&#39;s an implementation for &Boost.Thread;
but unless the program is compiled against one of the multithreading runtimes
(often determined by the compiler predefining the macro _MT) the BOOST_HAS_THREADS
macro remains undefined.
@@ -44,7 +48,7 @@
<section id="thread.configuration.implementation">
<title>Library Defined Implementation Macros</title>
<para>
These macros are defined by &Boost.Threads; and are implementation details
These macros are defined by &Boost.Thread; and are implementation details
of interest only to implementors.
</para>
<informaltable>
@@ -60,14 +64,14 @@
<entry>BOOST_HAS_WINTHREADS</entry>
<entry>
Indicates that the platform has the Microsoft Win32 threading libraries,
and that they should be used to implement &Boost.Threads;.
and that they should be used to implement &Boost.Thread;.
</entry>
</row>
<row>
<entry>BOOST_HAS_PTHREADS</entry>
<entry>
Indicates that the platform has the POSIX pthreads libraries, and that
they should be used to implement &Boost.Threads;.
they should be used to implement &Boost.Thread;.
</entry>
</row>
<row>

View File

@@ -1,10 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<section id="threads.design" last-revision="$Date$">
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<section id="thread.design" last-revision="$Date$">
<title>Design</title>
<para>With client/server and three-tier architectures becoming common place
in today's world, it's becoming increasingly important for programs to be
@@ -15,18 +19,18 @@
Further, these APIs are almost universally C APIs and fail to take
advantage of C++'s strengths, or to address concepts unique to C++, such as
exceptions.</para>
<para>The &Boost.Threads; library is an attempt to define a portable interface
<para>The &Boost.Thread; library is an attempt to define a portable interface
for writing parallel processes in C++.</para>
<section id="threads.design.goals">
<section id="thread.design.goals">
<title>Goals</title>
<para>The &Boost.Threads; library has several goals that should help to set
<para>The &Boost.Thread; library has several goals that should help to set
it apart from other solutions. These goals are listed in order of precedence
with full descriptions below.
<variablelist>
<varlistentry>
<term>Portability</term>
<listitem>
<para>&Boost.Threads; was designed to be highly portable. The goal is
<para>&Boost.Thread; was designed to be highly portable. The goal is
for the interface to be easily implemented on any platform that
supports threads, and possibly even on platforms without native thread
support.</para>
@@ -35,8 +39,8 @@
<varlistentry>
<term>Safety</term>
<listitem>
<para>&Boost.Threads; was designed to be as safe as possible. Writing
<link linkend="threads.glossary.thread-safe">thread-safe</link>
<para>&Boost.Thread; was designed to be as safe as possible. Writing
<link linkend="thread.glossary.thread-safe">thread-safe</link>
code is very difficult and successful libraries must strive to
insulate the programmer from dangerous constructs as much as
possible. This is accomplished in several ways:
@@ -45,14 +49,14 @@
<para>C++ language features are used to make correct usage easy
(if possible) and error-prone usage impossible or at least more
difficult. For example, see the <link
linkend="threads.concepts.Mutex">Mutex</link> and <link
linkend="threads.concepts.Lock">Lock</link> designs, and note
linkend="thread.concepts.Mutex">Mutex</link> and <link
linkend="thread.concepts.Lock">Lock</link> designs, and note
how they interact.</para>
</listitem>
<listitem>
<para>Certain traditional concurrent programming features are
considered so error-prone that they are not provided at all. For
example, see <xref linkend="threads.rationale.events" />.</para>
example, see <xref linkend="thread.rationale.events" />.</para>
</listitem>
<listitem>
<para>Dangerous features, or features which may be misused, are
@@ -65,9 +69,9 @@
<varlistentry>
<term>Flexibility</term>
<listitem>
<para>&Boost.Threads; was designed to be flexible. This goal is often
<para>&Boost.Thread; was designed to be flexible. This goal is often
at odds with <emphasis>safety</emphasis>. When functionality might be
compromised by the desire to keep the interface safe, &Boost.Threads;
compromised by the desire to keep the interface safe, &Boost.Thread;
has been designed to provide the functionality, but to make it's use
prohibitive for general use. In other words, the interfaces have been
designed such that it's usually obvious when something is unsafe, and
@@ -77,11 +81,11 @@
<varlistentry>
<term>Efficiency</term>
<listitem>
<para>&Boost.Threads; was designed to be as efficient as
<para>&Boost.Thread; was designed to be as efficient as
possible. When building a library on top of another library there is
always a danger that the result will be so much slower than the
"native" API that programmers are inclined to ignore the higher level
API. &Boost.Threads; was designed to minimize the chances of this
API. &Boost.Thread; was designed to minimize the chances of this
occurring. The interfaces have been crafted to allow an implementation
the greatest chance of being as efficient as possible. This goal is
often at odds with the goal for <emphasis>safety</emphasis>. Every
@@ -94,18 +98,18 @@
</section>
<section>
<title>Iterative Phases</title>
<para>Another goal of &Boost.Threads; was to take a dynamic, iterative
<para>Another goal of &Boost.Thread; was to take a dynamic, iterative
approach in its development. The computing industry is still exploring the
concepts of parallel programming. Most thread libraries supply only simple
primitive concepts for thread synchronization. These concepts are very
simple, but it is very difficult to use them safely or to provide formal
proofs for constructs built on top of them. There has been a lot of research
into other concepts, such as in "Communicating Sequential Processes."
&Boost.Threads; was designed in iterative steps, with each step providing
&Boost.Thread; was designed in iterative steps, with each step providing
the building blocks necessary for the next step and giving the researcher
the tools necessary to explore new concepts in a portable manner.</para>
<para>Given the goal of following a dynamic, iterative approach
&Boost.Threads; shall go through several growth cycles. Each phase in its
&Boost.Thread; shall go through several growth cycles. Each phase in its
development shall be roughly documented here.</para>
</section>
<section>
@@ -119,10 +123,10 @@
much help to a programmer who wants to use the library in his multithreaded
application. So there's a very great need for portable primitives that will
allow the library developer to create <link
linkend="threads.glossary.thread-safe">thread-safe</link>
linkend="thread.glossary.thread-safe">thread-safe</link>
implementations. This need far out weighs the need for portable methods to
create and manage threads.</para>
<para>Because of this need, the first phase of &Boost.Threads; focuses
<para>Because of this need, the first phase of &Boost.Thread; focuses
solely on providing portable primitive concepts for thread
synchronization. Types provided in this phase include the
<classname>boost::mutex</classname>,
@@ -135,16 +139,16 @@
synchronization primitives, though there are others that will be added in
later phases.</para>
</section>
<section id="threads.design.phase2">
<section id="thread.design.phase2">
<title>Phase 2, Thread Management and Thread Specific Storage</title>
<para>This phase addresses the creation and management of threads and
provides a mechanism for thread specific storage (data associated with a
thread instance). Thread management is a tricky issue in C++, so this
phase addresses only the basic needs of multithreaded program. Later
phases are likely to add additional functionality in this area. This
phase of &Boost.Threads; adds the <classname>boost::thread</classname> and
phase of &Boost.Thread; adds the <classname>boost::thread</classname> and
<classname>boost::thread_specific_ptr</classname> types. With these
additions the &Boost.Threads; library can be considered minimal but
additions the &Boost.Thread; library can be considered minimal but
complete.</para>
</section>
<section>

View File

@@ -1,26 +1,31 @@
<!ENTITY Boost.Threads "<emphasis role='bold'>Boost.Threads</emphasis>">
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<!ENTITY Boost "<emphasis role='bold'>Boost</emphasis>">
<!ENTITY Boost.Thread "<emphasis role='bold'>Boost.Thread</emphasis>">
<!ENTITY Boost.Build "<emphasis role='bold'>Boost.Build</emphasis>">
<!ENTITY cite.AndrewsSchneider83 "<citation><xref
linkend='threads.bib.AndrewsSchneider83'
endterm='threads.bib.AndrewsSchneider83.abbrev'/></citation>">
<!ENTITY cite.Boost "<citation><xref linkend='threads.bib.Boost'
endterm='threads.bib.Boost.abbrev'/></citation>">
<!ENTITY cite.Hansen73 "<citation><xref linkend='threads.bib.Hansen73'
endterm='threads.bib.Hansen73.abbrev'/></citation>">
<!ENTITY cite.Butenhof97 "<citation><xref linkend='threads.bib.Butenhof97'
endterm='threads.bib.Butenhof97.abbrev'/></citation>">
<!ENTITY cite.Hoare74 "<citation><xref linkend='threads.bib.Hoare74'
endterm='threads.bib.Hoare74.abbrev'/></citation>">
<!ENTITY cite.ISO98 "<citation><xref linkend='threads.bib.ISO98'
endterm='threads.bib.ISO98.abbrev'/></citation>">
linkend='thread.bib.AndrewsSchneider83'
endterm='thread.bib.AndrewsSchneider83.abbrev'/></citation>">
<!ENTITY cite.Boost "<citation><xref linkend='thread.bib.Boost'
endterm='thread.bib.Boost.abbrev'/></citation>">
<!ENTITY cite.Hansen73 "<citation><xref linkend='thread.bib.Hansen73'
endterm='thread.bib.Hansen73.abbrev'/></citation>">
<!ENTITY cite.Butenhof97 "<citation><xref linkend='thread.bib.Butenhof97'
endterm='thread.bib.Butenhof97.abbrev'/></citation>">
<!ENTITY cite.Hoare74 "<citation><xref linkend='thread.bib.Hoare74'
endterm='thread.bib.Hoare74.abbrev'/></citation>">
<!ENTITY cite.ISO98 "<citation><xref linkend='thread.bib.ISO98'
endterm='thread.bib.ISO98.abbrev'/></citation>">
<!ENTITY cite.McDowellHelmbold89 "<citation><xref
linkend='threads.bib.McDowellHelmbold89'
endterm='threads.bib.McDowellHelmbold89.abbrev'/></citation>">
linkend='thread.bib.McDowellHelmbold89'
endterm='thread.bib.McDowellHelmbold89.abbrev'/></citation>">
<!ENTITY cite.SchmidtPyarali "<citation><xref
linkend='threads.bib.SchmidtPyarali'
endterm='threads.bib.SchmidtPyarali.abbrev'/></citation>">
linkend='thread.bib.SchmidtPyarali'
endterm='thread.bib.SchmidtPyarali.abbrev'/></citation>">
<!ENTITY cite.SchmidtStalRohnertBuschmann "<citation><xref
linkend='threads.bib.SchmidtStalRohnertBuschmann'
endterm='threads.bib.SchmidtStalRohnertBuschmann.abbrev'/></citation>">
<!ENTITY cite.Stroustrup "<citation><xref linkend='threads.bib.Stroustrup'
endterm='threads.bib.Stroustrup.abbrev'/></citation>">
linkend='thread.bib.SchmidtStalRohnertBuschmann'
endterm='thread.bib.SchmidtStalRohnertBuschmann.abbrev'/></citation>">
<!ENTITY cite.Stroustrup "<citation><xref linkend='thread.bib.Stroustrup'
endterm='thread.bib.Stroustrup.abbrev'/></citation>">

View File

@@ -1,9 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/exceptions.hpp"
last-revision="$Date$">
<namespace name="boost">
@@ -34,7 +38,7 @@
<purpose>
<simpara>The <classname>thread_resource_error</classname> class
defines an exception type that is thrown by constructors in the
&Boost.Threads; library when thread-related resources can not be
&Boost.Thread; library when thread-related resources can not be
acquired.</simpara>
</purpose>

View File

@@ -1,45 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<section id="threads.faq" last-revision="$Date$">
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<section id="thread.faq" last-revision="$Date$">
<title>Frequently Asked Questions</title>
<qandaset>
<qandaentry>
<question>
<para>Are lock objects <link
linkend="threads.glossary.thread-safe">thread safe</link>?</para>
linkend="thread.glossary.thread-safe">thread safe</link>?</para>
</question>
<answer>
<para><emphasis role="bold">No!</emphasis> Lock objects are not meant to
be shared between threads. They are meant to be short-lived objects
created on automatic storage within a code block. Any other usage is
just likely to lead to errors and won't really be of actual benefit anyway.
Share <link linkend="threads.concepts.mutexes">Mutexes</link>, not
Share <link linkend="thread.concepts.mutexes">Mutexes</link>, not
Locks. For more information see the <link
linkend="threads.rationale.locks">rationale</link> behind the
linkend="thread.rationale.locks">rationale</link> behind the
design for lock objects.</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Why was &Boost.Threads; modeled after (specific library
<para>Why was &Boost.Thread; modeled after (specific library
name)?</para>
</question>
<answer>
<para>It wasn't. &Boost.Threads; was designed from scratch. Extensive
<para>It wasn't. &Boost.Thread; was designed from scratch. Extensive
design discussions involved numerous people representing a wide range of
experience across many platforms. To ensure portability, the initial
implements were done in parallel using POSIX Threads and the Win32
threading API. But the &Boost.Threads; design is very much in the spirit
threading API. But the &Boost.Thread; design is very much in the spirit
of C++, and thus doesn't model such C based APIs.</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Why wasn't &Boost.Threads; modeled after (specific library
<para>Why wasn't &Boost.Thread; modeled after (specific library
name)?</para>
</question>
<answer>
@@ -54,12 +58,12 @@
</qandaentry>
<qandaentry>
<question>
<para>Why do <link linkend="threads.concepts.mutexes">Mutexes</link>
<para>Why do <link linkend="thread.concepts.mutexes">Mutexes</link>
have noncopyable semantics?</para>
</question>
<answer>
<para>To ensure that <link
linkend="threads.glossary.deadlock">deadlocks</link> don't occur. The
linkend="thread.glossary.deadlock">deadlocks</link> don't occur. The
only logical form of copy would be to use some sort of shallow copy
semantics in which multiple mutex objects could refer to the same mutex
state. This means that if ObjA has a mutex object as part of its state
@@ -73,20 +77,20 @@
<qandaentry>
<question>
<para>How can you prevent <link
linkend="threads.glossary.deadlock">deadlock</link> from occurring when
linkend="thread.glossary.deadlock">deadlock</link> from occurring when
a thread must lock multiple mutexes?</para>
</question>
<answer>
<para>Always lock them in the same order. One easy way of doing this is
to use each mutex's address to determine the order in which they are
locked. A future &Boost.Threads; concept may wrap this pattern up in a
locked. A future &Boost.Thread; concept may wrap this pattern up in a
reusable class.</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Don't noncopyable <link
linkend="threads.concepts.mutexes">Mutex</link> semantics mean that a
linkend="thread.concepts.mutexes">Mutex</link> semantics mean that a
class with a mutex member will be noncopyable as well?</para>
</question>
<answer>
@@ -94,7 +98,7 @@
copy constructor and assignment operator, so they will have to be coded
explicitly. This is a <emphasis role="bold">good thing</emphasis>,
however, since the compiler generated operations would not be <link
linkend="threads.glossary.thread-safe">thread-safe</link>. The following
linkend="thread.glossary.thread-safe">thread-safe</link>. The following
is a simple example of a class with copyable semantics and internal
synchronization through a mutex member.</para>
<programlisting>
@@ -144,7 +148,7 @@ private:
<qandaentry>
<question>
<para>How can you lock a <link
linkend="threads.concepts.mutexes">Mutex</link> member in a const member
linkend="thread.concepts.mutexes">Mutex</link> member in a const member
function, in order to implement the Monitor Pattern?</para>
</question>
<answer>
@@ -165,8 +169,8 @@ private:
</question>
<answer>
<para>Condition variables result in user code much less prone to <link
linkend="threads.glossary.race-condition">race conditions</link> than
event variables. See <xref linkend="threads.rationale.events" />
linkend="thread.glossary.race-condition">race conditions</link> than
event variables. See <xref linkend="thread.rationale.events" />
for analysis. Also see &cite.Hoare74; and &cite.SchmidtStalRohnertBuschmann;.
</para>
</answer>
@@ -177,7 +181,7 @@ private:
</question>
<answer>
<para>There's a valid need for thread termination, so at some point
&Boost.Threads; probably will include it, but only after we can find a
&Boost.Thread; probably will include it, but only after we can find a
truly safe (and portable) mechanism for this concept.</para>
</answer>
</qandaentry>
@@ -206,5 +210,26 @@ private:
condition variable.</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Why doesn't the thread's ctor take at least a void* to pass any
information along with the function? All other threading libs support
that and it makes Boost.Threads inferiour. </para>
</question>
<answer>
<para>There is no need, because Boost.Threads are superiour! First
thing is that its ctor doesn't take a function but a functor. That
means that you can pass an object with an overloaded operator() and
include additional data as members in that object. Beware though that
this object is copied, use boost::ref to prevent that. Secondly, even
a boost::function&lt;void (void)&gt; 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>

View File

@@ -1,10 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<glossary id="threads.glossary" last-revision="$Date$">
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<glossary id="thread.glossary" last-revision="$Date$">
<title>Glossary</title>
<para>Definitions are given in terms of the C++ Standard
&cite.ISO98;. References to the standard are in the form [1.2.3/4], which
@@ -12,9 +16,9 @@
"/".</para>
<para>Because the definitions are written in something akin to "standardese",
they can be difficult to understand. The intent isn't to confuse, but rather
to clarify the additional requirements &Boost.Threads; places on a C++
to clarify the additional requirements &Boost.Thread; places on a C++
implementation as defined by the C++ Standard.</para>
<glossentry id="threads.glossary.thread">
<glossentry id="thread.glossary.thread">
<glossterm>Thread</glossterm>
<glossdef>
<para>Thread is short for "thread of execution". A thread of execution is
@@ -50,13 +54,13 @@
</itemizedlist>
</glossdef>
</glossentry>
<glossentry id="threads.glossary.thread-safe">
<glossentry id="thread.glossary.thread-safe">
<glossterm>Thread-safe</glossterm>
<glossdef>
<para>A program is thread-safe if it has no <link
linkend="threads.glossary.race-condition">race conditions</link>, does
not <link linkend="threads.glossary.deadlock">deadlock</link>, and has
no <link linkend="threads.glossary.priority-failure">priority
linkend="thread.glossary.race-condition">race conditions</link>, does
not <link linkend="thread.glossary.deadlock">deadlock</link>, and has
no <link linkend="thread.glossary.priority-failure">priority
failures</link>.</para>
<para>Note that thread-safety does not necessarily imply efficiency, and
than while some thread-safety violations can be determined statically at
@@ -64,7 +68,7 @@
runtime.</para>
</glossdef>
</glossentry>
<glossentry id="threads.glossary.thread-state">
<glossentry id="thread.glossary.thread-state">
<glossterm>Thread State</glossterm>
<glossdef>
<para>During the lifetime of a thread, it shall be in one of the following
@@ -166,7 +170,7 @@
above table.]</para>
</glossdef>
</glossentry>
<glossentry id="threads.glossary.race-condition">
<glossentry id="thread.glossary.race-condition">
<glossterm>Race Condition</glossterm>
<glossdef>
<para>A race condition is what occurs when multiple threads read from and write
@@ -175,10 +179,10 @@
pattern which isn't even a valid value for the data type. A race condition
results in undefined behavior [1.3.12].</para>
<para>Race conditions can be prevented by serializing memory access using
the tools provided by &Boost.Threads;.</para>
the tools provided by &Boost.Thread;.</para>
</glossdef>
</glossentry>
<glossentry id="threads.glossary.deadlock">
<glossentry id="thread.glossary.deadlock">
<glossterm>Deadlock</glossterm>
<glossdef>
<para>Deadlock is an execution state where for some set of threads, each
@@ -187,14 +191,14 @@
become ready again.</para>
</glossdef>
</glossentry>
<glossentry id="threads.glossary.starvation">
<glossentry id="thread.glossary.starvation">
<glossterm>Starvation</glossterm>
<glossdef>
<para>The condition in which a thread is not making sufficient progress in
its work during a given time interval.</para>
</glossdef>
</glossentry>
<glossentry id="threads.glossary.priority-failure">
<glossentry id="thread.glossary.priority-failure">
<glossterm>Priority Failure</glossterm>
<glossdef>
<para>A priority failure (such as priority inversion or infinite overtaking)
@@ -202,10 +206,10 @@
performed in time to be useful.</para>
</glossdef>
</glossentry>
<glossentry id="threads.glossary.undefined-behavior">
<glossentry id="thread.glossary.undefined-behavior">
<glossterm>Undefined Behavior</glossterm>
<glossdef>
<para>The result of certain operations in &Boost.Threads; is undefined;
<para>The result of certain operations in &Boost.Thread; is undefined;
this means that those operations can invoke almost any behavior when
they are executed.</para>
@@ -220,7 +224,7 @@
programming error.</para>
</glossdef>
</glossentry>
<glossentry id="threads.glossary.memory-visibility">
<glossentry id="thread.glossary.memory-visibility">
<glossterm>Memory Visibility</glossterm>
<glossdef>
<para>An address [1.7] shall always point to the same memory byte,

View File

@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<section id="threads.implementation_notes" last-revision="$Date$">
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<section id="thread.implementation_notes" last-revision="$Date$">
<title>Implementation Notes</title>
<section id="threads.implementation_notes.win32">
<section id="thread.implementation_notes.win32">
<title>Win32</title>
<para>
In the current Win32 implementation, creating a boost::thread object

View File

@@ -1,8 +1,12 @@
<!-- Copyright (c) 2002-2003 Beman Dawes, William E. Kempf.
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<html>
<head>
<meta http-equiv="refresh" content="0; URL=../../../doc/html/threads.html">
<meta http-equiv="refresh" content="0; URL=../../../doc/html/thread.html">
</head>
<body>
Automatic redirection failed, please go to <a href="../../../doc/html/threads.html">../../../doc/html/threads.html</a>
Automatic redirection failed, please go to <a href="../../../doc/html/thread.html">../../../doc/html/thread.html</a>
</body>
</html>

View File

@@ -1,35 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/mutex.hpp"
last-revision="$Date$">
<namespace name="boost">
<class name="mutex">
<purpose>
<para>The <classname>mutex</classname> class is a model of the
<link linkend="threads.concepts.Mutex">Mutex</link> concept.</para>
<link linkend="thread.concepts.Mutex">Mutex</link> concept.</para>
</purpose>
<description>
<para>The <classname>mutex</classname> class is a model of the
<link linkend="threads.concepts.Mutex">Mutex</link> concept.
<link linkend="thread.concepts.Mutex">Mutex</link> concept.
It should be used to synchronize access to shared resources using
<link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
locking mechanics.</para>
<para>For classes that model related mutex concepts, see
<classname>try_mutex</classname> and <classname>timed_mutex</classname>.</para>
<para>For <link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
<para>For <link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
locking mechanics, see <classname>recursive_mutex</classname>,
<classname>recursive_try_mutex</classname>, and <classname>recursive_timed_mutex</classname>.
</para>
<para>The <classname>mutex</classname> class supplies the following typedef,
which <link linkend="threads.concepts.lock-models">models</link>
which <link linkend="thread.concepts.lock-models">models</link>
the specified locking strategy:
<informaltable>
@@ -43,7 +47,7 @@
<tbody>
<row>
<entry>scoped_lock</entry>
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
</tbody>
</tgroup>
@@ -51,7 +55,7 @@
</para>
<para>The <classname>mutex</classname> class uses an
<link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
locking strategy, so attempts to recursively lock a <classname>mutex</classname>
object or attempts to unlock one by threads that don't own a lock on it result in
<emphasis role="bold">undefined behavior</emphasis>.
@@ -61,10 +65,10 @@
<code>NDEBUG</code> is not defined.</para>
<para>Like all
<link linkend="threads.concepts.mutex-models">mutex models</link>
in &Boost.Threads;, <classname>mutex</classname> leaves the
<link linkend="threads.concepts.sheduling-policies">scheduling policy</link>
as <link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
<link linkend="thread.concepts.mutex-models">mutex models</link>
in &Boost.Thread;, <classname>mutex</classname> leaves the
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
Programmers should make no assumptions about the order in which
waiting threads acquire a lock.</para>
</description>
@@ -100,26 +104,26 @@
<class name="try_mutex">
<purpose>
<para>The <classname>try_mutex</classname> class is a model of the
<link linkend="threads.concepts.TryMutex">TryMutex</link> concept.</para>
<link linkend="thread.concepts.TryMutex">TryMutex</link> concept.</para>
</purpose>
<description>
<para>The <classname>try_mutex</classname> class is a model of the
<link linkend="threads.concepts.TryMutex">TryMutex</link> concept.
<link linkend="thread.concepts.TryMutex">TryMutex</link> concept.
It should be used to synchronize access to shared resources using
<link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
locking mechanics.</para>
<para>For classes that model related mutex concepts, see
<classname>mutex</classname> and <classname>timed_mutex</classname>.</para>
<para>For <link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
<para>For <link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
locking mechanics, see <classname>recursive_mutex</classname>,
<classname>recursive_try_mutex</classname>, and <classname>recursive_timed_mutex</classname>.
</para>
<para>The <classname>try_mutex</classname> class supplies the following typedefs,
which <link linkend="threads.concepts.lock-models">model</link>
which <link linkend="thread.concepts.lock-models">model</link>
the specified locking strategies:
<informaltable>
@@ -133,11 +137,11 @@
<tbody>
<row>
<entry>scoped_lock</entry>
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
<row>
<entry>scoped_try_lock</entry>
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
</row>
</tbody>
</tgroup>
@@ -145,7 +149,7 @@
</para>
<para>The <classname>try_mutex</classname> class uses an
<link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
locking strategy, so attempts to recursively lock a <classname>try_mutex</classname>
object or attempts to unlock one by threads that don't own a lock on it result in
<emphasis role="bold">undefined behavior</emphasis>.
@@ -155,10 +159,10 @@
<code>NDEBUG</code> is not defined.</para>
<para>Like all
<link linkend="threads.concepts.mutex-models">mutex models</link>
in &Boost.Threads;, <classname>try_mutex</classname> leaves the
<link linkend="threads.concepts.sheduling-policies">scheduling policy</link>
as <link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
<link linkend="thread.concepts.mutex-models">mutex models</link>
in &Boost.Thread;, <classname>try_mutex</classname> leaves the
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
Programmers should make no assumptions about the order in which
waiting threads acquire a lock.</para>
</description>
@@ -199,26 +203,26 @@
<class name="timed_mutex">
<purpose>
<para>The <classname>timed_mutex</classname> class is a model of the
<link linkend="threads.concepts.TimedMutex">TimedMutex</link> concept.</para>
<link linkend="thread.concepts.TimedMutex">TimedMutex</link> concept.</para>
</purpose>
<description>
<para>The <classname>timed_mutex</classname> class is a model of the
<link linkend="threads.concepts.TimedMutex">TimedMutex</link> concept.
<link linkend="thread.concepts.TimedMutex">TimedMutex</link> concept.
It should be used to synchronize access to shared resources using
<link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
locking mechanics.</para>
<para>For classes that model related mutex concepts, see
<classname>mutex</classname> and <classname>try_mutex</classname>.</para>
<para>For <link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
<para>For <link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
locking mechanics, see <classname>recursive_mutex</classname>,
<classname>recursive_try_mutex</classname>, and <classname>recursive_timed_mutex</classname>.
</para>
<para>The <classname>timed_mutex</classname> class supplies the following typedefs,
which <link linkend="threads.concepts.lock-models">model</link>
which <link linkend="thread.concepts.lock-models">model</link>
the specified locking strategies:
<informaltable>
@@ -232,15 +236,15 @@
<tbody>
<row>
<entry>scoped_lock</entry>
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
<row>
<entry>scoped_try_lock</entry>
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
</row>
<row>
<entry>scoped_timed_lock</entry>
<entry><link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
</row>
</tbody>
</tgroup>
@@ -248,7 +252,7 @@
</para>
<para>The <classname>timed_mutex</classname> class uses an
<link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
locking strategy, so attempts to recursively lock a <classname>timed_mutex</classname>
object or attempts to unlock one by threads that don't own a lock on it result in
<emphasis role="bold">undefined behavior</emphasis>.
@@ -258,10 +262,10 @@
<code>NDEBUG</code> is not defined.</para>
<para>Like all
<link linkend="threads.concepts.mutex-models">mutex models</link>
in &Boost.Threads;, <classname>timed_mutex</classname> leaves the
<link linkend="threads.concepts.sheduling-policies">scheduling policy</link>
as <link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
<link linkend="thread.concepts.mutex-models">mutex models</link>
in &Boost.Thread;, <classname>timed_mutex</classname> leaves the
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
Programmers should make no assumptions about the order in which
waiting threads acquire a lock.</para>
</description>

View File

@@ -1,9 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/once.hpp"
last-revision="$Date$">
<macro name="BOOST_ONCE_INIT">
@@ -11,7 +15,7 @@
<code>once_flag</code> type (statically initialized to
<macroname>BOOST_ONCE_INIT</macroname>) can be used to run a
routine exactly once. This can be used to initialize data in a
<link linkend="threads.glossary.thread-safe">thread-safe</link>
<link linkend="thread.glossary.thread-safe">thread-safe</link>
manner.</purpose>
<description>The implementation-defined macro
@@ -27,7 +31,7 @@
<code>once_flag</code> type (statically initialized to
<macroname>BOOST_ONCE_INIT</macroname>) can be used to run a
routine exactly once. This can be used to initialize data in a
<link linkend="threads.glossary.thread-safe">thread-safe</link>
<link linkend="thread.glossary.thread-safe">thread-safe</link>
manner.</purpose>
<description>The implementation-defined type <code>once_flag</code>
@@ -45,7 +49,7 @@
<code>once_flag</code> type (statically initialized to
<macroname>BOOST_ONCE_INIT</macroname>) can be used to run a
routine exactly once. This can be used to initialize data in a
<link linkend="threads.glossary.thread-safe">thread-safe</link>
<link linkend="thread.glossary.thread-safe">thread-safe</link>
manner.</purpose>
<description>
@@ -61,25 +65,23 @@ void init()
void thread_proc()
{
boost::call_once(&amp;init, once);
boost::call_once(once, &amp;init);
}</programlisting>
</para></description>
<parameter name="func">
<paramtype>void (*func)()</paramtype>
</parameter>
<parameter name="flag">
<paramtype>once_flag&amp;</paramtype>
</parameter>
<requires>The function <code>func</code> shall not throw
exceptions.</requires>
<parameter name="func">
<paramtype>Function func</paramtype>
</parameter>
<effects>As if (in an atomic fashion):
<code>if (flag == BOOST_ONCE_INIT) func();</code></effects>
<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>
<postconditions><code>flag != BOOST_ONCE_INIT</code>
<postconditions><code>flag != BOOST_ONCE_INIT</code> unless <code>func()</code> throws an exception.
</postconditions>
</function>
</namespace>

View File

@@ -1,19 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<section id="threads.overview" last-revision="$Date$">
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<section id="thread.overview" last-revision="$Date$">
<title>Overview</title>
<section id="threads.introduction">
<section id="thread.introduction">
<title>Introduction</title>
<para>&Boost.Threads; allows C++ programs to execute as multiple,
<para>&Boost.Thread; allows C++ programs to execute as multiple,
asynchronous, independent threads-of-execution. Each thread has its own
machine state including program instruction counter and registers. Programs
which execute as multiple threads are called multithreaded programs to
distinguish them from traditional single-threaded programs. The <link
linkend="threads.glossary">glossary</link> gives a more complete description
linkend="thread.glossary">glossary</link> gives a more complete description
of the multithreading execution environment.</para>
<para>Multithreading provides several advantages:
<itemizedlist>
@@ -44,15 +48,15 @@
multithreaded programs are subject to additional errors:
<itemizedlist>
<listitem>
<para><link linkend="threads.glossary.race-condition">Race
<para><link linkend="thread.glossary.race-condition">Race
conditions</link></para>
</listitem>
<listitem>
<para><link linkend="threads.glossary.deadlock">Deadlock</link>
<para><link linkend="thread.glossary.deadlock">Deadlock</link>
(sometimes called "deadly embrace")</para>
</listitem>
<listitem>
<para><link linkend="threads.glossary.priority-failure">Priority
<para><link linkend="thread.glossary.priority-failure">Priority
failures</link> (priority inversion, infinite overtaking, starvation,
etc.)</para>
</listitem>
@@ -61,10 +65,10 @@
errors. These aren't rare or exotic failures - they are virtually guaranteed
to occur unless multithreaded code is designed to avoid them. Priority
failures are somewhat less common, but are nonetheless serious.</para>
<para>The <link linkend="threads.design">&Boost.Threads; design</link>
<para>The <link linkend="thread.design">&Boost.Thread; design</link>
attempts to minimize these errors, but they will still occur unless the
programmer proactively designs to avoid them.</para>
<note>Please also see <xref linkend="threads.implementation_notes"/>
<note>Please also see <xref linkend="thread.implementation_notes"/>
for additional, implementation-specific considerations.</note>
</section>
<section>
@@ -119,11 +123,11 @@
<title>Runtime libraries</title>
<para>
<emphasis role="bold">Warning:</emphasis> Multithreaded programs such as
those using &Boost.Threads; must link to <link
linkend="threads.glossary.thread-safe">thread-safe</link> versions of
those using &Boost.Thread; must link to <link
linkend="thread.glossary.thread-safe">thread-safe</link> versions of
all runtime libraries used by the program, including the runtime library
for the C++ Standard Library. Failure to do so will cause <link
linkend="threads.glossary.race-condition">race conditions</link> to occur
linkend="thread.glossary.race-condition">race conditions</link> to occur
when multiple threads simultaneously execute runtime library functions for
<code>new</code>, <code>delete</code>, or other language features which
imply shared state.</para>
@@ -169,15 +173,15 @@
</section>
</section>
<section>
<title>Common guarantees for all &Boost.Threads; components</title>
<title>Common guarantees for all &Boost.Thread; components</title>
<section>
<title>Exceptions</title>
<para>&Boost.Threads; destructors never
<para>&Boost.Thread; destructors never
throw exceptions. Unless otherwise specified, other
&Boost.Threads; functions that do not have
&Boost.Thread; functions that do not have
an exception-specification may throw implementation-defined
exceptions.</para>
<para>In particular, &Boost.Threads;
<para>In particular, &Boost.Thread;
reports failure to allocate storage by throwing an exception of type
<code>std::bad_alloc</code> or a class derived from
<code>std::bad_alloc</code>, failure to obtain thread resources other than
@@ -191,7 +195,7 @@
</section>
<section>
<title>NonCopyable requirement</title>
<para>&Boost.Threads; classes documented as
<para>&Boost.Thread; classes documented as
meeting the NonCopyable requirement disallow copy construction and copy
assignment. For the sake of exposition, the synopsis of such classes show
private derivation from <classname>boost::noncopyable</classname>. Users

View File

@@ -1,19 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<section id="threads.rationale" last-revision="$Date$">
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<section id="thread.rationale" last-revision="$Date$">
<title>Rationale</title>
<para>This page explains the rationale behind various design decisions in the
&Boost.Threads; library. Having the rationale documented here should explain
&Boost.Thread; library. Having the rationale documented here should explain
how we arrived at the current design as well as prevent future rehashing of
discussions and thought processes that have already occurred. It can also give
users a lot of insight into the design process required for this
library.</para>
<section id="threads.rationale.Boost.Threads">
<title>Rationale for the Creation of &Boost.Threads;</title>
<section id="thread.rationale.Boost.Thread">
<title>Rationale for the Creation of &Boost.Thread;</title>
<para>Processes often have a degree of "potential parallelism" and it can
often be more intuitive to design systems with this in mind. Further, these
parallel processes can result in more responsive programs. The benefits for
@@ -33,24 +37,24 @@
<para>What's truly needed is C++ language support for threads. However, the
C++ standards committee needs existing practice or a good proposal as a
starting point for adding this to the standard.</para>
<para>The &Boost.Threads; library was developed to provide a C++ developer
<para>The &Boost.Thread; library was developed to provide a C++ developer
with a portable interface for writing multithreaded programs on numerous
platforms. There's a hope that the library can be the basis for a more
detailed proposal for the C++ standards committee to consider for inclusion
in the next C++ standard.</para>
</section>
<section id="threads.rationale.primitives">
<title>Rationale for the Low Level Primitives Supported in &Boost.Threads;</title>
<para>The &Boost.Threads; library supplies a set of low level primitives for
<section id="thread.rationale.primitives">
<title>Rationale for the Low Level Primitives Supported in &Boost.Thread;</title>
<para>The &Boost.Thread; library supplies a set of low level primitives for
writing multithreaded programs, such as mutexes and condition variables. In
fact, the first release of &Boost.Threads; supports only these low level
fact, the first release of &Boost.Thread; supports only these low level
primitives. However, computer science research has shown that use of these
primitives is difficult since it's difficult to mathematically prove that a
usage pattern is correct, meaning it doesn't result in race conditions or
deadlocks. There are several algebras (such as CSP, CCS and Join calculus)
that have been developed to help write provably correct parallel
processes. In order to prove the correctness these processes must be coded
using higher level abstractions. So why does &Boost.Threads; support the
using higher level abstractions. So why does &Boost.Thread; support the
lower level concepts?</para>
<para>The reason is simple: the higher level concepts need to be implemented
using at least some of the lower level concepts. So having portable lower
@@ -64,11 +68,11 @@
level concepts, supporting the lower level concepts provides
greater accessibility.</para>
</section>
<section id="threads.rationale.locks">
<section id="thread.rationale.locks">
<title>Rationale for the Lock Design</title>
<para>Programmers who are used to multithreaded programming issues will
quickly note that the &Boost.Threads; design for mutex lock concepts is not
<link linkend="threads.glossary.thread-safe">thread-safe</link> (this is
quickly note that the &Boost.Thread; design for mutex lock concepts is not
<link linkend="thread.glossary.thread-safe">thread-safe</link> (this is
clearly documented as well). At first this may seem like a serious design
flaw. Why have a multithreading primitive that's not thread-safe
itself?</para>
@@ -91,17 +95,17 @@
since checking the state can occur only by a call after construction, we'd
have a race condition if the lock object were shared between threads.</para>
<para>So, to avoid the overhead of synchronizing access to the state
information and to avoid the race condition, the &Boost.Threads; library
information and to avoid the race condition, the &Boost.Thread; library
simply does nothing to make lock objects thread-safe. Instead, sharing a
lock object between threads results in undefined behavior. Since the only
proper usage of lock objects is within block scope this isn't a problem, and
so long as the lock object is properly used there's no danger of any
multithreading issues.</para>
</section>
<section id="threads.rationale.non-copyable">
<section id="thread.rationale.non-copyable">
<title>Rationale for NonCopyable Thread Type</title>
<para>Programmers who are used to C libraries for multithreaded programming
are likely to wonder why &Boost.Threads; uses a noncopyable design for
are likely to wonder why &Boost.Thread; uses a noncopyable design for
<classname>boost::thread</classname>. After all, the C thread types are
copyable, and you often have a need for copying them within user
code. However, careful comparison of C designs to C++ designs shows a flaw
@@ -137,7 +141,7 @@
appear to bear them out. To illustrate the analysis we'll first provide
pseudo-code illustrating the six typical usage patterns of a thread
object.</para>
<section id="threads.rationale.non-copyable.simple">
<section id="thread.rationale.non-copyable.simple">
<title>1. Use case: Simple creation of a thread.</title>
<programlisting>
void foo()
@@ -146,7 +150,7 @@
}
</programlisting>
</section>
<section id="threads.rationale.non-copyable.joined">
<section id="thread.rationale.non-copyable.joined">
<title>2. Use case: Creation of a thread that's later joined.</title>
<programlisting>
void foo()
@@ -156,7 +160,7 @@
}
</programlisting>
</section>
<section id="threads.rationale.non-copyable.loop">
<section id="thread.rationale.non-copyable.loop">
<title>3. Use case: Simple creation of several threads in a loop.</title>
<programlisting>
void foo()
@@ -166,7 +170,7 @@
}
</programlisting>
</section>
<section id="threads.rationale.non-copyable.loop-join">
<section id="thread.rationale.non-copyable.loop-join">
<title>4. Use case: Creation of several threads in a loop which are later joined.</title>
<programlisting>
void foo()
@@ -178,7 +182,7 @@
}
</programlisting>
</section>
<section id="threads.rationale.non-copyable.pass">
<section id="thread.rationale.non-copyable.pass">
<title>5. Use case: Creation of a thread whose ownership is passed to another object/method.</title>
<programlisting>
void foo()
@@ -188,7 +192,7 @@
}
</programlisting>
</section>
<section id="threads.rationale.non-copyable.shared">
<section id="thread.rationale.non-copyable.shared">
<title>6. Use case: Creation of a thread whose ownership is shared between multiple
objects.</title>
<programlisting>
@@ -221,7 +225,7 @@
use a concept for any of the usage patterns there would be a good argument
for choosing the other design. So we'll code all six usage patterns using
both designs.</para>
<section id="threads.rationale_comparison.non-copyable.simple">
<section id="thread.rationale_comparison.non-copyable.simple">
<title>1. Comparison: simple creation of a thread.</title>
<programlisting>
void foo()
@@ -234,7 +238,7 @@
}
</programlisting>
</section>
<section id="threads.rationale_comparison.non-copyable.joined">
<section id="thread.rationale_comparison.non-copyable.joined">
<title>2. Comparison: creation of a thread that's later joined.</title>
<programlisting>
void foo()
@@ -249,7 +253,7 @@
}
</programlisting>
</section>
<section id="threads.rationale_comparison.non-copyable.loop">
<section id="thread.rationale_comparison.non-copyable.loop">
<title>3. Comparison: simple creation of several threads in a loop.</title>
<programlisting>
void foo()
@@ -264,7 +268,7 @@
}
</programlisting>
</section>
<section id="threads.rationale_comparison.non-copyable.loop-join">
<section id="thread.rationale_comparison.non-copyable.loop-join">
<title>4. Comparison: creation of several threads in a loop which are later joined.</title>
<programlisting>
void foo()
@@ -285,7 +289,7 @@
}
</programlisting>
</section>
<section id="threads.rationale_comparison.non-copyable.pass">
<section id="thread.rationale_comparison.non-copyable.pass">
<title>5. Comparison: creation of a thread whose ownership is passed to another object/method.</title>
<programlisting>
void foo()
@@ -300,7 +304,7 @@
}
</programlisting>
</section>
<section id="threads.rationale_comparison.non-copyable.shared">
<section id="thread.rationale_comparison.non-copyable.shared">
<title>6. Comparison: creation of a thread whose ownership is shared
between multiple objects.</title>
<programlisting>
@@ -321,18 +325,18 @@
<para>This shows the usage patterns being nearly identical in complexity for
both designs. The only actual added complexity occurs because of the use of
operator new in
<link linkend="threads.rationale_comparison.non-copyable.loop-join">(4)</link>,
<link linkend="threads.rationale_comparison.non-copyable.pass">(5)</link>, and
<link linkend="threads.rationale_comparison.non-copyable.shared">(6)</link>;
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>,
<link linkend="thread.rationale_comparison.non-copyable.pass">(5)</link>, and
<link linkend="thread.rationale_comparison.non-copyable.shared">(6)</link>;
and the use of std::auto_ptr and boost::shared_ptr in
<link linkend="threads.rationale_comparison.non-copyable.loop-join">(4)</link> and
<link linkend="threads.rationale_comparison.non-copyable.shared">(6)</link>
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link> and
<link linkend="thread.rationale_comparison.non-copyable.shared">(6)</link>
respectively. However, that's not really
much added complexity, and C++ programmers are used to using these idioms
anyway. Some may dislike the presence of operator new in user code, but
this can be eliminated by proper design of higher level concepts, such as
the boost::thread_group class that simplifies example
<link linkend="threads.rationale_comparison.non-copyable.loop-join">(4)</link>
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>
down to:</para>
<programlisting>
void foo()
@@ -347,49 +351,49 @@
design.</para>
<para>So what about performance? Looking at the above code examples,
we can analyze the theoretical impact to performance that both designs
have. For <link linkend="threads.rationale_comparison.non-copyable.simple">(1)</link>
have. For <link linkend="thread.rationale_comparison.non-copyable.simple">(1)</link>
we can see that platforms that don't have a ref-counted native
thread type (POSIX, for instance) will be impacted by a thread_ref
design. Even if the native thread type is ref-counted there may be an impact
if more state information has to be maintained for concepts foreign to the
native API, such as clean up stacks for Win32 implementations.
For <link linkend="threads.rationale_comparison.non-copyable.joined">(2)</link>
and <link linkend="threads.rationale_comparison.non-copyable.loop">(3)</link>
For <link linkend="thread.rationale_comparison.non-copyable.joined">(2)</link>
and <link linkend="thread.rationale_comparison.non-copyable.loop">(3)</link>
the performance impact will be identical to
<link linkend="threads.rationale_comparison.non-copyable.simple">(1)</link>.
For <link linkend="threads.rationale_comparison.non-copyable.loop-join">(4)</link>
<link linkend="thread.rationale_comparison.non-copyable.simple">(1)</link>.
For <link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>
things get a little more interesting and we find that theoretically at least
the thread_ref may perform faster since the thread design requires dynamic
memory allocation/deallocation. However, in practice there may be dynamic
allocation for the thread_ref design as well, it will just be hidden from
the user. As long as the implementation has to do dynamic allocations the
thread_ref loses again because of the reference management. For
<link linkend="threads.rationale_comparison.non-copyable.pass">(5)</link> we see
<link linkend="thread.rationale_comparison.non-copyable.pass">(5)</link> we see
the same impact as we do for
<link linkend="threads.rationale_comparison.non-copyable.loop-join">(4)</link>.
For <link linkend="threads.rationale_comparison.non-copyable.shared">(6)</link>
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>.
For <link linkend="thread.rationale_comparison.non-copyable.shared">(6)</link>
we still have a possible impact to
the thread design because of dynamic allocation but thread_ref no longer
suffers because of its reference management, and in fact, theoretically at
least, the thread_ref may do a better job of managing the references. All of
this indicates that thread wins for
<link linkend="threads.rationale_comparison.non-copyable.simple">(1)</link>,
<link linkend="threads.rationale_comparison.non-copyable.joined">(2)</link> and
<link linkend="threads.rationale_comparison.non-copyable.loop">(3)</link>; with
<link linkend="threads.rationale_comparison.non-copyable.loop-join">(4)</link>
and <link linkend="threads.rationale_comparison.non-copyable.pass">(5)</link> the
<link linkend="thread.rationale_comparison.non-copyable.simple">(1)</link>,
<link linkend="thread.rationale_comparison.non-copyable.joined">(2)</link> and
<link linkend="thread.rationale_comparison.non-copyable.loop">(3)</link>; with
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>
and <link linkend="thread.rationale_comparison.non-copyable.pass">(5)</link> the
winner depending on the implementation and the platform but with the thread design
probably having a better chance; and with
<link linkend="threads.rationale_comparison.non-copyable.shared">(6)</link>
<link linkend="thread.rationale_comparison.non-copyable.shared">(6)</link>
it will again depend on the
implementation and platform but this time we favor thread_ref
slightly. Given all of this it's a narrow margin, but the thread design
prevails.</para>
<para>Given this analysis, and the fact that noncopyable objects for system
resources are the normal designs that C++ programmers are used to dealing
with, the &Boost.Threads; library has gone with a noncopyable design.</para>
with, the &Boost.Thread; library has gone with a noncopyable design.</para>
</section>
<section id="threads.rationale.events">
<section id="thread.rationale.events">
<title>Rationale for not providing <emphasis>Event Variables</emphasis></title>
<para><emphasis>Event variables</emphasis> are simply far too
error-prone. <classname>boost::condition</classname> variables are a much safer
@@ -416,13 +420,13 @@
experiences caused them to be very careful in their use of event
variables. Overt problems can be avoided, for example, by teaming the event
variable with a mutex, but that may just convert a <link
linkend="threads.glossary.race-condition">race condition</link> into another
linkend="thread.glossary.race-condition">race condition</link> into another
problem, such as excessive resource use. One of the most distressing aspects
of the experience reports is the claim that many defects are latent. That
is, the programs appear to work correctly, but contain hidden timing
dependencies which will cause them to fail when environmental factors or
usage patterns change, altering relative thread timings.</para>
<para>The decision to exclude event variables from &Boost.Threads; has been
<para>The decision to exclude event variables from &Boost.Thread; has been
surprising to some Windows programmers. They have written programs which
work using event variables, and wonder what the problem is. It seems similar
to the "goto considered harmful" controversy of 30 years ago. It isn't that

View File

@@ -1,9 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/read_write_mutex.hpp"
last-revision="$Date$">
<namespace name="boost">
@@ -16,13 +20,13 @@
<purpose>
<para>Specifies the
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
to use when a set of threads try to obtain different types of
locks simultaneously.</para>
</purpose>
<description>
<para>The only clock type supported by &Boost.Threads; is
<para>The only clock type supported by &Boost.Thread; is
<code>TIME_UTC</code>. The epoch for <code>TIME_UTC</code>
is 1970-01-01 00:00:00.</para>
</description>
@@ -32,21 +36,31 @@
<class name="read_write_mutex">
<purpose>
<para>The <classname>read_write_mutex</classname> class is a model of the
<link linkend="threads.concepts.ReadWriteMutex">ReadWriteMutex</link> concept.</para>
<link linkend="thread.concepts.ReadWriteMutex">ReadWriteMutex</link> concept.</para>
<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>
</purpose>
<description>
<para>The <classname>read_write_mutex</classname> class is a model of the
<link linkend="threads.concepts.ReadWriteMutex">ReadWriteMutex</link> concept.
<link linkend="thread.concepts.ReadWriteMutex">ReadWriteMutex</link> concept.
It should be used to synchronize access to shared resources using
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
locking mechanics.</para>
<para>For classes that model related mutex concepts, see
<classname>try_read_write_mutex</classname> and <classname>timed_read_write_mutex</classname>.</para>
<para>The <classname>read_write_mutex</classname> class supplies the following typedefs,
which <link linkend="threads.concepts.read-write-lock-models">model</link>
which <link linkend="thread.concepts.read-write-lock-models">model</link>
the specified locking strategies:
<informaltable>
@@ -60,15 +74,15 @@
<tbody>
<row>
<entry>scoped_read_write_lock</entry>
<entry><link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
<entry><link linkend="thread.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
</row>
<row>
<entry>scoped_read_lock</entry>
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
<row>
<entry>scoped_write_lock</entry>
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
</tbody>
</tgroup>
@@ -76,7 +90,7 @@
</para>
<para>The <classname>read_write_mutex</classname> class uses an
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
locking strategy, so attempts to recursively lock a <classname>read_write_mutex</classname>
object or attempts to unlock one by threads that don't own a lock on it result in
<emphasis role="bold">undefined behavior</emphasis>.
@@ -86,20 +100,20 @@
<code>NDEBUG</code> is not defined.</para>
<para>Like all
<link linkend="threads.concepts.read-write-mutex-models">read/write mutex models</link>
in &Boost.Threads;, <classname>read_write_mutex</classname> has two types of
<link linkend="threads.concepts.read-write-scheduling-policies">scheduling policies</link>, an
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
<link linkend="thread.concepts.read-write-mutex-models">read/write mutex models</link>
in &Boost.Thread;, <classname>read_write_mutex</classname> has two types of
<link linkend="thread.concepts.read-write-scheduling-policies">scheduling policies</link>, an
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
between threads trying to obtain different types of locks and an
<link linkend="threads.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link>
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link>
between threads trying to obtain the same type of lock.
The <classname>read_write_mutex</classname> class allows the
programmer to choose what
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
will be used; however, like all read/write mutex models,
<classname>read_write_mutex</classname> leaves the
<link linkend="threads.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>.
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>.
</para>
<note>Self-deadlock is virtually guaranteed if a thread tries to
@@ -155,21 +169,31 @@
<class name="try_read_write_mutex">
<purpose>
<para>The <classname>try_read_write_mutex</classname> class is a model of the
<link linkend="threads.concepts.TryReadWriteMutex">TryReadWriteMutex</link> concept.</para>
<link linkend="thread.concepts.TryReadWriteMutex">TryReadWriteMutex</link> concept.</para>
<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>
</purpose>
<description>
<para>The <classname>try_read_write_mutex</classname> class is a model of the
<link linkend="threads.concepts.TryReadWriteMutex">TryReadWriteMutex</link> concept.
<link linkend="thread.concepts.TryReadWriteMutex">TryReadWriteMutex</link> concept.
It should be used to synchronize access to shared resources using
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
locking mechanics.</para>
<para>For classes that model related mutex concepts, see
<classname>read_write_mutex</classname> and <classname>timed_read_write_mutex</classname>.</para>
<para>The <classname>try_read_write_mutex</classname> class supplies the following typedefs,
which <link linkend="threads.concepts.read-write-lock-models">model</link>
which <link linkend="thread.concepts.read-write-lock-models">model</link>
the specified locking strategies:
<informaltable>
@@ -183,27 +207,27 @@
<tbody>
<row>
<entry>scoped_read_write_lock</entry>
<entry><link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
<entry><link linkend="thread.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
</row>
<row>
<entry>scoped_try_read_write_lock</entry>
<entry><link linkend="threads.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
<entry><link linkend="thread.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
</row>
<row>
<entry>scoped_read_lock</entry>
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
<row>
<entry>scoped_try_read_lock</entry>
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
</row>
<row>
<entry>scoped_write_lock</entry>
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
<row>
<entry>scoped_try_write_lock</entry>
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
</row>
</tbody>
</tgroup>
@@ -211,7 +235,7 @@
</para>
<para>The <classname>try_read_write_mutex</classname> class uses an
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
locking strategy, so attempts to recursively lock a <classname>try_read_write_mutex</classname>
object or attempts to unlock one by threads that don't own a lock on it result in
<emphasis role="bold">undefined behavior</emphasis>.
@@ -221,20 +245,20 @@
<code>NDEBUG</code> is not defined.</para>
<para>Like all
<link linkend="threads.concepts.read-write-mutex-models">read/write mutex models</link>
in &Boost.Threads;, <classname>try_read_write_mutex</classname> has two types of
<link linkend="threads.concepts.read-write-scheduling-policies">scheduling policies</link>, an
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
<link linkend="thread.concepts.read-write-mutex-models">read/write mutex models</link>
in &Boost.Thread;, <classname>try_read_write_mutex</classname> has two types of
<link linkend="thread.concepts.read-write-scheduling-policies">scheduling policies</link>, an
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
between threads trying to obtain different types of locks and an
<link linkend="threads.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link>
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link>
between threads trying to obtain the same type of lock.
The <classname>try_read_write_mutex</classname> class allows the
programmer to choose what
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
will be used; however, like all read/write mutex models,
<classname>try_read_write_mutex</classname> leaves the
<link linkend="threads.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
<link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
<link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
</para>
<note>Self-deadlock is virtually guaranteed if a thread tries to
@@ -297,21 +321,31 @@
<class name="timed_read_write_mutex">
<purpose>
<para>The <classname>timed_read_write_mutex</classname> class is a model of the
<link linkend="threads.concepts.TimedReadWriteMutex">TimedReadWriteMutex</link> concept.</para>
<link linkend="thread.concepts.TimedReadWriteMutex">TimedReadWriteMutex</link> concept.</para>
<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>
</purpose>
<description>
<para>The <classname>timed_read_write_mutex</classname> class is a model of the
<link linkend="threads.concepts.TimedReadWriteMutex">TimedReadWriteMutex</link> concept.
<link linkend="thread.concepts.TimedReadWriteMutex">TimedReadWriteMutex</link> concept.
It should be used to synchronize access to shared resources using
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
locking mechanics.</para>
<para>For classes that model related mutex concepts, see
<classname>read_write_mutex</classname> and <classname>try_read_write_mutex</classname>.</para>
<para>The <classname>timed_read_write_mutex</classname> class supplies the following typedefs,
which <link linkend="threads.concepts.read-write-lock-models">model</link>
which <link linkend="thread.concepts.read-write-lock-models">model</link>
the specified locking strategies:
<informaltable>
@@ -325,39 +359,39 @@
<tbody>
<row>
<entry>scoped_read_write_lock</entry>
<entry><link linkend="threads.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
<entry><link linkend="thread.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
</row>
<row>
<entry>scoped_try_read_write_lock</entry>
<entry><link linkend="threads.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
<entry><link linkend="thread.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
</row>
<row>
<entry>scoped_timed_read_write_lock</entry>
<entry><link linkend="threads.concepts.ScopedTimedReadWriteLock">ScopedTimedReadWriteLock</link></entry>
<entry><link linkend="thread.concepts.ScopedTimedReadWriteLock">ScopedTimedReadWriteLock</link></entry>
</row>
<row>
<entry>scoped_read_lock</entry>
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
<row>
<entry>scoped_try_read_lock</entry>
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
</row>
<row>
<entry>scoped_timed_read_lock</entry>
<entry><link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
</row>
<row>
<entry>scoped_write_lock</entry>
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
<row>
<entry>scoped_try_write_lock</entry>
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
</row>
<row>
<entry>scoped_timed_write_lock</entry>
<entry><link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
</row>
</tbody>
</tgroup>
@@ -365,7 +399,7 @@
</para>
<para>The <classname>timed_read_write_mutex</classname> class uses an
<link linkend="threads.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
locking strategy, so attempts to recursively lock a <classname>timed_read_write_mutex</classname>
object or attempts to unlock one by threads that don't own a lock on it result in
<emphasis role="bold">undefined behavior</emphasis>.
@@ -375,20 +409,20 @@
<code>NDEBUG</code> is not defined.</para>
<para>Like all
<link linkend="threads.concepts.read-write-mutex-models">read/write mutex models</link>
in &Boost.Threads;, <classname>timed_read_write_mutex</classname> has two types of
<link linkend="threads.concepts.read-write-scheduling-policies">scheduling policies</link>, an
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
<link linkend="thread.concepts.read-write-mutex-models">read/write mutex models</link>
in &Boost.Thread;, <classname>timed_read_write_mutex</classname> has two types of
<link linkend="thread.concepts.read-write-scheduling-policies">scheduling policies</link>, an
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
between threads trying to obtain different types of locks and an
<link linkend="threads.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link>
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link>
between threads trying to obtain the same type of lock.
The <classname>timed_read_write_mutex</classname> class allows the
programmer to choose what
<link linkend="threads.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
will be used; however, like all read/write mutex models,
<classname>timed_read_write_mutex</classname> leaves the
<link linkend="threads.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
<link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
<link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
</para>
<note>Self-deadlock is virtually guaranteed if a thread tries to

View File

@@ -1,29 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/recursive_mutex.hpp"
last-revision="$Date$">
<namespace name="boost">
<class name="recursive_mutex">
<purpose>
<para>The <classname>recursive_mutex</classname> class is a model of the
<link linkend="threads.concepts.Mutex">Mutex</link> concept.</para>
<link linkend="thread.concepts.Mutex">Mutex</link> concept.</para>
</purpose>
<description>
<para>The <classname>recursive_mutex</classname> class is a model of the
<link linkend="threads.concepts.Mutex">Mutex</link> concept.
<link linkend="thread.concepts.Mutex">Mutex</link> concept.
It should be used to synchronize access to shared resources using
<link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
locking mechanics.</para>
<para>For classes that model related mutex concepts, see
<classname>recursive_try_mutex</classname> and <classname>recursive_timed_mutex</classname>.</para>
<para>For <link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
<para>For <link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
locking mechanics, see <classname>mutex</classname>,
<classname>try_mutex</classname>, and <classname>timed_mutex</classname>.
</para>
@@ -43,7 +47,7 @@
<tbody>
<row>
<entry>scoped_lock</entry>
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
</tbody>
</tgroup>
@@ -51,7 +55,7 @@
</para>
<para>The <classname>recursive_mutex</classname> class uses a
<link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
locking strategy, so attempts to recursively lock a
<classname>recursive_mutex</classname> object
succeed and an internal "lock count" is maintained.
@@ -60,10 +64,10 @@
<emphasis role="bold">undefined behavior</emphasis>.</para>
<para>Like all
<link linkend="threads.concepts.mutex-models">mutex models</link>
in &Boost.Threads;, <classname>recursive_mutex</classname> leaves the
<link linkend="threads.concepts.sheduling-policies">scheduling policy</link>
as <link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
<link linkend="thread.concepts.mutex-models">mutex models</link>
in &Boost.Thread;, <classname>recursive_mutex</classname> leaves the
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
Programmers should make no assumptions about the order in which
waiting threads acquire a lock.</para>
</description>
@@ -99,20 +103,20 @@
<class name="recursive_try_mutex">
<purpose>
<para>The <classname>recursive_try_mutex</classname> class is a model of the
<link linkend="threads.concepts.TryMutex">TryMutex</link> concept.</para>
<link linkend="thread.concepts.TryMutex">TryMutex</link> concept.</para>
</purpose>
<description>
<para>The <classname>recursive_try_mutex</classname> class is a model of the
<link linkend="threads.concepts.TryMutex">TryMutex</link> concept.
<link linkend="thread.concepts.TryMutex">TryMutex</link> concept.
It should be used to synchronize access to shared resources using
<link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
locking mechanics.</para>
<para>For classes that model related mutex concepts, see
<classname>recursive_mutex</classname> and <classname>recursive_timed_mutex</classname>.</para>
<para>For <link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
<para>For <link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
locking mechanics, see <classname>mutex</classname>,
<classname>try_mutex</classname>, and <classname>timed_mutex</classname>.
</para>
@@ -132,11 +136,11 @@
<tbody>
<row>
<entry>scoped_lock</entry>
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
<row>
<entry>scoped_try_lock</entry>
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
</row>
</tbody>
</tgroup>
@@ -144,7 +148,7 @@
</para>
<para>The <classname>recursive_try_mutex</classname> class uses a
<link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
locking strategy, so attempts to recursively lock a
<classname>recursive_try_mutex</classname> object
succeed and an internal "lock count" is maintained.
@@ -153,10 +157,10 @@
<emphasis role="bold">undefined behavior</emphasis>.</para>
<para>Like all
<link linkend="threads.concepts.mutex-models">mutex models</link>
in &Boost.Threads;, <classname>recursive_try_mutex</classname> leaves the
<link linkend="threads.concepts.sheduling-policies">scheduling policy</link>
as <link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
<link linkend="thread.concepts.mutex-models">mutex models</link>
in &Boost.Thread;, <classname>recursive_try_mutex</classname> leaves the
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
Programmers should make no assumptions about the order in which
waiting threads acquire a lock.</para>
</description>
@@ -197,20 +201,20 @@
<class name="recursive_timed_mutex">
<purpose>
<para>The <classname>recursive_timed_mutex</classname> class is a model of the
<link linkend="threads.concepts.TimedMutex">TimedMutex</link> concept.</para>
<link linkend="thread.concepts.TimedMutex">TimedMutex</link> concept.</para>
</purpose>
<description>
<para>The <classname>recursive_timed_mutex</classname> class is a model of the
<link linkend="threads.concepts.TimedMutex">TimedMutex</link> concept.
<link linkend="thread.concepts.TimedMutex">TimedMutex</link> concept.
It should be used to synchronize access to shared resources using
<link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
locking mechanics.</para>
<para>For classes that model related mutex concepts, see
<classname>recursive_mutex</classname> and <classname>recursive_try_mutex</classname>.</para>
<para>For <link linkend="threads.concepts.unspecified-locking-strategy">Unspecified</link>
<para>For <link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
locking mechanics, see <classname>mutex</classname>,
<classname>try_mutex</classname>, and <classname>timed_mutex</classname>.
</para>
@@ -230,15 +234,15 @@
<tbody>
<row>
<entry>scoped_lock</entry>
<entry><link linkend="threads.concepts.ScopedLock">ScopedLock</link></entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
<row>
<entry>scoped_try_lock</entry>
<entry><link linkend="threads.concepts.ScopedTryLock">ScopedTryLock</link></entry>
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
</row>
<row>
<entry>scoped_timed_lock</entry>
<entry><link linkend="threads.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
</row>
</tbody>
</tgroup>
@@ -246,7 +250,7 @@
</para>
<para>The <classname>recursive_timed_mutex</classname> class uses a
<link linkend="threads.concepts.recursive-locking-strategy">Recursive</link>
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
locking strategy, so attempts to recursively lock a
<classname>recursive_timed_mutex</classname> object
succeed and an internal "lock count" is maintained.
@@ -255,10 +259,10 @@
<emphasis role="bold">undefined behavior</emphasis>.</para>
<para>Like all
<link linkend="threads.concepts.mutex-models">mutex models</link>
in &Boost.Threads;, <classname>recursive_timed_mutex</classname> leaves the
<link linkend="threads.concepts.sheduling-policies">scheduling policy</link>
as <link linkend="threads.concepts.unspecified-scheduling-policy">Unspecified</link>.
<link linkend="thread.concepts.mutex-models">mutex models</link>
in &Boost.Thread;, <classname>recursive_timed_mutex</classname> leaves the
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
Programmers should make no assumptions about the order in which
waiting threads acquire a lock.</para>
</description>

View File

@@ -1,10 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<library-reference id="threads.reference"
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<library-reference id="thread.reference"
last-revision="$Date$"
xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="barrier-ref.xml"/>
@@ -13,6 +17,12 @@
<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"/>

View File

@@ -1,15 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<section id="threads.release_notes" last-revision="$Date$">
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<section id="thread.release_notes" last-revision="$Date$">
<title>Release Notes</title>
<section id="threads.release_notes.boost_1_32_0">
<section id="thread.release_notes.boost_1_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">
<title>Boost 1.32.0</title>
<section id="threads.release_notes.boost_1_32_0.change_log.documentation">
<section id="thread.release_notes.boost_1_32_0.change_log.documentation">
<title>Documentation converted to BoostBook</title>
<para>The documentation was converted to BoostBook format,
@@ -20,24 +80,24 @@
please report them!</para>
</section>
<section id="threads.release_notes.boost_1_32_0.change_log.static_link">
<section id="thread.release_notes.boost_1_32_0.change_log.static_link">
<title>Statically-link build option added</title>
<para>The option to link &Boost.Threads; as a static
<para>The option to link &Boost.Thread; as a static
library has been added (with some limitations on Win32 platforms).
This feature was originally removed from an earlier version
of Boost because <classname>boost::thread_specific_ptr</classname>
required that &Boost.Threads; be dynamically linked in order
required that &Boost.Thread; be dynamically linked in order
for its cleanup functionality to work on Win32 platforms.
Because this limitation never applied to non-Win32 platforms,
because significant progress has been made in removing
the limitation on Win32 platforms (many thanks to
Aaron LaFramboise and Roland Scwarz!), and because the lack
of static linking is one of the most common complaints of
&Boost.Threads; users, this decision was reversed.</para>
&Boost.Thread; users, this decision was reversed.</para>
<para>On non-Win32 platforms:
To choose the dynamically linked version of &Boost.Threads;
To choose the dynamically linked version of &Boost.Thread;
using Boost's auto-linking feature, #define BOOST_THREAD_USE_DLL;
to choose the statically linked version,
#define BOOST_THREAD_USE_LIB.
@@ -63,9 +123,9 @@
because it has not yet been possible to implement automatic
tss cleanup in the statically linked version for compilers
other than VC++, although it is hoped that this will be
possible in a future version of &Boost.Threads;.
possible in a future version of &Boost.Thread;.
Note for advanced users: &Boost.Threads; provides several "hook"
Note for advanced users: &Boost.Thread; provides several "hook"
functions to allow users to experiment with the statically
linked version on Win32 with compilers other than VC++.
These functions are on_process_enter(), on_process_exit(),
@@ -74,13 +134,13 @@
information.</para>
</section>
<section id="threads.release_notes.boost_1_32_0.change_log.barrier">
<section id="thread.release_notes.boost_1_32_0.change_log.barrier">
<title>Barrier functionality added</title>
<para>A new class, <classname>boost::barrier</classname>, was added.</para>
</section>
<section id="threads.release_notes.boost_1_32_0.change_log.read_write_mutex">
<section id="thread.release_notes.boost_1_32_0.change_log.read_write_mutex">
<title>Read/write mutex functionality added</title>
<para>New classes,
@@ -91,13 +151,13 @@
<note>Since the read/write mutex and related classes are new,
both interface and implementation are liable to change
in future releases of &Boost.Threads;.
in future releases of &Boost.Thread;.
The lock concepts and lock promotion in particular are
still under discussion and very likely to change.</note>
</para>
</section>
<section id="threads.release_notes.boost_1_32_0.change_log.thread_specific_ptr">
<section id="thread.release_notes.boost_1_32_0.change_log.thread_specific_ptr">
<title>Thread-specific pointer functionality changed</title>
<para>The <classname>boost::thread_specific_ptr</classname>
@@ -124,7 +184,7 @@
is called.</para>
</section>
<section id="threads.release_notes.boost_1_32_0.change_log.mutex">
<section id="thread.release_notes.boost_1_32_0.change_log.mutex">
<title>Mutex implementation changed for Win32</title>
<para>On Win32, <classname>boost::mutex</classname>,
@@ -135,10 +195,10 @@
<classname>boost::recursive_timed_mutex</classname> use a Win32 mutex.</para>
</section>
<section id="threads.release_notes.boost_1_32_0.change_log.wince">
<section id="thread.release_notes.boost_1_32_0.change_log.wince">
<title>Windows CE support improved</title>
<para>Minor changes were made to make Boost.Threads work on Windows CE.</para>
<para>Minor changes were made to make Boost.Thread work on Windows CE.</para>
</section>
</section>
</section>

View File

@@ -1,9 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/thread.hpp"
last-revision="$Date$">
<namespace name="boost">
@@ -11,15 +15,15 @@
<purpose>
<para>The <classname>thread</classname> class represents threads of
execution, and provides the functionality to create and manage
threads within the &Boost.Threads; library. See
<xref linkend="threads.glossary"/> for a precise description of
<link linkend="threads.glossary.thread">thread of execution</link>,
threads within the &Boost.Thread; library. See
<xref linkend="thread.glossary"/> for a precise description of
<link linkend="thread.glossary.thread">thread of execution</link>,
and for definitions of threading-related terms and of thread states such as
<link linkend="threads.glossary.thread-state">blocked</link>.</para>
<link linkend="thread.glossary.thread-state">blocked</link>.</para>
</purpose>
<description>
<para>A <link linkend="threads.glossary.thread">thread of execution</link>
<para>A <link linkend="thread.glossary.thread">thread of execution</link>
has an initial function. For the program's initial thread, the initial
function is <code>main()</code>. For other threads, the initial
function is <code>operator()</code> of the function object passed to
@@ -36,7 +40,7 @@
&quot;joinable&quot; or &quot;non-joinable&quot;.</para>
<para>Except as described below, the policy used by an implementation
of &Boost.Threads; to schedule transitions between thread states is
of &Boost.Thread; to schedule transitions between thread states is
unspecified.</para>
<para><note>Just as the lifetime of a file may be different from the
@@ -149,7 +153,7 @@
<notes>If <code>*this == thread()</code> the result is
implementation-defined. If the implementation doesn't
detect this the result will be
<link linkend="threads.glossary.deadlock">deadlock</link>.
<link linkend="thread.glossary.deadlock">deadlock</link>.
</notes>
</method>
</method-group>
@@ -170,7 +174,7 @@
<type>void</type>
<effects>The current thread of execution is placed in the
<link linkend="threads.glossary.thread-state">ready</link>
<link linkend="thread.glossary.thread-state">ready</link>
state.</effects>
<notes>

View File

@@ -1,10 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<library name="Threads" dirname="thread" id="threads"
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<library name="Thread" dirname="thread" id="thread"
last-revision="$Date$"
xmlns:xi="http://www.w3.org/2001/XInclude">
<libraryinfo>
@@ -20,19 +24,14 @@ xmlns:xi="http://www.w3.org/2001/XInclude">
<holder>William E. Kempf</holder>
</copyright>
<legalnotice>
<para>Permission to use, copy, modify, distribute and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in all
copies and that both that copyright notice and this permission notice
appear in supporting documentation. William E. Kempf makes no
representations about the suitability of this software for any purpose.
It is provided "as is" without express or implied warranty.</para>
<para>Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)</para>
</legalnotice>
<librarypurpose>Portable C++ multi-threading</librarypurpose>
<librarycategory name="category:concurrent" />
<title>Boost.Threads</title>
<title>Boost.Thread</title>
</libraryinfo>
<title>Boost.Threads</title>
<title>Boost.Thread</title>
<xi:include href="overview.xml"/>
<xi:include href="design.xml"/>
<xi:include href="concepts.xml"/>

View File

@@ -1,9 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/tss.hpp"
last-revision="$Date$">
<namespace name="boost">
@@ -17,7 +21,7 @@
<para>Thread specific storage is data associated with
individual threads and is often used to make operations
that rely on global data
<link linkend="threads.glossary.thread-safe">thread-safe</link>.
<link linkend="thread.glossary.thread-safe">thread-safe</link>.
</para>
<para>Template <classname>thread_specific_ptr</classname>

View File

@@ -1,9 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % threads.entities SYSTEM "entities.xml">
%threads.entities;
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/xtime.hpp"
last-revision="$Date$">
<namespace name="boost">
@@ -16,7 +20,7 @@
</purpose>
<description>
<para>The only clock type supported by &Boost.Threads; is
<para>The only clock type supported by &Boost.Thread; is
<code>TIME_UTC</code>. The epoch for <code>TIME_UTC</code>
is 1970-01-01 00:00:00.</para>
</description>
@@ -33,9 +37,9 @@
<description>
<simpara>The <classname>xtime</classname> type is used to represent a point on
some time scale or a duration in time. This type may be proposed for the C standard by
Markus Kuhn. &Boost.Threads; provides only a very minimal implementation of this
Markus Kuhn. &Boost.Thread; provides only a very minimal implementation of this
proposal; it is expected that a full implementation (or some other time
library) will be provided in Boost as a separate library, at which time &Boost.Threads;
library) will be provided in Boost as a separate library, at which time &Boost.Thread;
will deprecate its own implementation.</simpara>
<simpara><emphasis role="bold">Note</emphasis> that the resolution is

View File

@@ -1,54 +0,0 @@
# Copyright (C) 2001-2003
# William E. Kempf
#
# Permission to use, copy, modify, distribute and sell this software
# and its documentation for any purpose is hereby granted without fee,
# provided that the above copyright notice appear in all copies and
# that both that copyright notice and this permission notice appear
# in supporting documentation. William E. Kempf makes no representations
# about the suitability of this software for any purpose.
# It is provided "as is" without express or implied warranty.
#
# Boost.Threads example Jamfile
#
# Additional configuration variables used:
# 1. PTW32 may be used on Win32 platforms to specify that the pthreads-win32
# library should be used instead of "native" threads. This feature is
# mostly used for testing and it's generally recommended you use the
# native threading libraries instead. PTW32 should be set to be a list
# of two strings, the first specifying the installation path of the
# pthreads-win32 library and the second specifying which library
# variant to link against (see the pthreads-win32 documentation).
# Example: jam -sPTW32="c:\pthreads-win32 pthreadVCE.lib"
# Declare the location of this subproject relative to the root.
subproject libs/thread/example ;
# Include threads.jam for Boost.Threads global build information.
# This greatly simplifies the Jam code needed to configure the build
# for the various Win32 build types.
import ../build/threads ;
{
template example
## sources ##
: <template>thread_base
<dll>../build/boost_thread
## requirements ##
:
## default build ##
:
;
exe monitor : <template>example monitor.cpp ;
exe starvephil : <template>example starvephil.cpp ;
exe tennis : <template>example tennis.cpp ;
exe condition : <template>example condition.cpp ;
exe mutex : <template>example mutex.cpp ;
exe once : <template>example once.cpp ;
exe recursive_mutex : <template>example recursive_mutex.cpp ;
exe thread : <template>example thread.cpp ;
exe thread_group : <template>example thread_group.cpp ;
exe tss : <template>example tss.cpp ;
exe xtime : <template>example xtime.cpp ;
}

View File

@@ -1,3 +1,8 @@
# Copyright (C) 2001-2003
# William E. Kempf
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
project boost/thread/example
: requirements <library>../build//boost_thread <threading>multi

View File

@@ -1,13 +1,8 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <iostream>
#include <vector>

View File

@@ -1,13 +1,8 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <vector>
#include <iostream>

View File

@@ -1,13 +1,8 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>

View File

@@ -1,13 +1,8 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/thread.hpp>
#include <boost/thread/once.hpp>

View File

@@ -1,13 +1,8 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/thread.hpp>

View File

@@ -1,13 +1,8 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>

View File

@@ -1,13 +1,8 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>

View File

@@ -1,13 +1,8 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>

View File

@@ -1,13 +1,8 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/thread.hpp>
#include <iostream>

View File

@@ -1,13 +1,8 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/thread.hpp>
#include <boost/thread/tss.hpp>

View File

@@ -1,13 +1,8 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>

View File

@@ -1,13 +1,8 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_THREAD_WEK01082003_HPP)
#define BOOST_THREAD_WEK01082003_HPP

View File

@@ -1,13 +1,9 @@
// Copyright (C) 2002-2003
// David Moore, William E. Kempf
// Copyright (C) 2007 Anthony Williams
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_BARRIER_JDM030602_HPP
#define BOOST_BARRIER_JDM030602_HPP
@@ -15,25 +11,48 @@
#include <boost/thread/detail/config.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/condition_variable.hpp>
#include <string>
#include <stdexcept>
namespace boost {
class BOOST_THREAD_DECL barrier
namespace boost
{
public:
barrier(unsigned int count);
~barrier();
bool wait();
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;
}
private:
mutex m_mutex;
condition m_cond;
unsigned int m_threshold;
unsigned int m_count;
unsigned int m_generation;
};
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;
};
} // namespace boost

View File

@@ -1,198 +1,16 @@
// Copyright (C) 2001-2003
// William E. Kempf
#ifndef BOOST_THREAD_CONDITION_HPP
#define BOOST_THREAD_CONDITION_HPP
// (C) Copyright 2007 Anthony Williams
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONDITION_WEK070601_HPP
#define BOOST_CONDITION_WEK070601_HPP
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/detail/config.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/utility.hpp>
#include <boost/thread/detail/lock.hpp>
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
#elif defined(BOOST_HAS_MPTASKS)
# include "scoped_critical_region.hpp"
#endif
namespace boost {
struct xtime;
namespace detail {
class BOOST_THREAD_DECL condition_impl : private noncopyable
namespace boost
{
friend class condition;
typedef condition_variable_any 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

View File

@@ -0,0 +1,15 @@
#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>
#include BOOST_THREAD_PLATFORM(condition_variable.hpp)
#endif

View File

@@ -1,18 +1,21 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_THREAD_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>

View File

@@ -1,214 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#ifndef BOOST_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.

View File

@@ -0,0 +1,33 @@
// 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
{
template<typename T>
struct move_t
{
T& t;
move_t(T& t_):
t(t_)
{}
T* operator->() const
{
return &t;
}
};
template<typename T>
move_t<T> move(T& t)
{
return move_t<T>(t);
}
}
#endif

View File

@@ -0,0 +1,72 @@
// Copyright 2006 Roland Schwarz.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_THREAD_RS06040501_HPP
#define BOOST_THREAD_RS06040501_HPP
// fetch compiler and platform configuration
#include <boost/config.hpp>
// insist on threading support being available:
#include <boost/config/requires_threads.hpp>
// choose platform
#if defined(linux) || defined(__linux) || defined(__linux__)
# define BOOST_THREAD_LINUX
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
# define BOOST_THREAD_BSD
#elif defined(sun) || defined(__sun)
# define BOOST_THREAD_SOLARIS
#elif defined(__sgi)
# define BOOST_THREAD_IRIX
#elif defined(__hpux)
# define BOOST_THREAD_HPUX
#elif defined(__CYGWIN__)
# define BOOST_THREAD_CYGWIN
#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
# define BOOST_THREAD_WIN32
#elif defined(__BEOS__)
# define BOOST_THREAD_BEOS
#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
# define BOOST_THREAD_MACOS
#elif defined(__IBMCPP__) || defined(_AIX)
# define BOOST_THREAD_AIX
#elif defined(__amigaos__)
# define BOOST_THREAD_AMIGAOS
#elif defined(__QNXNTO__)
# define BOOST_THREAD_QNXNTO
#elif defined(unix) || defined(__unix) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE)
# if defined(BOOST_HAS_PTHREADS) && !defined(BOOST_THREAD_POSIX)
# define BOOST_THREAD_POSIX
# endif
#endif
// For every supported platform add a new entry into the dispatch table below.
// BOOST_THREAD_POSIX is tested first, so on platforms where posix and native
// threading is available, the user may choose, by defining BOOST_THREAD_POSIX
// in her source. If a platform is known to support pthreads and no native
// port of boost_thread is available just specify "pthread" in the
// dispatcher table. If there is no entry for a platform but pthreads is
// available on the platform, pthread is choosen as default. If nothing is
// available the preprocessor will fail with a diagnostic message.
#if defined(BOOST_THREAD_POSIX)
# define BOOST_THREAD_PPFX pthread
#else
# if defined(BOOST_THREAD_WIN32)
# define BOOST_THREAD_PPFX win32
# elif defined(BOOST_HAS_PTHREADS)
# define BOOST_THREAD_PPFX pthread
# else
# error "Sorry, no boost threads are available for this platform."
# endif
#endif
#define BOOST_THREAD_PLATFORM(header) <boost/thread/BOOST_THREAD_PPFX/header>
#endif // BOOST_THREAD_RS06040501_HPP

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@
//Currently only implemented for Win32, but should
//later be implemented for all platforms.
//Used by Win32 implementation of Boost.Threads
//tss to peform cleanup.
//tss to perform cleanup.
//Like the C runtime library atexit() function,
//which it mimics, at_thread_exit() returns
//zero if successful and a nonzero

View File

@@ -1,13 +1,9 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright (C) 2007 Anthony Williams
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_THREAD_EXCEPTIONS_PDM070801_H
#define BOOST_THREAD_EXCEPTIONS_PDM070801_H
@@ -36,12 +32,21 @@ public:
int native_error() const;
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:

View File

@@ -0,0 +1,520 @@
// 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(boost::move_t<unique_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
}
unique_lock(boost::move_t<upgrade_lock<Mutex> > other);
unique_lock& operator=(boost::move_t<unique_lock<Mutex> > other)
{
unique_lock temp(other);
swap(temp);
return *this;
}
unique_lock& operator=(boost::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(boost::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>
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(boost::move_t<shared_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
}
shared_lock(boost::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(boost::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();
}
}
shared_lock& operator=(boost::move_t<shared_lock<Mutex> > other)
{
shared_lock temp(other);
swap(temp);
return *this;
}
shared_lock& operator=(boost::move_t<unique_lock<Mutex> > other)
{
shared_lock temp(other);
swap(temp);
return *this;
}
shared_lock& operator=(boost::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>
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(boost::move_t<upgrade_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
}
upgrade_lock(boost::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();
}
}
upgrade_lock& operator=(boost::move_t<upgrade_lock<Mutex> > other)
{
upgrade_lock temp(other);
swap(temp);
return *this;
}
upgrade_lock& operator=(boost::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>
unique_lock<Mutex>::unique_lock(boost::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(boost::move(*source))
{}
~upgrade_to_unique_lock()
{
if(source)
{
*source=boost::move(exclusive);
}
}
upgrade_to_unique_lock(boost::move_t<upgrade_to_unique_lock<Mutex> > other):
source(other->source),exclusive(boost::move(other->exclusive))
{
other->source=0;
}
upgrade_to_unique_lock& operator=(boost::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

View File

@@ -1,167 +1,15 @@
// Copyright (C) 2001-2003
// William E. Kempf
#ifndef BOOST_THREAD_MUTEX_HPP
#define BOOST_THREAD_MUTEX_HPP
// mutex.hpp
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// (C) Copyright 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)
#ifndef BOOST_MUTEX_WEK070601_HPP
#define BOOST_MUTEX_WEK070601_HPP
#include <boost/thread/detail/platform.hpp>
#include BOOST_THREAD_PLATFORM(mutex.hpp)
#include <boost/thread/detail/config.hpp>
#include <boost/utility.hpp>
#include <boost/thread/detail/lock.hpp>
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
#endif
#if defined(BOOST_HAS_MPTASKS)
# include "scoped_critical_region.hpp"
#endif
namespace boost {
struct xtime;
class BOOST_THREAD_DECL mutex
: private noncopyable
{
public:
friend class detail::thread::lock_ops<mutex>;
typedef detail::thread::scoped_lock<mutex> scoped_lock;
mutex();
~mutex();
private:
#if defined(BOOST_HAS_WINTHREADS)
typedef void* cv_state;
#elif defined(BOOST_HAS_PTHREADS)
struct cv_state
{
pthread_mutex_t* pmutex;
};
#elif defined(BOOST_HAS_MPTASKS)
struct cv_state
{
};
#endif
void do_lock();
void do_unlock();
void do_lock(cv_state& state);
void do_unlock(cv_state& state);
#if defined(BOOST_HAS_WINTHREADS)
void* m_mutex;
bool m_critical_section;
#elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex;
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
#endif
};
class BOOST_THREAD_DECL try_mutex
: private noncopyable
{
public:
friend class detail::thread::lock_ops<try_mutex>;
typedef detail::thread::scoped_lock<try_mutex> scoped_lock;
typedef detail::thread::scoped_try_lock<try_mutex> scoped_try_lock;
try_mutex();
~try_mutex();
private:
#if defined(BOOST_HAS_WINTHREADS)
typedef void* cv_state;
#elif defined(BOOST_HAS_PTHREADS)
struct cv_state
{
pthread_mutex_t* pmutex;
};
#elif defined(BOOST_HAS_MPTASKS)
struct cv_state
{
};
#endif
void do_lock();
bool do_trylock();
void do_unlock();
void do_lock(cv_state& state);
void do_unlock(cv_state& state);
#if defined(BOOST_HAS_WINTHREADS)
void* m_mutex;
bool m_critical_section;
#elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex;
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
#endif
};
class BOOST_THREAD_DECL timed_mutex
: private noncopyable
{
public:
friend class detail::thread::lock_ops<timed_mutex>;
typedef detail::thread::scoped_lock<timed_mutex> scoped_lock;
typedef detail::thread::scoped_try_lock<timed_mutex> scoped_try_lock;
typedef detail::thread::scoped_timed_lock<timed_mutex> scoped_timed_lock;
timed_mutex();
~timed_mutex();
private:
#if defined(BOOST_HAS_WINTHREADS)
typedef void* cv_state;
#elif defined(BOOST_HAS_PTHREADS)
struct cv_state
{
pthread_mutex_t* pmutex;
};
#elif defined(BOOST_HAS_MPTASKS)
struct cv_state
{
};
#endif
void do_lock();
bool do_trylock();
bool do_timedlock(const xtime& xt);
void do_unlock();
void do_lock(cv_state& state);
void do_unlock(cv_state& state);
#if defined(BOOST_HAS_WINTHREADS)
void* m_mutex;
#elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex;
pthread_cond_t m_condition;
bool m_locked;
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
#endif
};
} // 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

View File

@@ -1,42 +1,23 @@
// Copyright (C) 2001-2003
// William E. Kempf
#ifndef BOOST_THREAD_ONCE_HPP
#define BOOST_THREAD_ONCE_HPP
// once.hpp
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// (C) Copyright 2006-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)
#ifndef BOOST_ONCE_WEK080101_HPP
#define BOOST_ONCE_WEK080101_HPP
#include <boost/thread/detail/platform.hpp>
#include BOOST_THREAD_PLATFORM(once.hpp)
#include <boost/thread/detail/config.hpp>
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
#endif
namespace boost {
#if defined(BOOST_HAS_PTHREADS)
typedef pthread_once_t once_flag;
#define BOOST_ONCE_INIT PTHREAD_ONCE_INIT
#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
typedef long once_flag;
#define BOOST_ONCE_INIT 0
namespace boost
{
inline void call_once(void (*func)(),once_flag& flag)
{
call_once(flag,func);
}
}
#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

View File

@@ -0,0 +1,168 @@
#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 <boost/thread/mutex.hpp>
#include <limits.h>
#include <boost/assert.hpp>
#include <algorithm>
#include <boost/thread/thread_time.hpp>
#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 false;
}
return true;
}
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

View File

@@ -0,0 +1,52 @@
#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/locks.hpp>
#include <boost/thread/thread_time.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 false;
}
return true;
}
void notify_one();
void notify_all();
};
}
#endif

View File

@@ -0,0 +1,197 @@
#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

View File

@@ -0,0 +1,55 @@
#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"
namespace boost {
struct once_flag
{
pthread_mutex_t mutex;
unsigned long flag;
};
#define BOOST_ONCE_INIT {PTHREAD_MUTEX_INITIALIZER,0}
template<typename Function>
void call_once(once_flag& flag,Function f)
{
unsigned long const function_complete_flag_value=0xc15730e2ul;
#ifdef BOOST_PTHREAD_HAS_ATOMICS
if(::boost::detail::interlocked_read_acquire(&flag.flag)!=function_complete_flag_value)
{
#endif
pthread::pthread_mutex_scoped_lock const lock(&flag.mutex);
if(flag.flag!=function_complete_flag_value)
{
f();
#ifdef BOOST_PTHREAD_HAS_ATOMICS
::boost::detail::interlocked_write_release(&flag.flag,function_complete_flag_value);
#else
flag.flag=function_complete_flag_value;
#endif
}
#ifdef BOOST_PTHREAD_HAS_ATOMICS
}
#endif
}
}
#endif

View File

@@ -0,0 +1,34 @@
#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));
}
};
}
}
#endif

View File

@@ -0,0 +1,249 @@
#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

View File

@@ -0,0 +1,307 @@
#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

View File

@@ -0,0 +1,289 @@
#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
{
boost::optional<pthread_t> id;
friend class boost::thread;
friend thread_id this_thread::get_id();
thread_id(pthread_t id_):
id(id_)
{}
public:
thread_id()
{}
bool operator==(const thread_id& y) const
{
return (id && y.id) && (pthread_equal(*id,*y.id)!=0);
}
bool operator!=(const thread_id& y) const
{
return !(*this==y);
}
template<class charT, class traits>
friend std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const thread_id& x)
{
if(x.id)
{
return os<<*x.id;
}
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(boost::move_t<F> f_):
f(f_)
{}
void run()
{
f();
}
};
mutable boost::mutex thread_info_mutex;
boost::shared_ptr<detail::thread_data_base> thread_info;
void start_thread();
explicit thread(boost::shared_ptr<detail::thread_data_base> data);
boost::shared_ptr<detail::thread_data_base> 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(boost::move_t<F> f):
thread_info(new thread_data<F>(f))
{
start_thread();
}
explicit thread(boost::move_t<thread> x);
thread& operator=(boost::move_t<thread> x);
operator boost::move_t<thread>();
boost::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;
};
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 inline thread::id get_id()
{
return thread::id(pthread_self());
}
BOOST_THREAD_DECL void interruption_point();
BOOST_THREAD_DECL bool interruption_enabled();
BOOST_THREAD_DECL bool interruption_requested();
BOOST_THREAD_DECL inline void yield()
{
thread::yield();
}
template<typename TimeDuration>
BOOST_THREAD_DECL 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();
int size() const;
private:
std::list<thread*> m_threads;
mutex m_mutex;
};
} // namespace boost
#endif

View File

@@ -0,0 +1,93 @@
#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/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 thread_data_base
{
boost::shared_ptr<thread_data_base> 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;
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),
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

View File

@@ -0,0 +1,28 @@
#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

View File

@@ -1,283 +0,0 @@
// Copyright (C) 2002-2003
// David Moore, William E. Kempf, Michael Glassford
//
// 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/detail/workaround.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/detail/lock.hpp>
#include <boost/thread/detail/read_write_lock.hpp>
#include <boost/thread/condition.hpp>
namespace boost {
namespace read_write_scheduling_policy {
enum read_write_scheduling_policy_enum
{
writer_priority, //Prefer writers; can starve readers
reader_priority, //Prefer readers; can starve writers
alternating_many_reads, //Alternate readers and writers; before a writer, release all queued readers
alternating_single_read //Alternate readers and writers; before a writer, release only one queued reader
};
} // namespace read_write_scheduling_policy
namespace detail {
namespace thread {
// Shared implementation construct for explicit Scheduling Policies
// This implementation is susceptible to self-deadlock, though....
template<typename Mutex>
struct read_write_mutex_impl
{
typedef Mutex mutex_type;
typedef detail::thread::scoped_lock<Mutex> scoped_lock;
typedef detail::thread::scoped_try_lock<Mutex> scoped_try_lock;
typedef detail::thread::scoped_timed_lock<Mutex> scoped_timed_lock;
read_write_mutex_impl(read_write_scheduling_policy::read_write_scheduling_policy_enum sp);
#if !BOOST_WORKAROUND(__BORLANDC__,<= 0x564)
~read_write_mutex_impl();
#endif
Mutex m_prot;
const read_write_scheduling_policy::read_write_scheduling_policy_enum m_sp;
int m_state; //-1 = write lock; 0 = unlocked; >0 = read locked
boost::condition m_waiting_writers;
boost::condition m_waiting_readers;
boost::condition m_waiting_promotion;
int m_num_waiting_writers;
int m_num_waiting_readers;
bool m_state_waiting_promotion;
int m_num_waking_writers;
int m_num_waking_readers;
int m_num_max_waking_writers; //Debug only
int m_num_max_waking_readers; //Debug only
bool m_readers_next;
void do_read_lock();
void do_write_lock();
void do_write_unlock();
void do_read_unlock();
bool do_try_write_lock();
bool do_try_read_lock();
bool do_timed_write_lock(const xtime &xt);
bool do_timed_read_lock(const xtime &xt);
void do_demote_to_read_lock();
bool do_try_demote_to_read_lock();
bool do_timed_demote_to_read_lock(const xtime &xt);
void do_promote_to_write_lock();
bool do_try_promote_to_write_lock();
bool do_timed_promote_to_write_lock(const xtime &xt);
bool locked();
read_write_lock_state::read_write_lock_state_enum state();
private:
bool do_demote_to_read_lock_impl();
enum scheduling_reason
{
scheduling_reason_unlock,
scheduling_reason_timeout,
scheduling_reason_demote
};
void do_scheduling_impl(const scheduling_reason reason);
bool do_wake_one_reader(void);
bool do_wake_all_readers(void);
bool do_wake_writer(void);
bool waker_exists(void);
};
} // namespace detail
} // namespace thread
class BOOST_THREAD_DECL read_write_mutex : private noncopyable
{
public:
read_write_mutex(read_write_scheduling_policy::read_write_scheduling_policy_enum sp);
~read_write_mutex();
read_write_scheduling_policy::read_write_scheduling_policy_enum policy() const { return m_impl.m_sp; }
friend class detail::thread::read_write_lock_ops<read_write_mutex>;
typedef detail::thread::scoped_read_write_lock<
read_write_mutex> scoped_read_write_lock;
typedef detail::thread::scoped_read_lock<
read_write_mutex> scoped_read_lock;
typedef detail::thread::scoped_write_lock<
read_write_mutex> scoped_write_lock;
private:
// Operations that will eventually be done only
// via lock types
void do_write_lock();
void do_read_lock();
void do_write_unlock();
void do_read_unlock();
void do_demote_to_read_lock();
void do_promote_to_write_lock();
bool locked();
read_write_lock_state::read_write_lock_state_enum state();
detail::thread::read_write_mutex_impl<mutex> m_impl;
};
class BOOST_THREAD_DECL try_read_write_mutex : private noncopyable
{
public:
try_read_write_mutex(read_write_scheduling_policy::read_write_scheduling_policy_enum sp);
~try_read_write_mutex();
read_write_scheduling_policy::read_write_scheduling_policy_enum policy() const { return m_impl.m_sp; }
friend class detail::thread::read_write_lock_ops<try_read_write_mutex>;
typedef detail::thread::scoped_read_write_lock<
try_read_write_mutex> scoped_read_write_lock;
typedef detail::thread::scoped_try_read_write_lock<
try_read_write_mutex> scoped_try_read_write_lock;
typedef detail::thread::scoped_read_lock<
try_read_write_mutex> scoped_read_lock;
typedef detail::thread::scoped_try_read_lock<
try_read_write_mutex> scoped_try_read_lock;
typedef detail::thread::scoped_write_lock<
try_read_write_mutex> scoped_write_lock;
typedef detail::thread::scoped_try_write_lock<
try_read_write_mutex> scoped_try_write_lock;
private:
// Operations that will eventually be done only
// via lock types
void do_write_lock();
void do_read_lock();
void do_write_unlock();
void do_read_unlock();
bool do_try_write_lock();
bool do_try_read_lock();
void do_demote_to_read_lock();
bool do_try_demote_to_read_lock();
void do_promote_to_write_lock();
bool do_try_promote_to_write_lock();
bool locked();
read_write_lock_state::read_write_lock_state_enum state();
detail::thread::read_write_mutex_impl<try_mutex> m_impl;
};
class BOOST_THREAD_DECL timed_read_write_mutex : private noncopyable
{
public:
timed_read_write_mutex(read_write_scheduling_policy::read_write_scheduling_policy_enum sp);
~timed_read_write_mutex();
read_write_scheduling_policy::read_write_scheduling_policy_enum policy() const { return m_impl.m_sp; }
friend class detail::thread::read_write_lock_ops<timed_read_write_mutex>;
typedef detail::thread::scoped_read_write_lock<
timed_read_write_mutex> scoped_read_write_lock;
typedef detail::thread::scoped_try_read_write_lock<
timed_read_write_mutex> scoped_try_read_write_lock;
typedef detail::thread::scoped_timed_read_write_lock<
timed_read_write_mutex> scoped_timed_read_write_lock;
typedef detail::thread::scoped_read_lock<
timed_read_write_mutex> scoped_read_lock;
typedef detail::thread::scoped_try_read_lock<
timed_read_write_mutex> scoped_try_read_lock;
typedef detail::thread::scoped_timed_read_lock<
timed_read_write_mutex> scoped_timed_read_lock;
typedef detail::thread::scoped_write_lock<
timed_read_write_mutex> scoped_write_lock;
typedef detail::thread::scoped_try_write_lock<
timed_read_write_mutex> scoped_try_write_lock;
typedef detail::thread::scoped_timed_write_lock<
timed_read_write_mutex> scoped_timed_write_lock;
private:
// Operations that will eventually be done only
// via lock types
void do_write_lock();
void do_read_lock();
void do_write_unlock();
void do_read_unlock();
bool do_try_write_lock();
bool do_try_read_lock();
bool do_timed_write_lock(const xtime &xt);
bool do_timed_read_lock(const xtime &xt);
void do_demote_to_read_lock();
bool do_try_demote_to_read_lock();
bool do_timed_demote_to_read_lock(const xtime &xt);
void do_promote_to_write_lock();
bool do_try_promote_to_write_lock();
bool do_timed_promote_to_write_lock(const xtime &xt);
bool locked();
read_write_lock_state::read_write_lock_state_enum state();
detail::thread::read_write_mutex_impl<timed_mutex> m_impl;
};
} // 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.

View File

@@ -1,182 +1,15 @@
// Copyright (C) 2001-2003
// William E. Kempf
#ifndef BOOST_THREAD_RECURSIVE_MUTEX_HPP
#define BOOST_THREAD_RECURSIVE_MUTEX_HPP
// recursive_mutex.hpp
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// (C) Copyright 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)
#ifndef BOOST_RECURSIVE_MUTEX_WEK070601_HPP
#define BOOST_RECURSIVE_MUTEX_WEK070601_HPP
#include <boost/thread/detail/platform.hpp>
#include BOOST_THREAD_PLATFORM(recursive_mutex.hpp)
#include <boost/thread/detail/config.hpp>
#include <boost/utility.hpp>
#include <boost/thread/detail/lock.hpp>
#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:
friend class detail::thread::lock_ops<recursive_mutex>;
typedef detail::thread::scoped_lock<recursive_mutex> scoped_lock;
recursive_mutex();
~recursive_mutex();
private:
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
typedef std::size_t cv_state;
#elif defined(BOOST_HAS_PTHREADS)
struct cv_state
{
long count;
pthread_mutex_t* pmutex;
};
#endif
void do_lock();
void do_unlock();
void do_lock(cv_state& state);
void do_unlock(cv_state& state);
#if defined(BOOST_HAS_WINTHREADS)
void* m_mutex;
bool m_critical_section;
unsigned long m_count;
#elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex;
unsigned m_count;
# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
pthread_cond_t m_unlocked;
pthread_t m_thread_id;
bool m_valid_id;
# endif
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
std::size_t m_count;
#endif
};
class BOOST_THREAD_DECL recursive_try_mutex
: private noncopyable
{
public:
friend class detail::thread::lock_ops<recursive_try_mutex>;
typedef detail::thread::scoped_lock<recursive_try_mutex> scoped_lock;
typedef detail::thread::scoped_try_lock<
recursive_try_mutex> scoped_try_lock;
recursive_try_mutex();
~recursive_try_mutex();
private:
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
typedef std::size_t cv_state;
#elif defined(BOOST_HAS_PTHREADS)
struct cv_state
{
long count;
pthread_mutex_t* pmutex;
};
#endif
void do_lock();
bool do_trylock();
void do_unlock();
void do_lock(cv_state& state);
void do_unlock(cv_state& state);
#if defined(BOOST_HAS_WINTHREADS)
void* m_mutex;
bool m_critical_section;
unsigned long m_count;
#elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex;
unsigned m_count;
# if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
pthread_cond_t m_unlocked;
pthread_t m_thread_id;
bool m_valid_id;
# endif
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
std::size_t m_count;
#endif
};
class BOOST_THREAD_DECL recursive_timed_mutex
: private noncopyable
{
public:
friend class detail::thread::lock_ops<recursive_timed_mutex>;
typedef detail::thread::scoped_lock<recursive_timed_mutex> scoped_lock;
typedef detail::thread::scoped_try_lock<
recursive_timed_mutex> scoped_try_lock;
typedef detail::thread::scoped_timed_lock<
recursive_timed_mutex> scoped_timed_lock;
recursive_timed_mutex();
~recursive_timed_mutex();
private:
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
typedef std::size_t cv_state;
#elif defined(BOOST_HAS_PTHREADS)
struct cv_state
{
long count;
pthread_mutex_t* pmutex;
};
#endif
void do_lock();
bool do_trylock();
bool do_timedlock(const xtime& xt);
void do_unlock();
void do_lock(cv_state& state);
void do_unlock(cv_state& state);
#if defined(BOOST_HAS_WINTHREADS)
void* m_mutex;
unsigned long m_count;
#elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex;
pthread_cond_t m_unlocked;
pthread_t m_thread_id;
bool m_valid_id;
unsigned m_count;
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
std::size_t m_count;
#endif
};
} // 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.

View File

@@ -0,0 +1,15 @@
#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>
#include BOOST_THREAD_PLATFORM(shared_mutex.hpp)
#endif

View File

@@ -1,87 +1,15 @@
// Copyright (C) 2001-2003
// William E. Kempf
#ifndef BOOST_THREAD_THREAD_HPP
#define BOOST_THREAD_THREAD_HPP
// thread.hpp
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// (C) Copyright 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)
#ifndef BOOST_THREAD_WEK070601_HPP
#define BOOST_THREAD_WEK070601_HPP
#include <boost/thread/detail/platform.hpp>
#include BOOST_THREAD_PLATFORM(thread.hpp)
#include <boost/thread/detail/config.hpp>
#include <boost/utility.hpp>
#include <boost/function.hpp>
#include <boost/thread/mutex.hpp>
#include <list>
#include <memory>
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
# include <boost/thread/condition.hpp>
#elif defined(BOOST_HAS_MPTASKS)
# include <Multiprocessing.h>
#endif
namespace boost {
struct xtime;
class BOOST_THREAD_DECL thread : private noncopyable
{
public:
thread();
explicit thread(const function0<void>& threadfunc);
~thread();
bool operator==(const thread& other) const;
bool operator!=(const thread& other) const;
void join();
static void sleep(const xtime& xt);
static void yield();
private:
#if defined(BOOST_HAS_WINTHREADS)
void* m_thread;
unsigned int m_id;
#elif defined(BOOST_HAS_PTHREADS)
private:
pthread_t m_thread;
#elif defined(BOOST_HAS_MPTASKS)
MPQueueID m_pJoinQueueID;
MPTaskID m_pTaskID;
#endif
bool m_joinable;
};
class BOOST_THREAD_DECL thread_group : private noncopyable
{
public:
thread_group();
~thread_group();
thread* create_thread(const function0<void>& threadfunc);
void add_thread(thread* thrd);
void remove_thread(thread* thrd);
void join_all();
int size();
private:
std::list<thread*> m_threads;
mutex m_mutex;
};
} // namespace boost
// Change Log:
// 8 Feb 01 WEKEMPF Initial version.
// 1 Jun 01 WEKEMPF Added boost::thread initial implementation.
// 3 Jul 01 WEKEMPF Redesigned boost::thread to be noncopyable.
#endif // BOOST_THREAD_WEK070601_HPP

View File

@@ -0,0 +1,46 @@
#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

View File

@@ -1,13 +1,8 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright (C) 2001-2003 William E. Kempf
// Copyright (C) 2006 Roland Schwarz
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_TSS_WEK070601_HPP
#define BOOST_TSS_WEK070601_HPP
@@ -26,6 +21,13 @@
namespace boost {
// disable warnings about non dll import
// see: http://www.boost.org/more/separate_compilation.html#dlls
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4251 4231 4660 4275)
#endif
namespace detail {
class BOOST_THREAD_DECL tss : private noncopyable
@@ -44,6 +46,7 @@ public:
}
}
~tss();
void* get() const;
void set(void* value);
void cleanup(void* p);
@@ -103,6 +106,10 @@ private:
detail::tss m_tss;
};
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
} // namespace boost
#endif //BOOST_TSS_WEK070601_HPP

View File

@@ -0,0 +1,120 @@
#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);
}
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

View File

@@ -0,0 +1,157 @@
#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;
}
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

View File

@@ -0,0 +1,304 @@
#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"
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();
}
}
};
protected:
template<typename lock_type>
bool do_wait(lock_type& lock,::boost::system_time const& wait_until)
{
detail::win32::handle_manager local_wake_sem;
detail::win32::handle_manager sem;
bool first_loop=true;
bool woken=false;
relocker<lock_type> locker(lock);
while(!woken)
{
{
boost::mutex::scoped_lock internal_lock(internal_mutex);
detail::interlocked_write_release(&total_count,total_count+1);
if(first_loop)
{
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;
}
first_loop=false;
}
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);
}
if(!this_thread::interruptible_wait(sem,::boost::detail::get_milliseconds_until(wait_until)))
{
break;
}
unsigned long const woken_result=detail::win32::WaitForSingleObject(local_wake_sem,0);
BOOST_ASSERT(woken_result==detail::win32::timeout || woken_result==0);
woken=(woken_result==0);
}
return woken;
}
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,::boost::detail::get_system_time_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);
}
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 false;
}
return true;
}
};
class condition_variable_any:
public detail::basic_condition_variable
{
public:
template<typename lock_type>
void wait(lock_type& m)
{
do_wait(m,::boost::detail::get_system_time_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,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 false;
}
return true;
}
};
}
#endif

View File

@@ -0,0 +1,77 @@
#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

View File

@@ -0,0 +1,61 @@
#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

View File

@@ -0,0 +1,130 @@
#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(NULL, 0, mutex_name);
#else
return win32::CreateMutexA(NULL, 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

View File

@@ -0,0 +1,61 @@
#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

View File

@@ -0,0 +1,509 @@
#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;
void* semaphores[2];
void* &unlock_sem;
void* &exclusive_sem;
void* upgrade_sem;
void release_waiters(state_data old_state)
{
if(old_state.exclusive_waiting)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(exclusive_sem,1,NULL)!=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),NULL)!=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,NULL)!=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

View File

@@ -0,0 +1,442 @@
#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 <list>
#include <algorithm>
#include <boost/ref.hpp>
namespace boost
{
class thread_interrupted
{};
namespace detail
{
struct thread_exit_callback_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;
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),
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);
}
}
virtual void run()=0;
};
}
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(boost::move_t<F> f_):
f(f_)
{}
void run()
{
f();
}
};
mutable boost::mutex thread_info_mutex;
boost::intrusive_ptr<detail::thread_data_base> thread_info;
static unsigned __stdcall thread_start_function(void* param);
void start_thread();
explicit thread(boost::intrusive_ptr<detail::thread_data_base> data);
boost::intrusive_ptr<detail::thread_data_base> 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>
explicit thread(boost::move_t<F> f):
thread_info(detail::heap_new<thread_data<F> >(f))
{
start_thread();
}
thread(boost::move_t<thread> x);
thread& operator=(boost::move_t<thread> x);
operator boost::move_t<thread>();
boost::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
class interruption_handle;
interruption_handle get_interruption_handle() const;
void interrupt();
bool interruption_requested() const;
static thread self();
};
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,unsigned long milliseconds);
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();
thread::interruption_handle BOOST_THREAD_DECL get_interruption_handle();
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:
unsigned thread_id;
id(unsigned thread_id_):
thread_id(thread_id_)
{}
friend class thread;
friend id this_thread::get_id();
public:
id():
thread_id(0)
{}
bool operator==(const id& y) const
{
return thread_id==y.thread_id;
}
bool operator!=(const id& y) const
{
return thread_id!=y.thread_id;
}
bool operator<(const id& y) const
{
return thread_id<y.thread_id;
}
bool operator>(const id& y) const
{
return thread_id>y.thread_id;
}
bool operator<=(const id& y) const
{
return thread_id<=y.thread_id;
}
bool operator>=(const id& y) const
{
return thread_id>=y.thread_id;
}
template<class charT, class traits>
friend std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const id& x)
{
return os<<x.thread_id;
}
};
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();
}
class thread::interruption_handle
{
private:
boost::detail::win32::handle_manager handle;
friend class thread;
friend interruption_handle this_thread::get_interruption_handle();
interruption_handle(detail::win32::handle h_):
handle(h_)
{}
public:
interruption_handle(interruption_handle const& other):
handle(other.handle.duplicate())
{}
interruption_handle():
handle(0)
{}
void swap(interruption_handle& other)
{
handle.swap(other.handle);
}
interruption_handle& operator=(interruption_handle const& other)
{
interruption_handle temp(other);
swap(temp);
return *this;
}
void reset()
{
handle=0;
}
void interrupt()
{
if(handle)
{
detail::win32::SetEvent(handle);
}
}
typedef void(interruption_handle::*bool_type)();
operator bool_type() const
{
return handle?&interruption_handle::interrupt:0;
}
};
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();
}
}
int size() const
{
boost::lock_guard<mutex> guard(m);
return threads.size();
}
private:
std::list<thread*> threads;
mutable mutex m;
};
}
#endif

View File

@@ -0,0 +1,109 @@
// 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"
#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
{
template<typename T>
T* heap_new()
{
void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,sizeof(T));
T* const data=new (heap_memory) T();
return data;
}
template<typename T,typename A1>
T* heap_new(A1 a1)
{
void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,sizeof(T));
T* const data=new (heap_memory) T(a1);
return data;
}
template<typename T,typename A1,typename A2>
T* heap_new(A1 a1,A2 a2)
{
void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,sizeof(T));
T* const data=new (heap_memory) T(a1,a2);
return data;
}
template<typename T>
void heap_delete(T* data)
{
data->~T();
detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,data);
}
template<typename T>
struct do_delete
{
T* data;
do_delete(T* data_):
data(data_)
{}
void operator()() const
{
detail::heap_delete(data);
}
};
template<typename T>
do_delete<T> make_heap_deleter(T* data)
{
return do_delete<T>(data);
}
}
}
#endif

View File

@@ -0,0 +1,278 @@
#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;
}
}
}
#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);
# 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(NULL,initial_count,max_count,NULL);
#else
handle const res=CreateSemaphoreW(NULL,initial_count,max_count,NULL);
#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

View File

@@ -1,13 +1,9 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright (C) 2007 Anthony Williams
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_XTIME_WEK070601_HPP
#define BOOST_XTIME_WEK070601_HPP
@@ -15,6 +11,8 @@
#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 {
@@ -42,9 +40,40 @@ struct xtime
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 BOOST_THREAD_DECL xtime_get(struct xtime* xtp, int clock_type);
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;
}
inline int xtime_cmp(const xtime& xt1, const xtime& xt2)
{

View File

@@ -1,3 +1,8 @@
<!-- Copyright (c) 2002-2003 William E. Kempf.
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<html>
<head>
<meta http-equiv="refresh" content="0; URL=doc/index.html">

View File

@@ -1,47 +0,0 @@
// Copyright (C) 2002-2003
// David Moore, William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#include <boost/thread/detail/config.hpp>
#include <boost/thread/barrier.hpp>
#include <string> // see http://article.gmane.org/gmane.comp.lib.boost.devel/106981
namespace boost {
barrier::barrier(unsigned int count)
: m_threshold(count), m_count(count), m_generation(0)
{
if (count == 0)
throw std::invalid_argument("count cannot be zero.");
}
barrier::~barrier()
{
}
bool barrier::wait()
{
boost::mutex::scoped_lock lock(m_mutex);
unsigned int gen = m_generation;
if (--m_count == 0)
{
m_generation++;
m_count = m_threshold;
m_cond.notify_all();
return true;
}
while (gen == m_generation)
m_cond.wait(lock);
return false;
}
} // namespace boost

View File

@@ -1,677 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#include <boost/thread/detail/config.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/limits.hpp>
#include <cassert>
#include "timeconv.inl"
#if defined(BOOST_HAS_WINTHREADS)
# ifndef NOMINMAX
# define NOMINMAX
# endif
# include <windows.h>
#elif defined(BOOST_HAS_PTHREADS)
# include <errno.h>
#elif defined(BOOST_HAS_MPTASKS)
# include <MacErrors.h>
# include "mac/init.hpp"
# include "mac/safe.hpp"
#endif
namespace boost {
namespace detail {
#if defined(BOOST_HAS_WINTHREADS)
condition_impl::condition_impl()
: m_gone(0), m_blocked(0), m_waiting(0)
{
m_gate = reinterpret_cast<void*>(CreateSemaphore(0, 1, 1, 0));
m_queue = reinterpret_cast<void*>(
CreateSemaphore(0, 0, (std::numeric_limits<long>::max)(), 0));
m_mutex = reinterpret_cast<void*>(CreateMutex(0, 0, 0));
if (!m_gate || !m_queue || !m_mutex)
{
int res = 0;
if (m_gate)
{
res = CloseHandle(reinterpret_cast<HANDLE>(m_gate));
assert(res);
}
if (m_queue)
{
res = CloseHandle(reinterpret_cast<HANDLE>(m_queue));
assert(res);
}
if (m_mutex)
{
res = CloseHandle(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
}
throw thread_resource_error();
}
}
condition_impl::~condition_impl()
{
int res = 0;
res = CloseHandle(reinterpret_cast<HANDLE>(m_gate));
assert(res);
res = CloseHandle(reinterpret_cast<HANDLE>(m_queue));
assert(res);
res = CloseHandle(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
}
void condition_impl::notify_one()
{
unsigned signals = 0;
int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
assert(res == WAIT_OBJECT_0);
if (m_waiting != 0) // the m_gate is already closed
{
if (m_blocked == 0)
{
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
return;
}
++m_waiting;
--m_blocked;
signals = 1;
}
else
{
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
assert(res == WAIT_OBJECT_0);
if (m_blocked > m_gone)
{
if (m_gone != 0)
{
m_blocked -= m_gone;
m_gone = 0;
}
signals = m_waiting = 1;
--m_blocked;
}
else
{
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
assert(res);
}
}
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
if (signals)
{
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0);
assert(res);
}
}
void condition_impl::notify_all()
{
unsigned signals = 0;
int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
assert(res == WAIT_OBJECT_0);
if (m_waiting != 0) // the m_gate is already closed
{
if (m_blocked == 0)
{
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
return;
}
m_waiting += (signals = m_blocked);
m_blocked = 0;
}
else
{
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
assert(res == WAIT_OBJECT_0);
if (m_blocked > m_gone)
{
if (m_gone != 0)
{
m_blocked -= m_gone;
m_gone = 0;
}
signals = m_waiting = m_blocked;
m_blocked = 0;
}
else
{
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
assert(res);
}
}
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
if (signals)
{
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0);
assert(res);
}
}
void condition_impl::enter_wait()
{
int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
assert(res == WAIT_OBJECT_0);
++m_blocked;
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
assert(res);
}
void condition_impl::do_wait()
{
int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), INFINITE);
assert(res == WAIT_OBJECT_0);
unsigned was_waiting=0;
unsigned was_gone=0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
assert(res == WAIT_OBJECT_0);
was_waiting = m_waiting;
was_gone = m_gone;
if (was_waiting != 0)
{
if (--m_waiting == 0)
{
if (m_blocked != 0)
{
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1,
0); // open m_gate
assert(res);
was_waiting = 0;
}
else if (m_gone != 0)
m_gone = 0;
}
}
else if (++m_gone == ((std::numeric_limits<unsigned>::max)() / 2))
{
// timeout occured, normalize the m_gone count
// this may occur if many calls to wait with a timeout are made and
// no call to notify_* is made
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
assert(res == WAIT_OBJECT_0);
m_blocked -= m_gone;
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
assert(res);
m_gone = 0;
}
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
if (was_waiting == 1)
{
for (/**/ ; was_gone; --was_gone)
{
// better now than spurious later
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue),
INFINITE);
assert(res == WAIT_OBJECT_0);
}
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
assert(res);
}
}
bool condition_impl::do_timed_wait(const xtime& xt)
{
bool ret = false;
unsigned int res = 0;
for (;;)
{
int milliseconds;
to_duration(xt, milliseconds);
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue),
milliseconds);
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
ret = (res == WAIT_OBJECT_0);
if (res == WAIT_TIMEOUT)
{
xtime cur;
xtime_get(&cur, TIME_UTC);
if (xtime_cmp(xt, cur) > 0)
continue;
}
break;
}
unsigned was_waiting=0;
unsigned was_gone=0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
assert(res == WAIT_OBJECT_0);
was_waiting = m_waiting;
was_gone = m_gone;
if (was_waiting != 0)
{
if (!ret) // timeout
{
if (m_blocked != 0)
--m_blocked;
else
++m_gone; // count spurious wakeups
}
if (--m_waiting == 0)
{
if (m_blocked != 0)
{
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1,
0); // open m_gate
assert(res);
was_waiting = 0;
}
else if (m_gone != 0)
m_gone = 0;
}
}
else if (++m_gone == ((std::numeric_limits<unsigned>::max)() / 2))
{
// timeout occured, normalize the m_gone count
// this may occur if many calls to wait with a timeout are made and
// no call to notify_* is made
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
assert(res == WAIT_OBJECT_0);
m_blocked -= m_gone;
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
assert(res);
m_gone = 0;
}
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
if (was_waiting == 1)
{
for (/**/ ; was_gone; --was_gone)
{
// better now than spurious later
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue),
INFINITE);
assert(res == WAIT_OBJECT_0);
}
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
assert(res);
}
return ret;
}
#elif defined(BOOST_HAS_PTHREADS)
condition_impl::condition_impl()
{
int res = 0;
res = pthread_cond_init(&m_condition, 0);
if (res != 0)
throw thread_resource_error();
}
condition_impl::~condition_impl()
{
int res = 0;
res = pthread_cond_destroy(&m_condition);
assert(res == 0);
}
void condition_impl::notify_one()
{
int res = 0;
res = pthread_cond_signal(&m_condition);
assert(res == 0);
}
void condition_impl::notify_all()
{
int res = 0;
res = pthread_cond_broadcast(&m_condition);
assert(res == 0);
}
void condition_impl::do_wait(pthread_mutex_t* pmutex)
{
int res = 0;
res = pthread_cond_wait(&m_condition, pmutex);
assert(res == 0);
}
bool condition_impl::do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex)
{
timespec ts;
to_timespec(xt, ts);
int res = 0;
res = pthread_cond_timedwait(&m_condition, pmutex, &ts);
assert(res == 0 || res == ETIMEDOUT);
return res != ETIMEDOUT;
}
#elif defined(BOOST_HAS_MPTASKS)
using threads::mac::detail::safe_enter_critical_region;
using threads::mac::detail::safe_wait_on_semaphore;
condition_impl::condition_impl()
: m_gone(0), m_blocked(0), m_waiting(0)
{
threads::mac::detail::thread_init();
OSStatus lStatus = noErr;
lStatus = MPCreateSemaphore(1, 1, &m_gate);
if(lStatus == noErr)
lStatus = MPCreateSemaphore(ULONG_MAX, 0, &m_queue);
if(lStatus != noErr || !m_gate || !m_queue)
{
if (m_gate)
{
lStatus = MPDeleteSemaphore(m_gate);
assert(lStatus == noErr);
}
if (m_queue)
{
lStatus = MPDeleteSemaphore(m_queue);
assert(lStatus == noErr);
}
throw thread_resource_error();
}
}
condition_impl::~condition_impl()
{
OSStatus lStatus = noErr;
lStatus = MPDeleteSemaphore(m_gate);
assert(lStatus == noErr);
lStatus = MPDeleteSemaphore(m_queue);
assert(lStatus == noErr);
}
void condition_impl::notify_one()
{
unsigned signals = 0;
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
m_mutex_mutex);
assert(lStatus == noErr);
if (m_waiting != 0) // the m_gate is already closed
{
if (m_blocked == 0)
{
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
return;
}
++m_waiting;
--m_blocked;
}
else
{
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
assert(lStatus == noErr);
if (m_blocked > m_gone)
{
if (m_gone != 0)
{
m_blocked -= m_gone;
m_gone = 0;
}
signals = m_waiting = 1;
--m_blocked;
}
else
{
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
}
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
while (signals)
{
lStatus = MPSignalSemaphore(m_queue);
assert(lStatus == noErr);
--signals;
}
}
}
void condition_impl::notify_all()
{
unsigned signals = 0;
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
m_mutex_mutex);
assert(lStatus == noErr);
if (m_waiting != 0) // the m_gate is already closed
{
if (m_blocked == 0)
{
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
return;
}
m_waiting += (signals = m_blocked);
m_blocked = 0;
}
else
{
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
assert(lStatus == noErr);
if (m_blocked > m_gone)
{
if (m_gone != 0)
{
m_blocked -= m_gone;
m_gone = 0;
}
signals = m_waiting = m_blocked;
m_blocked = 0;
}
else
{
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
}
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
while (signals)
{
lStatus = MPSignalSemaphore(m_queue);
assert(lStatus == noErr);
--signals;
}
}
}
void condition_impl::enter_wait()
{
OSStatus lStatus = noErr;
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
assert(lStatus == noErr);
++m_blocked;
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
}
void condition_impl::do_wait()
{
OSStatus lStatus = noErr;
lStatus = safe_wait_on_semaphore(m_queue, kDurationForever);
assert(lStatus == noErr);
unsigned was_waiting=0;
unsigned was_gone=0;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
m_mutex_mutex);
assert(lStatus == noErr);
was_waiting = m_waiting;
was_gone = m_gone;
if (was_waiting != 0)
{
if (--m_waiting == 0)
{
if (m_blocked != 0)
{
lStatus = MPSignalSemaphore(m_gate); // open m_gate
assert(lStatus == noErr);
was_waiting = 0;
}
else if (m_gone != 0)
m_gone = 0;
}
}
else if (++m_gone == ((std::numeric_limits<unsigned>::max)() / 2))
{
// timeout occured, normalize the m_gone count
// this may occur if many calls to wait with a timeout are made and
// no call to notify_* is made
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
assert(lStatus == noErr);
m_blocked -= m_gone;
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
m_gone = 0;
}
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
if (was_waiting == 1)
{
for (/**/ ; was_gone; --was_gone)
{
// better now than spurious later
lStatus = safe_wait_on_semaphore(m_queue, kDurationForever);
assert(lStatus == noErr);
}
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
}
}
bool condition_impl::do_timed_wait(const xtime& xt)
{
int milliseconds;
to_duration(xt, milliseconds);
OSStatus lStatus = noErr;
lStatus = safe_wait_on_semaphore(m_queue, milliseconds);
assert(lStatus == noErr || lStatus == kMPTimeoutErr);
bool ret = (lStatus == noErr);
unsigned was_waiting=0;
unsigned was_gone=0;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
m_mutex_mutex);
assert(lStatus == noErr);
was_waiting = m_waiting;
was_gone = m_gone;
if (was_waiting != 0)
{
if (!ret) // timeout
{
if (m_blocked != 0)
--m_blocked;
else
++m_gone; // count spurious wakeups
}
if (--m_waiting == 0)
{
if (m_blocked != 0)
{
lStatus = MPSignalSemaphore(m_gate); // open m_gate
assert(lStatus == noErr);
was_waiting = 0;
}
else if (m_gone != 0)
m_gone = 0;
}
}
else if (++m_gone == ((std::numeric_limits<unsigned>::max)() / 2))
{
// timeout occured, normalize the m_gone count
// this may occur if many calls to wait with a timeout are made and
// no call to notify_* is made
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
assert(lStatus == noErr);
m_blocked -= m_gone;
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
m_gone = 0;
}
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
if (was_waiting == 1)
{
for (/**/ ; was_gone; --was_gone)
{
// better now than spurious later
lStatus = safe_wait_on_semaphore(m_queue, kDurationForever);
assert(lStatus == noErr);
}
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
}
return ret;
}
#endif
} // namespace detail
} // namespace boost
// Change Log:
// 8 Feb 01 WEKEMPF Initial version.
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
// 3 Jan 03 WEKEMPF Modified for DLL implementation.

View File

@@ -1,8 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#define TARGET_CARBON 1

View File

@@ -1,66 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#include "delivery_man.hpp"
#include "os.hpp"
#include "execution_context.hpp"
namespace boost {
namespace threads {
namespace mac {
namespace detail {
delivery_man::delivery_man():
m_pPackage(NULL),
m_pSemaphore(kInvalidID),
m_bPackageWaiting(false)
{
assert(at_st());
OSStatus lStatus = MPCreateSemaphore(1UL, 0UL, &m_pSemaphore);
// TODO - throw on error here
assert(lStatus == noErr);
}
delivery_man::~delivery_man()
{
assert(m_bPackageWaiting == false);
OSStatus lStatus = MPDeleteSemaphore(m_pSemaphore);
assert(lStatus == noErr);
}
void delivery_man::accept_deliveries()
{
if(m_bPackageWaiting)
{
assert(m_pPackage != NULL);
m_pPackage->accept();
m_pPackage = NULL;
m_bPackageWaiting = false;
// signal to the thread making the call that we're done
OSStatus lStatus = MPSignalSemaphore(m_pSemaphore);
assert(lStatus == noErr);
}
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost

View File

@@ -1,84 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#ifndef BOOST_DELIVERY_MAN_MJM012402_HPP
#define BOOST_DELIVERY_MAN_MJM012402_HPP
#include <boost/function.hpp>
#include <boost/utility.hpp>
#include <boost/thread/mutex.hpp>
#include "package.hpp"
#include <Multiprocessing.h>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
// class delivery_man is intended to move boost::function objects from MP tasks to
// other execution contexts (such as deferred task time or system task time).
class delivery_man: private noncopyable
{
public:
delivery_man();
~delivery_man();
public:
template<class R>
R deliver(function<R> &rFunctor);
void accept_deliveries();
private:
base_package *m_pPackage;
mutex m_oMutex;
MPSemaphoreID m_pSemaphore;
bool m_bPackageWaiting;
};
template<class R>
R delivery_man::deliver(function<R> &rFunctor)
{
assert(at_mp());
// lock our mutex
mutex::scoped_lock oLock(m_oMutex);
// create a package and save it
package<R> oPackage(rFunctor);
m_pPackage = &oPackage;
m_bPackageWaiting = true;
// wait on the semaphore
OSStatus lStatus = MPWaitOnSemaphore(m_pSemaphore, kDurationForever);
assert(lStatus == noErr);
return(oPackage.return_value());
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_DELIVERY_MAN_MJM012402_HPP

View File

@@ -1,93 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#include "dt_scheduler.hpp"
#include "ot_context.hpp"
#include <boost/thread/detail/singleton.hpp>
#include <OpenTransportProtocol.h>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
const OTTimeout k_ulTimerTaskDelay = 1UL;
dt_scheduler::dt_scheduler():
m_bReschedule(false),
m_uppTask(NULL),
m_lTask(0UL)
{
using ::boost::detail::thread::singleton;
ot_context &rContext(singleton<ot_context>::instance());
m_uppTask = NewOTProcessUPP(task_entry);
m_lTask = OTCreateTimerTaskInContext(m_uppTask, this, rContext.get_context());
}
dt_scheduler::~dt_scheduler()
{
OTDestroyTimerTask(m_lTask);
m_lTask = 0UL;
DisposeOTProcessUPP(m_uppTask);
m_uppTask = NULL;
}
void dt_scheduler::start_polling()
{
m_bReschedule = true;
schedule_task();
}
void dt_scheduler::stop_polling()
{
m_bReschedule = false;
}
void dt_scheduler::schedule_task()
{
if(m_bReschedule)
{
OTScheduleTimerTask(m_lTask, k_ulTimerTaskDelay);
}
}
/*static*/ pascal void dt_scheduler::task_entry(void *pRefCon)
{
dt_scheduler *pThis = reinterpret_cast<dt_scheduler *>(pRefCon);
assert(pThis != NULL);
pThis->task();
}
void dt_scheduler::task()
{
periodic_function();
schedule_task();
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost

View File

@@ -1,63 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#ifndef BOOST_DT_SCHEDULER_MJM012402_HPP
#define BOOST_DT_SCHEDULER_MJM012402_HPP
#include "periodical.hpp"
#include <OpenTransport.h>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
// class dt_scheduler calls its pure-virtual periodic_function method periodically at
// deferred task time. This is generally 1kHz under Mac OS 9.
class dt_scheduler
{
public:
dt_scheduler();
virtual ~dt_scheduler();
protected:
void start_polling();
void stop_polling();
private:
virtual void periodic_function() = 0;
private:
void schedule_task();
static pascal void task_entry(void *pRefCon);
void task();
private:
bool m_bReschedule;
OTProcessUPP m_uppTask;
long m_lTask;
};
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_DT_SCHEDULER_MJM012402_HPP

View File

@@ -1,60 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#include <Debugging.h>
#include <Multiprocessing.h>
#include "execution_context.hpp"
#include "init.hpp"
namespace boost {
namespace threads {
namespace mac {
execution_context_t execution_context()
{
// make sure that MP services are available the first time through
static bool bIgnored = detail::thread_init();
// first check if we're an MP task
if(MPTaskIsPreemptive(kInvalidID))
{
return(k_eExecutionContextMPTask);
}
#if TARGET_CARBON
// Carbon has TaskLevel
UInt32 ulLevel = TaskLevel();
if(ulLevel == 0UL)
{
return(k_eExecutionContextSystemTask);
}
if(ulLevel & kInDeferredTaskMask)
{
return(k_eExecutionContextDeferredTask);
}
return(k_eExecutionContextOther);
#else
// this can be implemented using TaskLevel if you don't mind linking against
// DebugLib (and therefore breaking Mac OS 8.6 support), or CurrentExecutionLevel.
# error execution_context unimplimented
#endif
}
} // namespace mac
} // namespace threads
} // namespace boost

View File

@@ -1,47 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#ifndef BOOST_EXECUTION_CONTEXT_MJM012402_HPP
#define BOOST_EXECUTION_CONTEXT_MJM012402_HPP
namespace boost {
namespace threads {
namespace mac {
// utility functions for figuring out what context your code is executing in.
// Bear in mind that at_mp and in_blue are the only functions guarenteed by
// Apple to work. There is simply no way of being sure that you will not get
// false readings about task level at interrupt time in blue.
typedef enum {
k_eExecutionContextSystemTask,
k_eExecutionContextDeferredTask,
k_eExecutionContextMPTask,
k_eExecutionContextOther
} execution_context_t;
execution_context_t execution_context();
inline bool at_st()
{ return(execution_context() == k_eExecutionContextSystemTask); }
inline bool at_mp()
{ return(execution_context() == k_eExecutionContextMPTask); }
inline bool in_blue()
{ return(!at_mp()); }
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_EXECUTION_CONTEXT_MJM012402_HPP

View File

@@ -1,58 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#include "init.hpp"
#include "remote_call_manager.hpp"
#include <boost/thread/detail/singleton.hpp>
#include <Multiprocessing.h>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
namespace {
// force these to get called by the end of static initialization time.
static bool g_bInitialized = (thread_init() && create_singletons());
}
bool thread_init()
{
static bool bResult = MPLibraryIsLoaded();
return(bResult);
}
bool create_singletons()
{
using ::boost::detail::thread::singleton;
singleton<remote_call_manager>::instance();
return(true);
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost

View File

@@ -1,34 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#ifndef BOOST_INIT_MJM012402_HPP
#define BOOST_INIT_MJM012402_HPP
namespace boost {
namespace threads {
namespace mac {
namespace detail {
bool thread_init();
bool create_singletons();
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_INIT_MJM012402_HPP

View File

@@ -1,24 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#include <cassert>
#include <cstdio>
#include <MacTypes.h>
#include "remote_calls.hpp"
// this function will be called when an assertion fails. We redirect the assertion
// to DebugStr (MacsBug under Mac OS 1.x-9.x, Console under Mac OS X).
void __assertion_failed(char const *pszAssertion, char const *pszFile, int nLine)
{
using std::snprintf;
unsigned char strlDebug[sizeof(Str255) + 1];
char *pszDebug = reinterpret_cast<char *>(&strlDebug[1]);
strlDebug[0] = snprintf(pszDebug, sizeof(Str255), "assertion failed: \"%s\", %s, line %d", pszAssertion, pszFile, nLine);
boost::threads::mac::dt_remote_call(DebugStr, static_cast<ConstStringPtr>(strlDebug));
}

View File

@@ -1,128 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
//
// includes
//
#include <abort_exit.h>
#include <console.h>
#include <console_io.h>
#include <misc_io.h>
#include <SIOUX.h>
#include "remote_calls.hpp"
//
// using declarations
//
using std::__file_handle;
using std::__idle_proc;
using std::__io_error;
using std::__no_io_error;
using std::size_t;
using boost::threads::mac::st_remote_call;
//
// prototypes
//
static bool check_console();
static int do_read_console(__file_handle ulHandle, unsigned char *pBuffer, size_t *pCount, __idle_proc pfnIdleProc);
static int do_write_console(__file_handle ulHandle, unsigned char *pBuffer, size_t *pCount, __idle_proc pfnIdleProc);
//
// MSL function replacements
//
// these two functions are called by cin and cout, respectively, as well as by (all?)
// other functions in MSL that do console I/O. All that they do is as the remote
// call manager to ensure that their guts are called at system task time.
int __read_console(__file_handle handle, unsigned char * buffer, size_t * count, __idle_proc idle_proc)
{
return(st_remote_call(do_read_console, handle, buffer, count, idle_proc));
}
int __write_console(__file_handle handle, unsigned char * buffer, size_t * count, __idle_proc idle_proc)
{
return(st_remote_call(do_write_console, handle, buffer, count, idle_proc));
}
//
// implementations
//
static bool check_console()
{
static bool s_bHaveConsole(false);
static bool s_bWontHaveConsole(false);
if(s_bHaveConsole)
{
return(true);
}
if(s_bWontHaveConsole == false)
{
__stdio_atexit();
if(InstallConsole(0) != 0)
{
s_bWontHaveConsole = true;
return(false);
}
__console_exit = RemoveConsole;
s_bHaveConsole = true;
return(true);
}
return(false);
}
int do_read_console(__file_handle /*ulHandle*/, unsigned char *pBuffer, size_t *pCount, __idle_proc /*pfnIdleProc*/)
{
assert(pCount != NULL);
assert(pBuffer != NULL || *pCount == 0UL);
if(check_console() == false)
{
return(__io_error);
}
std::fflush(stdout);
long lCount = ReadCharsFromConsole(reinterpret_cast<char *>(pBuffer), static_cast<long>(*pCount));
*pCount = static_cast<size_t>(lCount);
if(lCount == -1L)
{
return(__io_error);
}
return(__no_io_error);
}
int do_write_console(__file_handle /*ulHandle*/, unsigned char *pBuffer, size_t *pCount, __idle_proc /*pfnIdleProc*/)
{
if(check_console() == false)
{
return(__io_error);
}
long lCount = WriteCharsToConsole(reinterpret_cast<char *>(pBuffer), static_cast<long>(*pCount));
*pCount = static_cast<size_t>(lCount);
if(lCount == -1L)
{
return(__io_error);
}
return(__no_io_error);
}

Some files were not shown because too many files have changed in this diff Show More