2
0
mirror of https://github.com/boostorg/thread.git synced 2026-02-08 11:12:23 +00:00

Compare commits

..

6 Commits

Author SHA1 Message Date
nobody
52a53be89b This commit was manufactured by cvs2svn to create tag
'Version_1_32_0'.

[SVN r26264]
2004-11-19 19:19:18 +00:00
Aleksey Gurtovoy
701a8fc4b5 fix invalid <p> tags
[SVN r26236]
2004-11-18 23:55:33 +00:00
Aleksey Gurtovoy
606fabcbd6 fix line endings
[SVN r26003]
2004-10-31 09:38:17 +00:00
Aleksey Gurtovoy
6d41e62c1c fix BoostBook/broken links/invalid filenames/etc.
[SVN r25933]
2004-10-29 10:23:48 +00:00
Aleksey Gurtovoy
643b8e7b79 fix BoostBook/broken links/invalid filenames/etc.
[SVN r25931]
2004-10-29 09:40:12 +00:00
nobody
76c5ae79b5 This commit was manufactured by cvs2svn to create branch 'RC_1_32_0'.
[SVN r25797]
2004-10-20 08:26:43 +00:00
135 changed files with 9938 additions and 7586 deletions

View File

@@ -1,122 +1,126 @@
# 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)
# Copyright (C) 2001-2003
# William E. Kempf
#
# This work is a reimplementation along the design and ideas
# of 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 ;
# pthreads is compiled on all platforms when available
if [ threads::is-pthread-available ] {
template pthread_base
: ## sources ##
[ threads::cpp_source ../src/pthread :
thread
mutex
recursive_mutex
condition
exceptions
xtime
once
tss
]
: ## requirements ##
threads::lib-pthread
<sysinclude>$(BOOST_ROOT)
<threading>multi
<define>BOOST_THREAD_POSIX
common-variant-tag
<borland><*><cxxflags>-w-8004
<borland><*><cxxflags>-w-8057
;
{
CPP_SOURCES =
barrier
condition
exceptions
mutex
once
recursive_mutex
read_write_mutex
thread
tss_hooks
tss_dll
tss_pe
tss
xtime
;
lib boost_thread_pthread
: <template>pthread_base
: ## requirements ##
<define>BOOST_THREAD_BUILD_LIB=1
;
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
<runtime-link>static
# the common names rule ensures that the library will
# be named according to the rules used by the install
# and auto-link features:
common-variant-tag
: ## default build ##
;
dll boost_thread_pthread
: <template>pthread_base
: ## requirements ##
<runtime-link>dynamic
<define>BOOST_THREAD_BUILD_DLL=1
;
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 ##
;
stage bin-stage
: <dll>boost_thread_pthread
<lib>boost_thread_pthread
;
lib $(boost_thread_lib_name)
: ## sources ##
<template>boost_thread_lib_base
: ## requirements ##
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name)
: ## default build ##
;
install thread_pthread lib
: <dll>boost_thread_pthread
<lib>boost_thread_pthread
;
dll $(boost_thread_lib_name)
: ## sources ##
<template>boost_thread_dll_base
: ## requirements ##
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name)
: ## default build ##
;
# the next is true on platforms where pthreads is native threading lib
if [ threads::is-native-on-build-os pthread ] {
lib boost_thread
: <template>pthread_base
: ## requirements ##
<define>BOOST_THREAD_BUILD_LIB=1
;
stage bin-stage
: <dll>$(boost_thread_lib_name)
<lib>$(boost_thread_lib_name)
;
dll boost_thread
: <template>pthread_base
: ## requirements ##
<runtime-link>dynamic
<define>BOOST_THREAD_BUILD_DLL=1
;
}
install thread lib
: <dll>$(boost_thread_lib_name)
<lib>$(boost_thread_lib_name)
;
if $(boost_thread_lib_settings_ptw32)
{
lib $(boost_thread_lib_name_ptw32)
: ## sources ##
<template>boost_thread_lib_base
: ## requirements ##
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name_ptw32)
$(pthreads-win32)
;
dll $(boost_thread_lib_name_ptw32)
: ## sources ##
<template>boost_thread_dll_base
: ## requirements ##
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name_ptw32)
$(pthreads-win32)
;
stage bin-stage
: <dll>$(boost_thread_lib_name_ptw32)
<lib>$(boost_thread_lib_name_ptw32)
;
install thread lib
: <dll>$(boost_thread_lib_name_ptw32)
<lib>$(boost_thread_lib_name_ptw32)
;
}
}
if [ threads::is-native-on-build-os win32 ] {
template win32_base
: ## sources ##
[ threads::cpp_source ../src/win32 :
thread
exceptions
xtime
tss
tss_hooks
tss_dll
tss_pe
]
: ## requirements ##
<sysinclude>$(BOOST_ROOT)
<threading>multi
common-variant-tag
<borland><*><cxxflags>-w-8004
<borland><*><cxxflags>-w-8057
;
lib boost_thread
: <template>win32_base
: ## requirements ##
<define>BOOST_THREAD_BUILD_LIB=1
;
dll boost_thread
: <template>win32_base
: ## requirements ##
<runtime-link>dynamic
<define>BOOST_THREAD_BUILD_DLL=1
;
}
stage bin-stage
: <dll>boost_thread
<lib>boost_thread
;
install thread lib
: <dll>boost_thread
<lib>boost_thread
;

View File

@@ -1,61 +1,26 @@
# Copyright 2006 Roland Schwarz.
# Distributed under the Boost Software License, Version 1.0. (See
# accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
# This work is a reimplementation along the design and ideas
# of William E. Kempf.
import os ;
import thread ;
if [ os.name ] = NT
{
reqts = <link>shared:<define>BOOST_THREAD_BUILD_DLL=1 ;
}
else
{
# Declare the uses system library
lib pthread : : <name>pthread ;
usage = <library>pthread ;
}
project boost/thread
: source-location ../src
: requirements <threading>multi
<link>static:<define>BOOST_THREAD_BUILD_LIB=1
<link>shared:<define>BOOST_THREAD_BUILD_DLL=1
: default-build <threading>multi [ thread.default-api ]
: source-location ../src
: usage-requirements $(usage)
: requirements $(reqts) <threading>multi
: default-build <threading>multi
;
# build the pthread based variant
lib boost_thread_pthread
: ## sources ##
pthread/thread.cpp
pthread/mutex.cpp
pthread/recursive_mutex.cpp
pthread/condition.cpp
pthread/exceptions.cpp
pthread/xtime.cpp
pthread/tss.cpp
: ## requirements ##
<define>BOOST_THREAD_POSIX
<thrd-api>pthread
;
CPP_SOURCES = condition mutex recursive_mutex thread xtime once
exceptions barrier tss tss_hooks tss_dll tss_pe ;
# use pthread on platforms where pthread is considered native
lib boost_thread
: ## sources ##
pthread/thread.cpp
pthread/mutex.cpp
pthread/recursive_mutex.cpp
pthread/condition.cpp
pthread/exceptions.cpp
pthread/xtime.cpp
pthread/tss.cpp
: ## requirements ##
<define>BOOST_THREAD_POSIX
<thrd-api>pthread
;
# the win32 native variant
lib boost_thread
: ## sources ##
win32/thread.cpp
win32/exceptions.cpp
win32/xtime.cpp
win32/tss.cpp
win32/tss_hooks.cpp
win32/tss_dll.cpp
win32/tss_pe.cpp
: ## requirements ##
<thrd-api>win32
;
: $(CPP_SOURCES).cpp
;

View File

@@ -1,70 +0,0 @@
# Copyright 2006 Roland Schwarz.
# Distributed under the Boost Software License, Version 1.0. (See
# accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
# This work is a reimplementation along the design and ideas
# of William E. Kempf.
import modules ;
import os ;
import feature ;
import property ;
# supported threading api's
feature.feature thrd-api : pthread win32 : symmetric ;
# save a reference to the original lib rule
IMPORT : lib : $(__name__) : type.lib ;
# local override of the global lib rule
rule lib ( name : sources * : requirements * : default-build * : usage-requirements * )
{
if <thrd-api>pthread in $(requirements)
{
if [ os.name ] = "NT"
{
local PTW32_INCLUDE = [ modules.peek : PTW32_INCLUDE ] ;
local PTW32_LIB = [ modules.peek : PTW32_LIB ] ;
if $(PTW32_INCLUDE) && $(PTW32_LIB)
{
requirements =
[ property.refine $(requirements) :
<define>BOOST_HAS_PTHREADS
<include>$(PTW32_INCLUDE)
<library>$(PTW32_LIB)
] ;
}
else
{
requirements += <build>no ;
# it would be nice if this message appears only once ...
# but I cannot figure out how to detectd the second phase.
echo "******************************************************" ;
echo "Building Boost.Thread without pthread support" ;
echo "If you need pthread you should specify the paths." ;
echo "For example:" ;
echo "PTW32_INCLUDE=C:\\Program Files\\ptw32\\Pre-built2\\include" ;
echo "PTW32_LIB=C:\\Program Files\\ptw32\\Pre-built2\\lib\\pthreadVC2.lib" ;
echo "******************************************************" ;
}
}
}
return [ type.lib $(name) : $(sources) : $(requirements) : $(default-build) : $(usage-requirements) ] ;
}
# auto export of rule lib to calling module only
IMPORT $(__name__) : lib : [ CALLER_MODULE 1 ] : lib ;
rule default-api
{
if [ os.name ] = "NT"
{
return <thrd-api>win32 ;
}
else
{
return <thrd-api>pthread ;
}
}

View File

@@ -1,65 +1,70 @@
# Copyright 2006 Roland Schwarz.
# Distributed under the Boost Software License, Version 1.0. (See
# accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
# Copyright (C) 2001-2003
# William E. Kempf
#
# This work is a reimplementation along the design and ideas
# of 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.
# find out if pthread is available on current build platform
rule threads::is-pthread-available
{
if $(OS) = "NT" {
if $(PTW32_INCLUDE) && $(PTW32_LIB) {
return true ;
}
else {
ECHO "******************************************************" ;
ECHO "Building Boost.Thread without pthread support" ;
ECHO "If you need pthread you should specify the paths." ;
ECHO "For example:" ;
ECHO "PTW32_INCLUDE=C:\\Program Files\\ptw32\\Pre-built2\\include" ;
ECHO "PTW32_LIB=C:\\Program Files\\ptw32\\Pre-built2\\lib\\pthreadVC2.lib" ;
ECHO "******************************************************" ;
}
}
else if $(OS) = "LINUX" {
return true ;
}
else { ## assume pthread is available on unknown os for now
return true ;
}
}
# 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).
# find the native library variant for current build os
rule threads::is-native-on-build-os ( libvariant )
# Do some OS-specific setup
{
if $(OS) = "NT" {
if $(libvariant) = win32 { return true ; }
}
else if $(OS) = "LINUX" {
if $(libvariant) = pthread { return true ; }
}
else { ## assume pthread is native on others for now
if $(libvariant) = pthread { return true ; }
}
}
# utility to prepend the source path to the cpp sources
rule threads::cpp_source ( path : sources * )
{
return $(path)/$(sources).cpp ;
}
# impose the pthread library and include path on the requirements
rule threads::lib-pthread ( toolset variant : subvariant-path properties * )
{
if $(OS) = "NT" && $(PTW32_INCLUDE) && $(PTW32_LIB) {
properties = [ impose-requirements $(properties) :
<define>BOOST_HAS_PTHREADS
<include>$(PTW32_INCLUDE)
<library-file>$(PTW32_LIB) ] ;
#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)
;
}
}
return $(subvariant-path) $(properties) ;
}
template thread_base
: ## sources ##
: ## requirements ##
<sysinclude>$(BOOST_ROOT)
<threading>multi
<borland><*><cxxflags>-w-8004
<borland><*><cxxflags>-w-8057
: ## default build ##
;
}

BIN
build/threads.mcp Normal file

Binary file not shown.

View File

@@ -54,7 +54,7 @@ last-revision="$Date$">
<title>ACM Computing Surveys</title>
<volumenum>Vol. 5</volumenum>
<issuenum>No. 4</issuenum>
<date>December, 1973</date>
<date>December, 1983</date>
</biblioset>
<biblioset relation="article">
<author>0-201-63392-2

View File

@@ -32,7 +32,7 @@ xmlns:xi="http://www.w3.org/2001/XInclude">
<librarycategory name="category:concurrent" />
<title>Boost.Threads</title>
</libraryinfo>
<title>Boost.Threads</title>
<title>&Boost.Threads;</title>
<xi:include href="overview.xml"/>
<xi:include href="design.xml"/>
<xi:include href="concepts.xml"/>

View File

@@ -1,52 +1,54 @@
# Copyright (C) 2006 Roland Schwarz.
# Distributed under the Boost Software License, Version 1.0. (See
# accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
# Copyright (C) 2001-2003
# William E. Kempf
#
# This work is a reimplementation along the design and ideas
# of 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"
# The threading library is available in two versions.
# Native to the environment or based ontop pthread.
# To select which version to use you need to define
# BOOST_THREAD_POSIX when compiling your sources.
# If BOOST_THREAD_POSIX is defined this will choose
# pthread implementation.
# You also need to specify the correct library version by
# specifying the the <lib> or <dll> tags.
# <lib>@boost/libs/thread/build/boost_thread for static native and
# <lib>@boost/libs/thread/build/boost_thread_pthread static pthread.
# If your compiler does not have the pthread lib in a standard
# include path, you need to specify that too, with <include> and
# <library-file>.
# Declare the location of this subproject relative to the root.
subproject libs/thread/example ;
project-root ;
# 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 ##
<lib>@boost/libs/thread/build/boost_thread
#<lib>@boost/libs/thread/build/boost_thread_pthread
#<dll>@boost/libs/thread/build/boost_thread
#<dll>@boost/libs/thread/build/boost_thread_pthread
: ## requirements ##
<include>$(BOOST_ROOT)
# uncomment below to get pthread on windows
#<define>BOOST_THREAD_POSIX
#<include>$(PTW32_INCLUDE)
#<library-file>$(PTW32_LIB)
: ## default build ##
<threading>multi
;
{
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 ;
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,53 +0,0 @@
# Copyright 2003 William E. Kempf
# Copyright 2006 Roland Schwarz
# Distributed under the Boost Software License, Version 1.0. (See
# accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
# This work is a reimplementation along the design and ideas
# of William E. Kempf.
project example ;
# If you move this example from its place in the Boost tree, edit this
# path to point at the root directory of your Boost installation (the
# one containing a subdirectory called "boost/".
path-global BOOST_ROOT : ../../.. ;
# Makes a project id for boost so that other Boost.Build projects can
# refer to it by name.
#
project boost : $(BOOST_ROOT) ;
# Attn: path-global was broken in my version of bbv1, which prevented specifying
# BOOST_ROOT as a relative path. So I needed to apply
# the below fix in allyourbase.jam as shown below:
#
#rule project ( name : location ? )
#{
# if ! $(location)
# {
# gPROJECT($(name)) = $(gPROJECT($(PROJECT))) ;
# PROJECT($(gPROJECT($(name)))) = $(name) ;
# PROJECT = $(name) ;
# }
# else
# {
# gPROJECT($(name)) = [ root-paths $(location) : [ root-paths $($(gTOP)) : [ PWD ] ] ] ;
# # speedsnail
# # Root the path globals to fix a bug which prevented to use them from an external
# # project. The fix is as as uninvasive as possible, as it will only trigger when
# # an external project is declared. So it will not interfere with the build of the
# # boost library. I took this route, as at the time of this fix, the bbv1 is expected
# # to be retired soon.
# # N.B.: The path-globals rule is expected to be invoked from Jamrules files only.
# local val ;
# for val in $(gPATH_GLOBALS) {
# gPATH_GLOBAL_VALUE($(val)) = [ root-paths $(gPATH_GLOBAL_VALUE($(val))) :
# [ root-paths $($(gTOP)) : [ PWD ] ]
# ] ;
# }
# local [ protect-subproject ] ;
# enter-subproject @$(name) ;
# }
#}

View File

@@ -1,22 +0,0 @@
# Copyright 2006 Roland Schwarz.
# Distributed under the Boost Software License, Version 1.0. (See
# accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
# This work is a reimplementation along the design and ideas
# of William E. Kempf.
#
# Edit this path to point at the tools/build/v1 subdirectory of your
# Boost installation.
if --v2 in $(ARGV)
{
JAMFILE = [Bb]uild.jam [Jj]amfile.v2 ;
boost-build ../../../tools/build/v2 ;
}
else
{
boost-build ../../../tools/build/v1 ;
}

View File

@@ -1,8 +1,13 @@
// Copyright (C) 2001-2003 William E. Kempf
// Distributed under the Boost Software License, Version 1.0 (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
// 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 <iostream>
#include <vector>
@@ -38,8 +43,7 @@ public:
}
private:
int begin, end;
std::vector<int>::size_type buffered;
int begin, end, buffered;
std::vector<int> circular_buf;
boost::condition buffer_not_full, buffer_not_empty;
boost::mutex monitor;

View File

@@ -1,8 +1,13 @@
// Copyright (C) 2001-2003 William E. Kempf
// Distributed under the Boost Software License, Version 1.0 (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
// 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 <vector>
#include <iostream>

View File

@@ -1,8 +1,13 @@
// Copyright (C) 2001-2003 William E. Kempf
// Distributed under the Boost Software License, Version 1.0 (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
// 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/mutex.hpp>
#include <boost/thread/thread.hpp>

View File

@@ -1,8 +1,13 @@
// Copyright (C) 2001-2003 William E. Kempf
// Distributed under the Boost Software License, Version 1.0 (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
// 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/thread.hpp>
#include <boost/thread/once.hpp>

View File

@@ -1,8 +1,13 @@
// Copyright (C) 2001-2003 William E. Kempf
// Distributed under the Boost Software License, Version 1.0 (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
// 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/recursive_mutex.hpp>
#include <boost/thread/thread.hpp>

View File

@@ -1,8 +1,13 @@
// Copyright (C) 2001-2003 William E. Kempf
// Distributed under the Boost Software License, Version 1.0 (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
// 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/mutex.hpp>
#include <boost/thread/condition.hpp>

View File

@@ -1,8 +1,13 @@
// Copyright (C) 2001-2003 William E. Kempf
// Distributed under the Boost Software License, Version 1.0 (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
// 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/mutex.hpp>
#include <boost/thread/condition.hpp>

View File

@@ -1,9 +1,13 @@
// Copyright (C) 2001-2003 William E. Kempf
// Distributed under the Boost Software License, Version 1.0 (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
// 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/thread.hpp>
#include <iostream>

View File

@@ -1,8 +1,13 @@
// Copyright (C) 2001-2003 William E. Kempf
// Distributed under the Boost Software License, Version 1.0 (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
// 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/thread.hpp>
#include <boost/thread/tss.hpp>

View File

@@ -1,8 +1,13 @@
// Copyright (C) 2001-2003 William E. Kempf
// Distributed under the Boost Software License, Version 1.0 (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
// 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/thread.hpp>
#include <boost/thread/xtime.hpp>

View File

@@ -1,64 +1,40 @@
#ifndef BOOST_THREAD_BARRIER_HPP
#define BOOST_THREAD_BARRIER_HPP
// barrier.hpp
// Copyright (C) 2002-2003
// David Moore, William E. Kempf
//
// (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)
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#ifndef BOOST_BARRIER_JDM030602_HPP
#define BOOST_BARRIER_JDM030602_HPP
#include <boost/thread/detail/config.hpp>
#include <cstddef>
#include <stdexcept>
#include <boost/thread/detail/platform.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std
{
using ::size_t;
}
#endif
namespace boost {
namespace boost
class BOOST_THREAD_DECL barrier
{
class barrier
{
boost::mutex m;
boost::condition cond;
const std::size_t max_count;
std::size_t current_count;
public:
barrier(std::size_t count):
max_count(count),current_count(0)
{
if(!max_count)
{
throw std::invalid_argument("You must specify a non-zero count");
}
}
bool wait()
{
boost::mutex::scoped_lock lock(m);
if(++current_count==max_count)
{
current_count=0;
cond.notify_all();
return true;
}
else
{
cond.wait(lock);
return false;
}
}
};
}
public:
barrier(unsigned int count);
~barrier();
bool wait();
private:
mutex m_mutex;
condition m_cond;
unsigned int m_threshold;
unsigned int m_count;
unsigned int m_generation;
};
} // namespace boost
#endif

View File

@@ -1,16 +1,198 @@
// 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)
// Copyright (C) 2001-2003
// William E. Kempf
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#ifndef BOOST_THREAD_RS06040706_HPP
#define BOOST_THREAD_RS06040706_HPP
#ifndef BOOST_CONDITION_WEK070601_HPP
#define BOOST_CONDITION_WEK070601_HPP
#include <boost/thread/detail/platform.hpp>
#include BOOST_THREAD_PLATFORM(condition.hpp)
#include <boost/thread/detail/config.hpp>
#endif // BOOST_THREAD_RS06040706_HPP
#include <boost/thread/exceptions.hpp>
#include <boost/utility.hpp>
#include <boost/thread/detail/lock.hpp>
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
#elif defined(BOOST_HAS_MPTASKS)
# include "scoped_critical_region.hpp"
#endif
namespace boost {
struct xtime;
namespace detail {
class BOOST_THREAD_DECL condition_impl : private noncopyable
{
friend class condition;
public:
condition_impl();
~condition_impl();
void notify_one();
void notify_all();
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
void enter_wait();
void do_wait();
bool do_timed_wait(const xtime& xt);
#elif defined(BOOST_HAS_PTHREADS)
void do_wait(pthread_mutex_t* pmutex);
bool do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex);
#endif
#if defined(BOOST_HAS_WINTHREADS)
void* m_gate;
void* m_queue;
void* m_mutex;
unsigned m_gone; // # threads that timed out and never made it to m_queue
unsigned long m_blocked; // # threads blocked on the condition
unsigned m_waiting; // # threads no longer waiting for the condition but
// still waiting to be removed from m_queue
#elif defined(BOOST_HAS_PTHREADS)
pthread_cond_t m_condition;
#elif defined(BOOST_HAS_MPTASKS)
MPSemaphoreID m_gate;
MPSemaphoreID m_queue;
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
unsigned m_gone; // # threads that timed out and never made it to m_queue
unsigned long m_blocked; // # threads blocked on the condition
unsigned m_waiting; // # threads no longer waiting for the condition but
// still waiting to be removed from m_queue
#endif
};
} // namespace detail
class condition : private noncopyable
{
public:
condition() { }
~condition() { }
void notify_one() { m_impl.notify_one(); }
void notify_all() { m_impl.notify_all(); }
template <typename L>
void wait(L& lock)
{
if (!lock)
throw lock_error();
do_wait(lock.m_mutex);
}
template <typename L, typename Pr>
void wait(L& lock, Pr pred)
{
if (!lock)
throw lock_error();
while (!pred())
do_wait(lock.m_mutex);
}
template <typename L>
bool timed_wait(L& lock, const xtime& xt)
{
if (!lock)
throw lock_error();
return do_timed_wait(lock.m_mutex, xt);
}
template <typename L, typename Pr>
bool timed_wait(L& lock, const xtime& xt, Pr pred)
{
if (!lock)
throw lock_error();
while (!pred())
{
if (!do_timed_wait(lock.m_mutex, xt))
return false;
}
return true;
}
private:
detail::condition_impl m_impl;
template <typename M>
void do_wait(M& mutex)
{
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
m_impl.enter_wait();
#endif
typedef detail::thread::lock_ops<M>
#if defined(__HP_aCC) && __HP_aCC <= 33900 && !defined(BOOST_STRICT_CONFIG)
# define lock_ops lock_ops_ // HP confuses lock_ops witht the template
#endif
lock_ops;
typename lock_ops::lock_state state;
lock_ops::unlock(mutex, state);
#if defined(BOOST_HAS_PTHREADS)
m_impl.do_wait(state.pmutex);
#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
m_impl.do_wait();
#endif
lock_ops::lock(mutex, state);
#undef lock_ops
}
template <typename M>
bool do_timed_wait(M& mutex, const xtime& xt)
{
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
m_impl.enter_wait();
#endif
typedef detail::thread::lock_ops<M>
#if defined(__HP_aCC) && __HP_aCC <= 33900 && !defined(BOOST_STRICT_CONFIG)
# define lock_ops lock_ops_ // HP confuses lock_ops witht the template
#endif
lock_ops;
typename lock_ops::lock_state state;
lock_ops::unlock(mutex, state);
bool ret = false;
#if defined(BOOST_HAS_PTHREADS)
ret = m_impl.do_timed_wait(xt, state.pmutex);
#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
ret = m_impl.do_timed_wait(xt);
#endif
lock_ops::lock(mutex, state);
#undef lock_ops
return ret;
}
};
} // namespace boost
// Change Log:
// 8 Feb 01 WEKEMPF Initial version.
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
// 23 May 01 WEKEMPF Removed "duration" timed_waits, as they are too
// difficult to use with spurious wakeups.
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
#endif // BOOST_CONDITION_WEK070601_HPP

View File

@@ -0,0 +1,84 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#ifndef BOOST_THREAD_CONFIG_WEK01032003_HPP
#define BOOST_THREAD_CONFIG_WEK01032003_HPP
#include <boost/config.hpp>
// insist on threading support being available:
#include <boost/config/requires_threads.hpp>
#if defined(BOOST_HAS_WINTHREADS)
# if defined(BOOST_THREAD_BUILD_DLL) //Build dll
# define BOOST_THREAD_DECL __declspec(dllexport)
# elif defined(BOOST_THREAD_BUILD_LIB) //Build lib
# define BOOST_THREAD_DECL
# elif defined(BOOST_THREAD_USE_DLL) //Use dll
# define BOOST_THREAD_DECL __declspec(dllimport)
# define BOOST_DYN_LINK
# elif defined(BOOST_THREAD_USE_LIB) //Use lib
# define BOOST_THREAD_DECL
# else //Use default
# if defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)
//For VC++, choose according to threading library setting
# if defined(_DLL)
//Threading library is dll: use Boost.Threads dll
# define BOOST_THREAD_USE_DLL
# define BOOST_THREAD_DECL __declspec(dllimport)
# define BOOST_DYN_LINK
# else
//Threading library is lib: used Boost.Threads lib
# define BOOST_THREAD_USE_LIB
# define BOOST_THREAD_DECL
# endif
# else
//For compilers not yet supporting auto-tss cleanup
//with Boost.Threads lib, use Boost.Threads dll
# define BOOST_THREAD_USE_DLL
# define BOOST_THREAD_DECL __declspec(dllimport)
# define BOOST_DYN_LINK
# endif
# endif
#else
# define BOOST_THREAD_DECL
# if defined(BOOST_THREAD_USE_LIB) //Use dll
# define BOOST_THREAD_USE_DLL
# define BOOST_DYN_LINK
# elif defined(BOOST_THREAD_USE_DLL) //Use lib
# define BOOST_THREAD_USE_LIB
# else //Use default
# define BOOST_THREAD_USE_LIB
# endif
#endif // BOOST_HAS_WINTHREADS
//
// Automatically link to the correct build variant where possible.
//
#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_THREAD_NO_LIB) && !defined(BOOST_THREAD_BUILD_DLL) && !defined(BOOST_THREAD_BUILD_LIB)
//
// Set the name of our library, this will get undef'ed by auto_link.hpp
// once it's done with it:
//
#if defined(BOOST_THREAD_LIB_NAME)
# define BOOST_LIB_NAME BOOST_THREAD_LIB_NAME
#else
# define BOOST_LIB_NAME boost_thread
#endif
//
// If we're importing code from a dll, then tell auto_link.hpp about it:
//
// And include the header that does the work:
//
#include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
#endif // BOOST_THREAD_CONFIG_WEK1032003_HPP

View File

@@ -0,0 +1,39 @@
// Copyright (C) 2001-2003
// Mac Murrett
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_FORCE_CAST_MJM012402_HPP
#define BOOST_FORCE_CAST_MJM012402_HPP
#include <boost/thread/detail/config.hpp>
namespace boost {
namespace detail {
namespace thread {
// force_cast will convert anything to anything.
// general case
template<class Return_Type, class Argument_Type>
inline Return_Type &force_cast(Argument_Type &rSrc)
{
return(*reinterpret_cast<Return_Type *>(&rSrc));
}
// specialization for const
template<class Return_Type, class Argument_Type>
inline const Return_Type &force_cast(const Argument_Type &rSrc)
{
return(*reinterpret_cast<const Return_Type *>(&rSrc));
}
} // namespace thread
} // namespace detail
} // namespace boost
#endif // BOOST_FORCE_CAST_MJM012402_HPP

View File

@@ -1,18 +1,21 @@
// 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)
// Copyright (C) 2001-2003
// William E. Kempf
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#ifndef BOOST_THREAD_RS06040708_HPP
#define BOOST_THREAD_RS06040708_HPP
#ifndef BOOST_XLOCK_WEK070601_HPP
#define BOOST_XLOCK_WEK070601_HPP
#include <boost/thread/pthread/config.hpp>
#include <boost/thread/detail/config.hpp>
#include <boost/utility.hpp>
#include <boost/thread/pthread/exceptions.hpp>
#include <boost/thread/exceptions.hpp>
namespace boost {
@@ -202,4 +205,10 @@ private:
} // namespace detail
} // namespace boost
#endif // BOOST_THREAD_RS06040708_HPP
#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

@@ -1,72 +0,0 @@
// 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

@@ -0,0 +1,59 @@
// Copyright (C) 2001-2003
// Mac Murrett
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_SINGLETON_MJM012402_HPP
#define BOOST_SINGLETON_MJM012402_HPP
#include <boost/thread/detail/config.hpp>
namespace boost {
namespace detail {
namespace thread {
// class singleton has the same goal as all singletons: create one instance of
// a class on demand, then dish it out as requested.
template <class T>
class singleton : private T
{
private:
singleton();
~singleton();
public:
static T &instance();
};
template <class T>
inline singleton<T>::singleton()
{
/* no-op */
}
template <class T>
inline singleton<T>::~singleton()
{
/* no-op */
}
template <class T>
/*static*/ T &singleton<T>::instance()
{
// function-local static to force this to work correctly at static
// initialization time.
static singleton<T> s_oT;
return(s_oT);
}
} // namespace thread
} // namespace detail
} // namespace boost
#endif // BOOST_SINGLETON_MJM012402_HPP

View File

@@ -1,16 +1,14 @@
// Copyright (C) 2001-2003 William E. Kempf
// Copyright (C) Michael Glassford 2004.
// Copyright (C) 2006 Roland Schwarz
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
// (C) Copyright Michael Glassford 2004.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_TLS_HOOKS_RS06092306_HPP
#define BOOST_TLS_HOOKS_RS06092306_HPP
#if !defined(BOOST_TLS_HOOKS_HPP)
#define BOOST_TLS_HOOKS_HPP
#include <boost/thread/win32/config.hpp>
#include <boost/thread/detail/config.hpp>
#if defined(BOOST_HAS_WINTHREADS)
typedef void (__cdecl *thread_exit_handler)(void);
@@ -22,12 +20,16 @@
//Currently only implemented for Win32, but should
//later be implemented for all platforms.
//Used by Win32 implementation of Boost.Threads
//tss to perform cleanup.
//tss to peform cleanup.
//Like the C runtime library atexit() function,
//which it mimics, at_thread_exit() returns
//zero if successful and a nonzero
//value if an error occurs.
#endif //defined(BOOST_HAS_WINTHREADS)
#if defined(BOOST_HAS_WINTHREADS)
extern "C" BOOST_THREAD_DECL void on_process_enter(void);
//Function to be called when the exe or dll
//that uses Boost.Threads first starts
@@ -71,4 +73,6 @@
//cleanup has been implemented and to force
//it to be linked into the Boost.Threads library.
#endif //BOOST_TLS_HOOKS_RS06092306_HPP
#endif //defined(BOOST_HAS_WINTHREADS)
#endif //!defined(BOOST_TLS_HOOKS_HPP)

View File

@@ -1,16 +1,101 @@
// 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)
// Copyright (C) 2001-2003
// William E. Kempf
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#ifndef BOOST_THREAD_RS06040710_HPP
#define BOOST_THREAD_RS06040710_HPP
#ifndef BOOST_THREAD_EXCEPTIONS_PDM070801_H
#define BOOST_THREAD_EXCEPTIONS_PDM070801_H
#include <boost/thread/detail/platform.hpp>
#include BOOST_THREAD_PLATFORM(exceptions.hpp)
#include <boost/thread/detail/config.hpp>
#endif // BOOST_THREAD_RS06040710_HPP
// pdm: Sorry, but this class is used all over the place & I end up
// with recursive headers if I don't separate it
// wek: Not sure why recursive headers would cause compilation problems
// given the include guards, but regardless it makes sense to
// seperate this out any way.
#include <string>
#include <stdexcept>
namespace boost {
class BOOST_THREAD_DECL thread_exception : public std::exception
{
protected:
thread_exception();
thread_exception(int sys_err_code);
public:
~thread_exception() throw();
int native_error() const;
const char* message() const;
private:
int m_sys_err;
};
class BOOST_THREAD_DECL lock_error : public thread_exception
{
public:
lock_error();
lock_error(int sys_err_code);
~lock_error() throw();
virtual const char* what() const throw();
};
class BOOST_THREAD_DECL thread_resource_error : public thread_exception
{
public:
thread_resource_error();
thread_resource_error(int sys_err_code);
~thread_resource_error() throw();
virtual const char* what() const throw();
};
class BOOST_THREAD_DECL unsupported_thread_option : public thread_exception
{
public:
unsupported_thread_option();
unsupported_thread_option(int sys_err_code);
~unsupported_thread_option() throw();
virtual const char* what() const throw();
};
class BOOST_THREAD_DECL invalid_thread_argument : public thread_exception
{
public:
invalid_thread_argument();
invalid_thread_argument(int sys_err_code);
~invalid_thread_argument() throw();
virtual const char* what() const throw();
};
class BOOST_THREAD_DECL thread_permission_error : public thread_exception
{
public:
thread_permission_error();
thread_permission_error(int sys_err_code);
~thread_permission_error() throw();
virtual const char* what() const throw();
};
} // namespace boost
#endif // BOOST_THREAD_CONFIG_PDM070801_H
// Change log:
// 3 Jan 03 WEKEMPF Modified for DLL implementation.

View File

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

View File

@@ -1,156 +0,0 @@
// Copyright 2006 Roland Schwarz.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_THREAD_RS06040707_HPP
#define BOOST_THREAD_RS06040707_HPP
#include <boost/thread/pthread/config.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/utility.hpp>
#include <boost/thread/pthread/lock.hpp>
#include <pthread.h>
namespace boost {
struct xtime;
// disable warnings about non dll import
// see: http://www.boost.org/more/separate_compilation.html#dlls
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4251 4231 4660 4275)
#endif
namespace detail {
class BOOST_THREAD_DECL condition_impl : private noncopyable
{
friend class condition;
public:
condition_impl();
~condition_impl();
void notify_one();
void notify_all();
void do_wait(pthread_mutex_t* pmutex);
bool do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex);
pthread_cond_t m_condition;
};
} // namespace detail
class condition : private noncopyable
{
public:
condition() { }
~condition() { }
void notify_one() { m_impl.notify_one(); }
void notify_all() { m_impl.notify_all(); }
template <typename L>
void wait(L& lock)
{
if (!lock)
throw lock_error();
do_wait(lock.m_mutex);
}
template <typename L, typename Pr>
void wait(L& lock, Pr pred)
{
if (!lock)
throw lock_error();
while (!pred())
do_wait(lock.m_mutex);
}
template <typename L>
bool timed_wait(L& lock, const xtime& xt)
{
if (!lock)
throw lock_error();
return do_timed_wait(lock.m_mutex, xt);
}
template <typename L, typename Pr>
bool timed_wait(L& lock, const xtime& xt, Pr pred)
{
if (!lock)
throw lock_error();
while (!pred())
{
if (!do_timed_wait(lock.m_mutex, xt))
return false;
}
return true;
}
private:
detail::condition_impl m_impl;
template <typename M>
void do_wait(M& mutex)
{
typedef detail::thread::lock_ops<M>
#if defined(__HP_aCC) && __HP_aCC <= 33900 && !defined(BOOST_STRICT_CONFIG)
# define lock_ops lock_ops_ // HP confuses lock_ops witht the template
#endif
lock_ops;
typename lock_ops::lock_state state;
lock_ops::unlock(mutex, state);
m_impl.do_wait(state.pmutex);
lock_ops::lock(mutex, state);
#undef lock_ops
}
template <typename M>
bool do_timed_wait(M& mutex, const xtime& xt)
{
typedef detail::thread::lock_ops<M>
#if defined(__HP_aCC) && __HP_aCC <= 33900 && !defined(BOOST_STRICT_CONFIG)
# define lock_ops lock_ops_ // HP confuses lock_ops witht the template
#endif
lock_ops;
typename lock_ops::lock_state state;
lock_ops::unlock(mutex, state);
bool ret = false;
ret = m_impl.do_timed_wait(xt, state.pmutex);
lock_ops::lock(mutex, state);
#undef lock_ops
return ret;
}
};
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
} // namespace boost
#endif // BOOST_CONDITION_RS06040707_HPP

View File

@@ -1,77 +0,0 @@
// Copyright 2006 Roland Schwarz.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_THREAD_RS06040702_HPP
#define BOOST_THREAD_RS06040702_HPP
#include <boost/config.hpp>
// insist on threading support being available:
#include <boost/config/requires_threads.hpp>
#if defined(BOOST_THREAD_BUILD_DLL) //Build dll
#elif defined(BOOST_THREAD_BUILD_LIB) //Build lib
#elif defined(BOOST_THREAD_USE_DLL) //Use dll
#elif defined(BOOST_THREAD_USE_LIB) //Use lib
#else //Use default
# if defined(BOOST_HAS_WINTHREADS)
# if defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)
//For compilers supporting auto-tss cleanup
//with Boost.Threads lib, use Boost.Threads lib
# define BOOST_THREAD_USE_LIB
# else
//For compilers not yet supporting auto-tss cleanup
//with Boost.Threads lib, use Boost.Threads dll
# define BOOST_THREAD_USE_DLL
# endif
# else
# define BOOST_THREAD_USE_LIB
# endif
#endif
#if defined(BOOST_HAS_DECLSPEC)
# if defined(BOOST_THREAD_BUILD_DLL) //Build dll
# define BOOST_THREAD_DECL __declspec(dllexport)
# elif defined(BOOST_THREAD_USE_DLL) //Use dll
# define BOOST_THREAD_DECL __declspec(dllimport)
# else
# define BOOST_THREAD_DECL
# endif
#else
# define BOOST_THREAD_DECL
#endif // BOOST_HAS_DECLSPEC
//
// Automatically link to the correct build variant where possible.
//
#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_THREAD_NO_LIB) && !defined(BOOST_THREAD_BUILD_DLL) && !defined(BOOST_THREAD_BUILD_LIB)
//
// Tell the autolink to link dynamically, this will get undef'ed by auto_link.hpp
// once it's done with it:
//
#if defined(BOOST_THREAD_USE_DLL)
# define BOOST_DYN_LINK
#endif
//
// Set the name of our library, this will get undef'ed by auto_link.hpp
// once it's done with it:
//
#if defined(BOOST_THREAD_LIB_NAME)
# define BOOST_LIB_NAME BOOST_THREAD_LIB_NAME
#else
# define BOOST_LIB_NAME boost_thread_pthread
#endif
//
// If we're importing code from a dll, then tell auto_link.hpp about it:
//
// And include the header that does the work:
//
#include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
#endif // BOOST_THREAD_RS06040702_HPP

View File

@@ -1,88 +0,0 @@
// Copyright 2006 Roland Schwarz.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_THREAD_RS06040709_HPP
#define BOOST_THREAD_RS06040709_HPP
#include <boost/thread/pthread/config.hpp>
#include <string>
#include <stdexcept>
namespace boost {
class BOOST_THREAD_DECL thread_exception : public std::exception
{
protected:
thread_exception();
thread_exception(int sys_err_code);
public:
~thread_exception() throw();
int native_error() const;
const char* message() const;
private:
int m_sys_err;
};
class BOOST_THREAD_DECL lock_error : public thread_exception
{
public:
lock_error();
lock_error(int sys_err_code);
~lock_error() throw();
virtual const char* what() const throw();
};
class BOOST_THREAD_DECL thread_resource_error : public thread_exception
{
public:
thread_resource_error();
thread_resource_error(int sys_err_code);
~thread_resource_error() throw();
virtual const char* what() const throw();
};
class BOOST_THREAD_DECL unsupported_thread_option : public thread_exception
{
public:
unsupported_thread_option();
unsupported_thread_option(int sys_err_code);
~unsupported_thread_option() throw();
virtual const char* what() const throw();
};
class BOOST_THREAD_DECL invalid_thread_argument : public thread_exception
{
public:
invalid_thread_argument();
invalid_thread_argument(int sys_err_code);
~invalid_thread_argument() throw();
virtual const char* what() const throw();
};
class BOOST_THREAD_DECL thread_permission_error : public thread_exception
{
public:
thread_permission_error();
thread_permission_error(int sys_err_code);
~thread_permission_error() throw();
virtual const char* what() const throw();
};
} // namespace boost
#endif // BOOST_THREAD_RS06040709_HPP

View File

@@ -1,116 +0,0 @@
// Copyright 2006 Roland Schwarz.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_THREAD_RS06040705_HPP
#define BOOST_THREAD_RS06040705_HPP
#include <boost/thread/pthread/config.hpp>
#include <boost/utility.hpp>
#include <boost/thread/pthread/lock.hpp>
#include <pthread.h>
namespace boost {
struct xtime;
// disable warnings about non dll import
// see: http://www.boost.org/more/separate_compilation.html#dlls
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4251 4231 4660 4275)
#endif
class BOOST_THREAD_DECL mutex
: private noncopyable
{
public:
friend class detail::thread::lock_ops<mutex>;
typedef detail::thread::scoped_lock<mutex> scoped_lock;
mutex();
~mutex();
private:
struct cv_state
{
pthread_mutex_t* pmutex;
};
void do_lock();
void do_unlock();
void do_lock(cv_state& state);
void do_unlock(cv_state& state);
pthread_mutex_t m_mutex;
};
class BOOST_THREAD_DECL try_mutex
: private noncopyable
{
public:
friend class detail::thread::lock_ops<try_mutex>;
typedef detail::thread::scoped_lock<try_mutex> scoped_lock;
typedef detail::thread::scoped_try_lock<try_mutex> scoped_try_lock;
try_mutex();
~try_mutex();
private:
struct cv_state
{
pthread_mutex_t* pmutex;
};
void do_lock();
bool do_trylock();
void do_unlock();
void do_lock(cv_state& state);
void do_unlock(cv_state& state);
pthread_mutex_t m_mutex;
};
class BOOST_THREAD_DECL timed_mutex
: private noncopyable
{
public:
friend class detail::thread::lock_ops<timed_mutex>;
typedef detail::thread::scoped_lock<timed_mutex> scoped_lock;
typedef detail::thread::scoped_try_lock<timed_mutex> scoped_try_lock;
typedef detail::thread::scoped_timed_lock<timed_mutex> scoped_timed_lock;
timed_mutex();
~timed_mutex();
private:
struct cv_state
{
pthread_mutex_t* pmutex;
};
void do_lock();
bool do_trylock();
bool do_timedlock(const xtime& xt);
void do_unlock();
void do_lock(cv_state& state);
void do_unlock(cv_state& state);
pthread_mutex_t m_mutex;
pthread_cond_t m_condition;
bool m_locked;
};
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
} // namespace boost
#endif // BOOST_MUTEX_RS06040705_HPP

View File

@@ -1,74 +0,0 @@
#ifndef BOOST_THREAD_PTHREAD_ONCE_HPP
#define BOOST_THREAD_PTHREAD_ONCE_HPP
// once.hpp
//
// (C) Copyright 2007 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/pthread/config.hpp>
#include <pthread.h>
#include <boost/assert.hpp>
namespace boost {
struct once_flag
{
pthread_mutex_t mutex;
unsigned flag;
};
#define BOOST_ONCE_INIT {PTHREAD_MUTEX_INITIALIZER,0}
namespace detail
{
struct pthread_mutex_scoped_lock
{
pthread_mutex_t * mutex;
explicit pthread_mutex_scoped_lock(pthread_mutex_t* mutex_):
mutex(mutex_)
{
int const res=pthread_mutex_lock(mutex);
BOOST_ASSERT(!res);
}
~pthread_mutex_scoped_lock()
{
int const res=pthread_mutex_unlock(mutex);
BOOST_ASSERT(!res);
}
};
}
template<typename Function>
void call_once(once_flag& flag,Function f)
{
long const function_complete_flag_value=0xc15730e2;
#ifdef BOOST_PTHREAD_HAS_ATOMICS
if(::boost::detail::interlocked_read_acquire(&flag.flag)!=function_complete_flag_value)
{
#endif
detail::pthread_mutex_scoped_lock const lock(&flag.mutex);
if(flag.flag!=function_complete_flag_value)
{
f();
#ifdef BOOST_PTHREAD_HAS_ATOMICS
::boost::detail::interlocked_write_release(&flag.flag,function_complete_flag_value);
#else
flag.flag=function_complete_flag_value;
#endif
}
#ifdef BOOST_PTHREAD_HAS_ATOMICS
}
#endif
}
}
#endif

View File

@@ -1,389 +0,0 @@
#ifndef BOOST_THREAD_PTHREAD_READ_WRITE_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_READ_WRITE_MUTEX_HPP
// (C) Copyright 2006-7 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/xtime.hpp>
namespace boost
{
class read_write_mutex
{
private:
struct state_data
{
unsigned shared_count:10;
unsigned exclusive:1;
unsigned upgradeable:1;
unsigned exclusive_waiting_blocked:1;
};
state_data state;
boost::mutex state_change;
boost::condition shared_cond;
boost::condition exclusive_cond;
boost::condition upgradeable_cond;
void release_waiters()
{
exclusive_cond.notify_one();
shared_cond.notify_all();
}
public:
read_write_mutex()
{
state_data state_={0};
state=state_;
}
~read_write_mutex()
{
}
void lock_shareable()
{
boost::mutex::scoped_lock lock(state_change);
while(true)
{
if(!state.exclusive && !state.exclusive_waiting_blocked)
{
++state.shared_count;
return;
}
shared_cond.wait(lock);
}
}
bool try_lock_shareable()
{
boost::mutex::scoped_lock lock(state_change);
if(state.exclusive || state.exclusive_waiting_blocked)
{
return false;
}
else
{
++state.shared_count;
return true;
}
}
bool timed_lock_shareable(xtime const& timeout)
{
boost::mutex::scoped_lock lock(state_change);
while(true)
{
if(!state.exclusive && !state.exclusive_waiting_blocked)
{
++state.shared_count;
return true;
}
if(!shared_cond.timed_wait(lock,timeout))
{
return false;
}
}
}
void unlock_shareable()
{
boost::mutex::scoped_lock lock(state_change);
bool const last_reader=!--state.shared_count;
if(last_reader)
{
if(state.upgradeable)
{
state.upgradeable=false;
state.exclusive=true;
upgradeable_cond.notify_one();
}
else
{
state.exclusive_waiting_blocked=false;
}
release_waiters();
}
}
void lock()
{
boost::mutex::scoped_lock lock(state_change);
while(true)
{
if(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=true;
}
else
{
state.exclusive=true;
return;
}
exclusive_cond.wait(lock);
}
}
bool timed_lock(xtime const& timeout)
{
boost::mutex::scoped_lock lock(state_change);
while(true)
{
if(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=true;
}
else
{
state.exclusive=true;
return true;
}
if(!exclusive_cond.timed_wait(lock,timeout))
{
return false;
}
}
}
bool try_lock()
{
boost::mutex::scoped_lock lock(state_change);
if(state.shared_count || state.exclusive)
{
return false;
}
else
{
state.exclusive=true;
return true;
}
}
void unlock()
{
boost::mutex::scoped_lock lock(state_change);
state.exclusive=false;
state.exclusive_waiting_blocked=false;
release_waiters();
}
void lock_upgradeable()
{
boost::mutex::scoped_lock lock(state_change);
while(true)
{
if(!state.exclusive && !state.exclusive_waiting_blocked && !state.upgradeable)
{
++state.shared_count;
state.upgradeable=true;
return;
}
shared_cond.wait(lock);
}
}
bool timed_lock_upgradeable(xtime const& timeout)
{
boost::mutex::scoped_lock lock(state_change);
while(true)
{
if(!state.exclusive && !state.exclusive_waiting_blocked && !state.upgradeable)
{
++state.shared_count;
state.upgradeable=true;
return true;
}
if(!shared_cond.timed_wait(lock,timeout))
{
return false;
}
}
}
bool try_lock_upgradeable()
{
boost::mutex::scoped_lock lock(state_change);
if(state.exclusive || state.exclusive_waiting_blocked || state.upgradeable)
{
return false;
}
else
{
++state.shared_count;
state.upgradeable=true;
return true;
}
}
void unlock_upgradeable()
{
boost::mutex::scoped_lock lock(state_change);
state.upgradeable=false;
bool const last_reader=!--state.shared_count;
if(last_reader)
{
state.exclusive_waiting_blocked=false;
release_waiters();
}
}
void unlock_upgradeable_and_lock()
{
boost::mutex::scoped_lock lock(state_change);
--state.shared_count;
while(true)
{
if(!state.shared_count)
{
state.upgradeable=false;
state.exclusive=true;
break;
}
upgradeable_cond.wait(lock);
}
}
void unlock_and_lock_upgradeable()
{
boost::mutex::scoped_lock lock(state_change);
state.exclusive=false;
state.upgradeable=true;
++state.shared_count;
state.exclusive_waiting_blocked=false;
release_waiters();
}
void unlock_and_lock_shareable()
{
boost::mutex::scoped_lock lock(state_change);
state.exclusive=false;
++state.shared_count;
state.exclusive_waiting_blocked=false;
release_waiters();
}
void unlock_upgradeable_and_lock_shareable()
{
boost::mutex::scoped_lock lock(state_change);
state.upgradeable=false;
state.exclusive_waiting_blocked=false;
release_waiters();
}
class scoped_read_lock
{
read_write_mutex& m;
public:
scoped_read_lock(read_write_mutex& m_):
m(m_)
{
m.lock_shareable();
}
~scoped_read_lock()
{
m.unlock_shareable();
}
};
class scoped_write_lock
{
read_write_mutex& m;
bool locked;
public:
scoped_write_lock(read_write_mutex& m_):
m(m_),locked(false)
{
lock();
}
void lock()
{
m.lock();
locked=true;
}
void unlock()
{
m.unlock();
locked=false;
}
~scoped_write_lock()
{
if(locked)
{
unlock();
}
}
};
class scoped_upgradeable_lock
{
read_write_mutex& m;
bool locked;
bool upgraded;
public:
scoped_upgradeable_lock(read_write_mutex& m_):
m(m_),
locked(false),upgraded(false)
{
lock();
}
void lock()
{
m.lock_upgradeable();
locked=true;
}
void upgrade()
{
m.unlock_upgradeable_and_lock();
upgraded=true;
}
void unlock()
{
if(upgraded)
{
m.unlock();
}
else
{
m.unlock_upgradeable();
}
}
~scoped_upgradeable_lock()
{
if(locked)
{
unlock();
}
}
};
};
}
#endif

View File

@@ -1,136 +0,0 @@
// Copyright (C) 2001-2003 William E. Kempf
// Copyright (C) 2006 Roland Schwarz
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_RECURSIVE_MUTEX_RS06092302_HPP
#define BOOST_RECURSIVE_MUTEX_RS06092302_HPP
#include <boost/thread/pthread/config.hpp>
#include <boost/utility.hpp>
#include <boost/thread/pthread/lock.hpp>
#include <pthread.h>
namespace boost {
struct xtime;
// disable warnings about non dll import
// see: http://www.boost.org/more/separate_compilation.html#dlls
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4251 4231 4660 4275)
#endif
class BOOST_THREAD_DECL recursive_mutex
: private noncopyable
{
public:
friend class detail::thread::lock_ops<recursive_mutex>;
typedef detail::thread::scoped_lock<recursive_mutex> scoped_lock;
recursive_mutex();
~recursive_mutex();
private:
struct cv_state
{
long count;
pthread_mutex_t* pmutex;
};
void do_lock();
void do_unlock();
void do_lock(cv_state& state);
void do_unlock(cv_state& state);
pthread_mutex_t m_mutex;
unsigned m_count;
#if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
pthread_cond_t m_unlocked;
pthread_t m_thread_id;
bool m_valid_id;
#endif
};
class BOOST_THREAD_DECL recursive_try_mutex
: private noncopyable
{
public:
friend class detail::thread::lock_ops<recursive_try_mutex>;
typedef detail::thread::scoped_lock<recursive_try_mutex> scoped_lock;
typedef detail::thread::scoped_try_lock<
recursive_try_mutex> scoped_try_lock;
recursive_try_mutex();
~recursive_try_mutex();
private:
struct cv_state
{
long count;
pthread_mutex_t* pmutex;
};
void do_lock();
bool do_trylock();
void do_unlock();
void do_lock(cv_state& state);
void do_unlock(cv_state& state);
pthread_mutex_t m_mutex;
unsigned m_count;
#if !defined(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE)
pthread_cond_t m_unlocked;
pthread_t m_thread_id;
bool m_valid_id;
#endif
};
class BOOST_THREAD_DECL recursive_timed_mutex
: private noncopyable
{
public:
friend class detail::thread::lock_ops<recursive_timed_mutex>;
typedef detail::thread::scoped_lock<recursive_timed_mutex> scoped_lock;
typedef detail::thread::scoped_try_lock<
recursive_timed_mutex> scoped_try_lock;
typedef detail::thread::scoped_timed_lock<
recursive_timed_mutex> scoped_timed_lock;
recursive_timed_mutex();
~recursive_timed_mutex();
private:
struct cv_state
{
long count;
pthread_mutex_t* pmutex;
};
void do_lock();
bool do_trylock();
bool do_timedlock(const xtime& xt);
void do_unlock();
void do_lock(cv_state& state);
void do_unlock(cv_state& state);
pthread_mutex_t m_mutex;
pthread_cond_t m_unlocked;
pthread_t m_thread_id;
bool m_valid_id;
unsigned m_count;
};
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
} // namespace boost
#endif // BOOST_RECURSIVE_MUTEX_RS06092302_HPP

View File

@@ -1,75 +0,0 @@
// Copyright 2006 Roland Schwarz.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_THREAD_RS06040701_HPP
#define BOOST_THREAD_RS06040701_HPP
#include <boost/thread/pthread/config.hpp>
#include <boost/thread/pthread/mutex.hpp>
#include <boost/utility.hpp>
#include <boost/function.hpp>
#include <list>
#include <memory>
#include <pthread.h>
namespace boost {
struct xtime;
// disable warnings about non dll import
// see: http://www.boost.org/more/separate_compilation.html#dlls
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4251 4231 4660 4275)
#endif
class BOOST_THREAD_DECL thread : private noncopyable
{
public:
thread();
explicit thread(const function0<void>& threadfunc);
~thread();
bool operator==(const thread& other) const;
bool operator!=(const thread& other) const;
void join();
static void sleep(const xtime& xt);
static void yield();
private:
pthread_t m_thread;
bool m_joinable;
};
class BOOST_THREAD_DECL thread_group : private noncopyable
{
public:
thread_group();
~thread_group();
thread* create_thread(const function0<void>& threadfunc);
void add_thread(thread* thrd);
void remove_thread(thread* thrd);
void join_all();
int size();
private:
std::list<thread*> m_threads;
mutex m_mutex;
};
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
} // namespace boost
#endif // BOOST_THREAD_RS06040701_HPP

View File

@@ -1,108 +0,0 @@
// Copyright (C) 2001-2003 William E. Kempf
// Copyright (C) 2006 Roland Schwarz
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_TSS_RS06092304_HPP
#define BOOST_TSS_RS06092304_HPP
#include <boost/thread/pthread/config.hpp>
#include <boost/utility.hpp>
#include <boost/function.hpp>
#include <boost/thread/pthread/exceptions.hpp>
#include <pthread.h>
namespace boost {
// disable warnings about non dll import
// see: http://www.boost.org/more/separate_compilation.html#dlls
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4251 4231 4660 4275)
#endif
namespace detail {
class BOOST_THREAD_DECL tss : private noncopyable
{
public:
tss(boost::function1<void, void*>* pcleanup) {
if (pcleanup == 0) throw boost::thread_resource_error();
try
{
init(pcleanup);
}
catch (...)
{
delete pcleanup;
throw boost::thread_resource_error();
}
}
void* get() const;
void set(void* value);
void cleanup(void* p);
private:
unsigned int m_slot; //This is a "pseudo-slot", not a native slot
void init(boost::function1<void, void*>* pcleanup);
};
template <typename T>
struct tss_adapter
{
template <typename F>
tss_adapter(const F& cleanup) : m_cleanup(cleanup) { }
void operator()(void* p) { m_cleanup(static_cast<T*>(p)); }
boost::function1<void, T*> m_cleanup;
};
} // namespace detail
template <typename T>
class thread_specific_ptr : private noncopyable
{
public:
thread_specific_ptr()
: m_tss(new boost::function1<void, void*>(
boost::detail::tss_adapter<T>(
&thread_specific_ptr<T>::cleanup)))
{
}
thread_specific_ptr(void (*clean)(T*))
: m_tss(new boost::function1<void, void*>(
boost::detail::tss_adapter<T>(clean)))
{
}
~thread_specific_ptr() { reset(); }
T* get() const { return static_cast<T*>(m_tss.get()); }
T* operator->() const { return get(); }
T& operator*() const { return *get(); }
T* release() { T* temp = get(); if (temp) m_tss.set(0); return temp; }
void reset(T* p=0)
{
T* cur = get();
if (cur == p) return;
m_tss.set(p);
if (cur) m_tss.cleanup(cur);
}
private:
static void cleanup(T* p) { delete p; }
detail::tss m_tss;
};
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
} // namespace boost
#endif //BOOST_TSS_RS06092304_HPP

View File

@@ -1,56 +0,0 @@
// Copyright 2006 Roland Schwarz.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_THREAD_RS06040711_HPP
#define BOOST_THREAD_RS06040711_HPP
#include <boost/thread/pthread/config.hpp>
#include <boost/cstdint.hpp>
namespace boost {
enum xtime_clock_types
{
TIME_UTC=1
// TIME_TAI,
// TIME_MONOTONIC,
// TIME_PROCESS,
// TIME_THREAD,
// TIME_LOCAL,
// TIME_SYNC,
// TIME_RESOLUTION
};
struct xtime
{
#if defined(BOOST_NO_INT64_T)
typedef int_fast32_t xtime_sec_t; //INT_FAST32_MIN <= sec <= INT_FAST32_MAX
#else
typedef int_fast64_t xtime_sec_t; //INT_FAST64_MIN <= sec <= INT_FAST64_MAX
#endif
typedef int_fast32_t xtime_nsec_t; //0 <= xtime.nsec < NANOSECONDS_PER_SECOND
xtime_sec_t sec;
xtime_nsec_t nsec;
};
int BOOST_THREAD_DECL xtime_get(struct xtime* xtp, int clock_type);
inline int xtime_cmp(const xtime& xt1, const xtime& xt2)
{
if (xt1.sec == xt2.sec)
return (int)(xt1.nsec - xt2.nsec);
else
return (xt1.sec > xt2.sec) ? 1 : -1;
}
} // namespace boost
#endif //BOOST_THREAD_RS06040711_HPP

View File

@@ -1,13 +1,273 @@
#ifndef BOOST_THREAD_READ_WRITE_MUTEX_HPP
#define BOOST_THREAD_READ_WRITE_MUTEX_HPP
// Copyright (C) 2002-2003
// David Moore, William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. David Moore makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// (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)
// A Boost::threads implementation of a synchronization
// primitive which can allow multiple readers or a single
// writer to have access to a shared resource.
#ifndef BOOST_READ_WRITE_MUTEX_JDM030602_HPP
#define BOOST_READ_WRITE_MUTEX_JDM030602_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/utility.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/detail/lock.hpp>
#include <boost/thread/detail/read_write_lock.hpp>
#include <boost/thread/condition.hpp>
namespace boost {
namespace read_write_scheduling_policy {
enum read_write_scheduling_policy_enum
{
writer_priority, //Prefer writers; can starve readers
reader_priority, //Prefer readers; can starve writers
alternating_many_reads, //Alternate readers and writers; before a writer, release all queued readers
alternating_single_read //Alternate readers and writers; before a writer, release only on queued reader
};
} // namespace read_write_scheduling_policy
namespace detail {
namespace thread {
// Shared implementation construct for explicit Scheduling Policies
// This implementation is susceptible to self-deadlock, though....
template<typename Mutex>
struct read_write_mutex_impl
{
typedef Mutex mutex_type;
typedef detail::thread::scoped_lock<Mutex> scoped_lock;
typedef detail::thread::scoped_try_lock<Mutex> scoped_try_lock;
typedef detail::thread::scoped_timed_lock<Mutex> scoped_timed_lock;
read_write_mutex_impl(read_write_scheduling_policy::read_write_scheduling_policy_enum sp)
: m_num_waiting_writers(0),
m_num_waiting_readers(0),
m_num_readers_to_wake(0),
m_state_waiting_promotion(false),
m_state(0),
m_sp(sp),
m_readers_next(true) { }
Mutex m_prot;
boost::condition m_waiting_writers;
boost::condition m_waiting_readers;
int m_num_waiting_writers;
int m_num_waiting_readers;
int m_num_readers_to_wake;
boost::condition m_waiting_promotion;
bool m_state_waiting_promotion;
int m_state; // -1 = excl locked
// 0 = unlocked
// 1-> INT_MAX - shared locked
const read_write_scheduling_policy::read_write_scheduling_policy_enum m_sp;
bool m_readers_next;
void do_read_lock();
void do_write_lock();
void do_write_unlock();
void do_read_unlock();
bool do_try_write_lock();
bool do_try_read_lock();
bool do_timed_write_lock(const xtime &xt);
bool do_timed_read_lock(const xtime &xt);
void do_demote_to_read_lock();
bool do_try_demote_to_read_lock();
bool do_timed_demote_to_read_lock(const xtime &xt);
void do_promote_to_write_lock();
bool do_try_promote_to_write_lock();
bool do_timed_promote_to_write_lock(const xtime &xt);
bool locked();
read_write_lock_state::read_write_lock_state_enum state();
private:
void do_unlock_scheduling_impl();
void do_timeout_scheduling_impl();
void do_demote_scheduling_impl();
void do_scheduling_impl();
bool do_demote_to_read_lock_impl();
};
} // namespace detail
} // namespace thread
class BOOST_THREAD_DECL read_write_mutex : private noncopyable
{
public:
read_write_mutex(read_write_scheduling_policy::read_write_scheduling_policy_enum sp) : m_impl(sp) { }
~read_write_mutex() { }
read_write_scheduling_policy::read_write_scheduling_policy_enum policy() const { return m_impl.m_sp; }
friend class detail::thread::read_write_lock_ops<read_write_mutex>;
typedef detail::thread::scoped_read_write_lock<
read_write_mutex> scoped_read_write_lock;
typedef detail::thread::scoped_read_lock<
read_write_mutex> scoped_read_lock;
typedef detail::thread::scoped_write_lock<
read_write_mutex> scoped_write_lock;
private:
// Operations that will eventually be done only
// via lock types
void do_write_lock();
void do_read_lock();
void do_write_unlock();
void do_read_unlock();
void do_demote_to_read_lock();
void do_promote_to_write_lock();
bool locked();
read_write_lock_state::read_write_lock_state_enum state();
detail::thread::read_write_mutex_impl<mutex> m_impl;
};
class BOOST_THREAD_DECL try_read_write_mutex : private noncopyable
{
public:
try_read_write_mutex(read_write_scheduling_policy::read_write_scheduling_policy_enum sp) : m_impl(sp) { }
~try_read_write_mutex() { }
read_write_scheduling_policy::read_write_scheduling_policy_enum policy() const { return m_impl.m_sp; }
friend class detail::thread::read_write_lock_ops<try_read_write_mutex>;
typedef detail::thread::scoped_read_write_lock<
try_read_write_mutex> scoped_read_write_lock;
typedef detail::thread::scoped_try_read_write_lock<
try_read_write_mutex> scoped_try_read_write_lock;
typedef detail::thread::scoped_read_lock<
try_read_write_mutex> scoped_read_lock;
typedef detail::thread::scoped_try_read_lock<
try_read_write_mutex> scoped_try_read_lock;
typedef detail::thread::scoped_write_lock<
try_read_write_mutex> scoped_write_lock;
typedef detail::thread::scoped_try_write_lock<
try_read_write_mutex> scoped_try_write_lock;
private:
// Operations that will eventually be done only
// via lock types
void do_write_lock();
void do_read_lock();
void do_write_unlock();
void do_read_unlock();
bool do_try_write_lock();
bool do_try_read_lock();
#include <boost/thread/detail/platform.hpp>
#include BOOST_THREAD_PLATFORM(read_write_mutex.hpp)
void do_demote_to_read_lock();
bool do_try_demote_to_read_lock();
void do_promote_to_write_lock();
bool do_try_promote_to_write_lock();
bool locked();
read_write_lock_state::read_write_lock_state_enum state();
detail::thread::read_write_mutex_impl<try_mutex> m_impl;
};
class BOOST_THREAD_DECL timed_read_write_mutex : private noncopyable
{
public:
timed_read_write_mutex(read_write_scheduling_policy::read_write_scheduling_policy_enum sp) : m_impl(sp) { }
~timed_read_write_mutex() { }
read_write_scheduling_policy::read_write_scheduling_policy_enum policy() const { return m_impl.m_sp; }
friend class detail::thread::read_write_lock_ops<timed_read_write_mutex>;
typedef detail::thread::scoped_read_write_lock<
timed_read_write_mutex> scoped_read_write_lock;
typedef detail::thread::scoped_try_read_write_lock<
timed_read_write_mutex> scoped_try_read_write_lock;
typedef detail::thread::scoped_timed_read_write_lock<
timed_read_write_mutex> scoped_timed_read_write_lock;
typedef detail::thread::scoped_read_lock<
timed_read_write_mutex> scoped_read_lock;
typedef detail::thread::scoped_try_read_lock<
timed_read_write_mutex> scoped_try_read_lock;
typedef detail::thread::scoped_timed_read_lock<
timed_read_write_mutex> scoped_timed_read_lock;
typedef detail::thread::scoped_write_lock<
timed_read_write_mutex> scoped_write_lock;
typedef detail::thread::scoped_try_write_lock<
timed_read_write_mutex> scoped_try_write_lock;
typedef detail::thread::scoped_timed_write_lock<
timed_read_write_mutex> scoped_timed_write_lock;
private:
// Operations that will eventually be done only
// via lock types
void do_write_lock();
void do_read_lock();
void do_write_unlock();
void do_read_unlock();
bool do_try_write_lock();
bool do_try_read_lock();
bool do_timed_write_lock(const xtime &xt);
bool do_timed_read_lock(const xtime &xt);
void do_demote_to_read_lock();
bool do_try_demote_to_read_lock();
bool do_timed_demote_to_read_lock(const xtime &xt);
void do_promote_to_write_lock();
bool do_try_promote_to_write_lock();
bool do_timed_promote_to_write_lock(const xtime &xt);
bool locked();
read_write_lock_state::read_write_lock_state_enum state();
detail::thread::read_write_mutex_impl<timed_mutex> m_impl;
};
} // namespace boost
#endif
// Change Log:
// 10 Mar 02
// Original version.
// 4 May 04 GlassfordM
// Implement lock promotion and demotion.
// Add locked() and state() member functions for debugging
// (should these be made public?).
// Rename to improve consistency and eliminate abbreviations:
// Use "read" and "write" instead of "shared" and "exclusive".
// Change "rd" to "read", "wr" to "write", "rw" to "read_write".
// Add mutex_type typdef.

View File

@@ -1,16 +1,182 @@
#ifndef BOOST_THREAD_RECURSIVE_MUTEX_HPP
#define BOOST_THREAD_RECURSIVE_MUTEX_HPP
// recursive_mutex.hpp
// Copyright (C) 2001-2003
// William E. Kempf
//
// (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)
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#include <boost/thread/detail/platform.hpp>
#include BOOST_THREAD_PLATFORM(recursive_mutex.hpp)
#ifndef BOOST_RECURSIVE_MUTEX_WEK070601_HPP
#define BOOST_RECURSIVE_MUTEX_WEK070601_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/utility.hpp>
#include <boost/thread/detail/lock.hpp>
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
#endif
#if defined(BOOST_HAS_MPTASKS)
# include "scoped_critical_region.hpp"
#endif
namespace boost {
struct xtime;
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

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

@@ -1,16 +1,121 @@
// 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)
// Copyright (C) 2001-2003
// William E. Kempf
//
// This work is a reimplementation along the design and ideas
// of 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_TSS_RS06092303_HPP
#define BOOST_TSS_RS06092303_HPP
#ifndef BOOST_TSS_WEK070601_HPP
#define BOOST_TSS_WEK070601_HPP
#include <boost/thread/detail/platform.hpp>
#include BOOST_THREAD_PLATFORM(tss.hpp)
#include <boost/thread/detail/config.hpp>
#endif // BOOST_TSS_RS06092301_HPP
#include <boost/utility.hpp>
#include <boost/function.hpp>
#include <boost/thread/exceptions.hpp>
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
#elif defined(BOOST_HAS_MPTASKS)
# include <Multiprocessing.h>
#endif
namespace boost {
namespace detail {
class BOOST_THREAD_DECL tss : private noncopyable
{
public:
tss(boost::function1<void, void*>* pcleanup) {
if (pcleanup == 0) throw boost::thread_resource_error();
try
{
init(pcleanup);
}
catch (...)
{
delete pcleanup;
throw boost::thread_resource_error();
}
}
void* get() const;
void set(void* value);
void cleanup(void* p);
private:
unsigned int m_slot; //This is a "pseudo-slot", not a native slot
void init(boost::function1<void, void*>* pcleanup);
};
#if defined(BOOST_HAS_MPTASKS)
void thread_cleanup();
#endif
template <typename T>
struct tss_adapter
{
template <typename F>
tss_adapter(const F& cleanup) : m_cleanup(cleanup) { }
void operator()(void* p) { m_cleanup(static_cast<T*>(p)); }
boost::function1<void, T*> m_cleanup;
};
} // namespace detail
template <typename T>
class thread_specific_ptr : private noncopyable
{
public:
thread_specific_ptr()
: m_tss(new boost::function1<void, void*>(
boost::detail::tss_adapter<T>(
&thread_specific_ptr<T>::cleanup)))
{
}
thread_specific_ptr(void (*clean)(T*))
: m_tss(new boost::function1<void, void*>(
boost::detail::tss_adapter<T>(clean)))
{
}
~thread_specific_ptr() { reset(); }
T* get() const { return static_cast<T*>(m_tss.get()); }
T* operator->() const { return get(); }
T& operator*() const { return *get(); }
T* release() { T* temp = get(); if (temp) m_tss.set(0); return temp; }
void reset(T* p=0)
{
T* cur = get();
if (cur == p) return;
m_tss.set(p);
if (cur) m_tss.cleanup(cur);
}
private:
static void cleanup(T* p) { delete p; }
detail::tss m_tss;
};
} // namespace boost
#endif //BOOST_TSS_WEK070601_HPP
// Change Log:
// 6 Jun 01
// WEKEMPF Initial version.
// 30 May 02 WEKEMPF
// Added interface to set specific cleanup handlers.
// Removed TLS slot limits from most implementations.
// 22 Mar 04 GlassfordM for WEKEMPF
// Fixed: thread_specific_ptr::reset() doesn't check error returned
// by tss::set(); tss::set() now throws if it fails.
// Fixed: calling thread_specific_ptr::reset() or
// thread_specific_ptr::release() causes double-delete: once on
// reset()/release() and once on ~thread_specific_ptr().

View File

@@ -1,140 +0,0 @@
#ifndef BOOST_BASIC_CHECKED_MUTEX_WIN32_HPP
#define BOOST_BASIC_CHECKED_MUTEX_WIN32_HPP
// basic_checked_mutex_win32.hpp
//
// (C) Copyright 2006 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/detail/interlocked.hpp>
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/interlocked_read.hpp>
#include <boost/assert.hpp>
namespace boost
{
namespace detail
{
struct basic_checked_mutex
{
long locking_thread;
long active_count;
void* semaphore;
BOOST_STATIC_CONSTANT(long,destroyed_mutex_marker=~0);
void initialize()
{
locking_thread=0;
active_count=0;
semaphore=0;
}
void destroy()
{
long const old_locking_thread=BOOST_INTERLOCKED_EXCHANGE(&locking_thread,destroyed_mutex_marker);
BOOST_ASSERT(!old_locking_thread);
void* const old_semaphore=BOOST_INTERLOCKED_EXCHANGE_POINTER(&semaphore,0);
if(old_semaphore)
{
bool const close_handle_succeeded=BOOST_CLOSE_HANDLE(old_semaphore)!=0;
BOOST_ASSERT(close_handle_succeeded);
}
}
bool try_lock()
{
check_mutex_lock();
bool const success=!BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,1,0);
if(success)
{
set_locking_thread();
}
return success;
}
void lock()
{
check_mutex_lock();
if(BOOST_INTERLOCKED_INCREMENT(&active_count)!=1)
{
bool const wait_succeeded=BOOST_WAIT_FOR_SINGLE_OBJECT(get_semaphore(),BOOST_INFINITE)==0;
BOOST_ASSERT(wait_succeeded);
}
set_locking_thread();
}
long get_active_count()
{
return ::boost::detail::interlocked_read(&active_count);
}
void unlock()
{
long const current_thread=BOOST_GET_CURRENT_THREAD_ID();
long const old_locking_thread=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&locking_thread,0,current_thread);
BOOST_ASSERT(old_locking_thread!=destroyed_mutex_marker);
BOOST_ASSERT(old_locking_thread==current_thread);
if(BOOST_INTERLOCKED_DECREMENT(&active_count)!=0)
{
bool const release_succeeded=BOOST_RELEASE_SEMAPHORE(get_semaphore(),1,0)!=0;
BOOST_ASSERT(release_succeeded);
}
}
bool locked()
{
return get_active_count()!=0;
}
private:
void check_mutex_lock()
{
long const current_thread=BOOST_GET_CURRENT_THREAD_ID();
long const current_locking_thread=::boost::detail::interlocked_read(&locking_thread);
BOOST_ASSERT(current_locking_thread!=current_thread);
BOOST_ASSERT(current_locking_thread!=destroyed_mutex_marker);
}
void set_locking_thread()
{
long const old_owner=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&locking_thread,BOOST_GET_CURRENT_THREAD_ID(),0);
BOOST_ASSERT(old_owner==0);
}
void* get_semaphore()
{
void* current_semaphore=::boost::detail::interlocked_read(&semaphore);
if(!current_semaphore)
{
void* const new_semaphore=BOOST_CREATE_SEMAPHORE(0,0,1,0);
BOOST_ASSERT(new_semaphore);
void* const old_semaphore=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&semaphore,new_semaphore,0);
if(old_semaphore!=0)
{
bool const close_succeeded=BOOST_CLOSE_HANDLE(new_semaphore)!=0;
BOOST_ASSERT(close_succeeded);
return old_semaphore;
}
else
{
return new_semaphore;
}
}
return current_semaphore;
}
};
}
}
#define BOOST_BASIC_CHECKED_MUTEX_INITIALIZER {0}
#endif

View File

@@ -1,123 +0,0 @@
#ifndef BOOST_BASIC_RECURSIVE_MUTEX_WIN32_HPP
#define BOOST_BASIC_RECURSIVE_MUTEX_WIN32_HPP
// basic_recursive_mutex.hpp
//
// (C) Copyright 2006 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/detail/interlocked.hpp>
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/interlocked_read.hpp>
#include <boost/thread/win32/basic_timed_mutex.hpp>
#include <boost/thread/xtime.hpp>
namespace boost
{
namespace detail
{
template<typename underlying_mutex_type>
struct basic_recursive_mutex_impl
{
long recursion_count;
long locking_thread_id;
underlying_mutex_type mutex;
void initialize()
{
recursion_count=0;
locking_thread_id=0;
mutex.initialize();
}
void destroy()
{
mutex.destroy();
}
bool try_lock()
{
long const current_thread_id=win32::GetCurrentThreadId();
return try_recursive_lock(current_thread_id) || try_basic_lock(current_thread_id);
}
void lock()
{
long const current_thread_id=win32::GetCurrentThreadId();
if(!try_recursive_lock(current_thread_id))
{
mutex.lock();
BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
recursion_count=1;
}
}
bool timed_lock(::boost::xtime const& target)
{
long const current_thread_id=win32::GetCurrentThreadId();
return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target);
}
long get_active_count()
{
return mutex.get_active_count();
}
void unlock()
{
if(!--recursion_count)
{
BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,0);
mutex.unlock();
}
}
bool locked()
{
return mutex.locked();
}
private:
bool try_recursive_lock(long current_thread_id)
{
if(::boost::detail::interlocked_read(&locking_thread_id)==current_thread_id)
{
++recursion_count;
return true;
}
return false;
}
bool try_basic_lock(long current_thread_id)
{
if(mutex.try_lock())
{
BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
recursion_count=1;
return true;
}
return false;
}
bool try_timed_lock(long current_thread_id,::boost::xtime const& target)
{
if(mutex.timed_lock(target))
{
BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id);
recursion_count=1;
return true;
}
return false;
}
};
typedef basic_recursive_mutex_impl<basic_timed_mutex> basic_recursive_mutex;
typedef basic_recursive_mutex_impl<basic_timed_mutex> basic_recursive_timed_mutex;
}
}
#define BOOST_BASIC_RECURSIVE_MUTEX_INITIALIZER {0}
#endif

View File

@@ -1,158 +0,0 @@
#ifndef BOOST_BASIC_TIMED_MUTEX_WIN32_HPP
#define BOOST_BASIC_TIMED_MUTEX_WIN32_HPP
// basic_timed_mutex_win32.hpp
//
// (C) Copyright 2006 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/assert.hpp>
#include <boost/detail/interlocked.hpp>
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/interlocked_read.hpp>
#include <boost/thread/win32/xtime.hpp>
#include <boost/thread/win32/xtime_utils.hpp>
namespace boost
{
namespace detail
{
struct basic_timed_mutex
{
BOOST_STATIC_CONSTANT(long,lock_flag_value=0x10000);
long active_count;
void* event;
void initialize()
{
active_count=0;
event=0;
}
void destroy()
{
void* const old_event=BOOST_INTERLOCKED_EXCHANGE_POINTER(&event,0);
if(old_event)
{
win32::CloseHandle(old_event);
}
}
bool try_lock()
{
long old_count=0;
while(!(old_count&lock_flag_value))
{
long const current_count=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,(old_count+1)|lock_flag_value,old_count);
if(current_count==old_count)
{
return true;
}
old_count=current_count;
}
return false;
}
void lock()
{
bool const success=timed_lock(::boost::detail::get_xtime_sentinel());
BOOST_ASSERT(success);
}
bool timed_lock(::boost::xtime const& target_time)
{
long old_count=0;
while(true)
{
long const current_count=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,(old_count+1)|lock_flag_value,old_count);
if(current_count==old_count)
{
break;
}
old_count=current_count;
}
if(old_count&lock_flag_value)
{
bool lock_acquired=false;
void* const sem=get_event();
++old_count; // we're waiting, too
do
{
old_count-=(lock_flag_value+1); // there will be one less active thread on this mutex when it gets unlocked
if(win32::WaitForSingleObject(sem,::boost::detail::get_milliseconds_until_time(target_time))!=0)
{
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
}
do
{
long const current_count=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,old_count|lock_flag_value,old_count);
if(current_count==old_count)
{
break;
}
old_count=current_count;
}
while(!(old_count&lock_flag_value));
lock_acquired=!(old_count&lock_flag_value);
}
while(!lock_acquired);
}
return true;
}
long get_active_count()
{
return ::boost::detail::interlocked_read(&active_count);
}
void unlock()
{
long const offset=lock_flag_value+1;
long old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,-offset);
if(old_count>offset)
{
win32::SetEvent(get_event());
}
}
bool locked()
{
return get_active_count()>=lock_flag_value;
}
private:
void* get_event()
{
void* current_event=::boost::detail::interlocked_read(&event);
if(!current_event)
{
void* const new_event=win32::create_anonymous_event(win32::auto_reset_event,win32::event_initially_reset);
void* const old_event=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&event,new_event,0);
if(old_event!=0)
{
win32::CloseHandle(new_event);
return old_event;
}
else
{
return new_event;
}
}
return current_event;
}
};
}
}
#define BOOST_BASIC_TIMED_MUTEX_INITIALIZER {0}
#endif

View File

@@ -1,229 +0,0 @@
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007 Anthony Williams
#ifndef CONDITION_HPP
#define CONDITION_HPP
#include "boost/config.hpp"
#include "boost/thread/mutex.hpp"
#include "boost/thread/win32/thread_primitives.hpp"
#include "boost/thread/win32/xtime.hpp"
#include "boost/thread/win32/xtime_utils.hpp"
#include <limits.h>
#include "boost/assert.hpp"
#include <algorithm>
namespace boost
{
template<typename lock_type>
class basic_condition
{
boost::mutex internal_mutex;
struct list_entry
{
detail::win32::handle semaphore;
long count;
bool notified;
};
BOOST_STATIC_CONSTANT(unsigned,generation_count=10);
list_entry generations[generation_count];
detail::win32::handle wake_sem;
static bool no_waiters(list_entry const& entry)
{
return entry.count==0;
}
void shift_generations_down()
{
if(std::remove_if(generations,generations+generation_count,no_waiters)==generations+generation_count)
{
broadcast_entry(generations[generation_count-1],false);
}
std::copy_backward(generations,generations+generation_count,generations+generation_count);
generations[0].semaphore=0;
generations[0].count=0;
generations[0].notified=false;
}
void broadcast_entry(list_entry& entry,bool wake)
{
if(wake)
{
detail::win32::ReleaseSemaphore(wake_sem,entry.count,NULL);
}
detail::win32::ReleaseSemaphore(entry.semaphore,entry.count,NULL);
entry.count=0;
dispose_entry(entry);
}
void dispose_entry(list_entry& entry)
{
BOOST_ASSERT(entry.count==0);
if(entry.semaphore)
{
unsigned long const close_result=detail::win32::CloseHandle(entry.semaphore);
BOOST_ASSERT(close_result);
}
entry.semaphore=0;
entry.notified=false;
}
detail::win32::handle duplicate_handle(detail::win32::handle source)
{
detail::win32::handle const current_process=detail::win32::GetCurrentProcess();
long const same_access_flag=2;
detail::win32::handle new_handle=0;
bool const success=detail::win32::DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
BOOST_ASSERT(success);
return new_handle;
}
bool do_wait(lock_type& lock,::boost::xtime const& target_time)
{
detail::win32::handle local_wake_sem;
detail::win32::handle sem;
bool first_loop=true;
bool woken=false;
while(!woken)
{
{
boost::mutex::scoped_lock internal_lock(internal_mutex);
if(first_loop)
{
lock.unlock();
if(!wake_sem)
{
wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
BOOST_ASSERT(wake_sem);
}
local_wake_sem=duplicate_handle(wake_sem);
if(generations[0].notified)
{
shift_generations_down();
}
if(!generations[0].semaphore)
{
generations[0].semaphore=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
BOOST_ASSERT(generations[0].semaphore);
}
first_loop=false;
}
++generations[0].count;
sem=duplicate_handle(generations[0].semaphore);
}
unsigned long const notified=detail::win32::WaitForSingleObject(sem,::boost::detail::get_milliseconds_until_time(target_time));
BOOST_ASSERT(notified==detail::win32::timeout || notified==0);
unsigned long const sem_close_result=detail::win32::CloseHandle(sem);
BOOST_ASSERT(sem_close_result);
if(notified==detail::win32::timeout)
{
break;
}
unsigned long const woken_result=detail::win32::WaitForSingleObject(local_wake_sem,0);
BOOST_ASSERT(woken_result==detail::win32::timeout || woken_result==0);
woken=(woken_result==0);
}
unsigned long const wake_sem_close_result=detail::win32::CloseHandle(local_wake_sem);
BOOST_ASSERT(wake_sem_close_result);
lock.lock();
return woken;
}
public:
basic_condition():
wake_sem(0)
{
for(unsigned i=0;i<generation_count;++i)
{
generations[i]=list_entry();
}
}
~basic_condition()
{
for(unsigned i=0;i<generation_count;++i)
{
dispose_entry(generations[i]);
}
detail::win32::CloseHandle(wake_sem);
}
void wait(lock_type& m)
{
do_wait(m,::boost::detail::get_xtime_sentinel());
}
template<typename predicate_type>
void wait(lock_type& m,predicate_type pred)
{
while(!pred()) wait(m);
}
bool timed_wait(lock_type& m,::boost::xtime const& target_time)
{
return do_wait(m,target_time);
}
template<typename predicate_type>
bool timed_wait(lock_type& m,::boost::xtime const& target_time,predicate_type pred)
{
while (!pred()) { if (!timed_wait(m, target_time)) return false; } return true;
}
void notify_one()
{
boost::mutex::scoped_lock internal_lock(internal_mutex);
if(wake_sem)
{
detail::win32::ReleaseSemaphore(wake_sem,1,NULL);
for(unsigned generation=generation_count;generation!=0;--generation)
{
list_entry& entry=generations[generation-1];
if(entry.count)
{
entry.notified=true;
detail::win32::ReleaseSemaphore(entry.semaphore,1,NULL);
if(!--entry.count)
{
dispose_entry(entry);
}
}
}
}
}
void notify_all()
{
boost::mutex::scoped_lock internal_lock(internal_mutex);
if(wake_sem)
{
for(unsigned generation=generation_count;generation!=0;--generation)
{
list_entry& entry=generations[generation-1];
if(entry.count)
{
broadcast_entry(entry,true);
}
}
}
}
};
typedef basic_condition<boost::mutex::scoped_lock> condition;
}
#endif

View File

@@ -1,77 +0,0 @@
// Copyright 2006 Roland Schwarz.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_THREAD_RS06041002_HPP
#define BOOST_THREAD_RS06041002_HPP
#include <boost/config.hpp>
// insist on threading support being available:
#include <boost/config/requires_threads.hpp>
#if defined(BOOST_THREAD_BUILD_DLL) //Build dll
#elif defined(BOOST_THREAD_BUILD_LIB) //Build lib
#elif defined(BOOST_THREAD_USE_DLL) //Use dll
#elif defined(BOOST_THREAD_USE_LIB) //Use lib
#else //Use default
# if defined(BOOST_HAS_WINTHREADS)
# if defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)
//For compilers supporting auto-tss cleanup
//with Boost.Threads lib, use Boost.Threads lib
# define BOOST_THREAD_USE_LIB
# else
//For compilers not yet supporting auto-tss cleanup
//with Boost.Threads lib, use Boost.Threads dll
# define BOOST_THREAD_USE_DLL
# endif
# else
# define BOOST_THREAD_USE_LIB
# endif
#endif
#if defined(BOOST_HAS_DECLSPEC)
# if defined(BOOST_THREAD_BUILD_DLL) //Build dll
# define BOOST_THREAD_DECL __declspec(dllexport)
# elif defined(BOOST_THREAD_USE_DLL) //Use dll
# define BOOST_THREAD_DECL __declspec(dllimport)
# else
# define BOOST_THREAD_DECL
# endif
#else
# define BOOST_THREAD_DECL
#endif // BOOST_HAS_DECLSPEC
//
// Automatically link to the correct build variant where possible.
//
#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_THREAD_NO_LIB) && !defined(BOOST_THREAD_BUILD_DLL) && !defined(BOOST_THREAD_BUILD_LIB)
//
// Tell the autolink to link dynamically, this will get undef'ed by auto_link.hpp
// once it's done with it:
//
#if defined(BOOST_THREAD_USE_DLL)
# define BOOST_DYN_LINK
#endif
//
// Set the name of our library, this will get undef'ed by auto_link.hpp
// once it's done with it:
//
#if defined(BOOST_THREAD_LIB_NAME)
# define BOOST_LIB_NAME BOOST_THREAD_LIB_NAME
#else
# define BOOST_LIB_NAME boost_thread
#endif
//
// If we're importing code from a dll, then tell auto_link.hpp about it:
//
// And include the header that does the work:
//
#include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
#endif // BOOST_THREAD_RS06041002_HPP

View File

@@ -1,91 +0,0 @@
// (C) Copyright 2005-6 Anthony Williams
// Copyright 2006 Roland Schwarz.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_THREAD_RS06041003_HPP
#define BOOST_THREAD_RS06041003_HPP
#include <boost/thread/win32/config.hpp>
#include <string>
#include <stdexcept>
namespace boost {
class BOOST_THREAD_DECL thread_exception : public std::exception
{
protected:
thread_exception();
thread_exception(int sys_err_code);
public:
~thread_exception() throw();
int native_error() const;
const char* message() const;
private:
int m_sys_err;
};
class BOOST_THREAD_DECL lock_error : public thread_exception
{
public:
lock_error();
lock_error(int sys_err_code);
~lock_error() throw();
virtual const char* what() const throw();
};
class BOOST_THREAD_DECL thread_resource_error : public thread_exception
{
public:
thread_resource_error();
thread_resource_error(int sys_err_code);
~thread_resource_error() throw();
virtual const char* what() const throw();
};
class BOOST_THREAD_DECL unsupported_thread_option : public thread_exception
{
public:
unsupported_thread_option();
unsupported_thread_option(int sys_err_code);
~unsupported_thread_option() throw();
virtual const char* what() const throw();
};
class BOOST_THREAD_DECL invalid_thread_argument : public thread_exception
{
public:
invalid_thread_argument();
invalid_thread_argument(int sys_err_code);
~invalid_thread_argument() throw();
virtual const char* what() const throw();
};
class BOOST_THREAD_DECL thread_permission_error : public thread_exception
{
public:
thread_permission_error();
thread_permission_error(int sys_err_code);
~thread_permission_error() throw();
virtual const char* what() const throw();
};
} // namespace boost
#endif // BOOST_THREAD_RS06041003_HPP

View File

@@ -1,36 +0,0 @@
#ifndef BOOST_THREAD_DETAIL_INTERLOCKED_READ_WIN32_HPP
#define BOOST_THREAD_DETAIL_INTERLOCKED_READ_WIN32_HPP
// interlocked_read_win32.hpp
//
// (C) Copyright 2005-7 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/detail/interlocked.hpp>
extern "C" void _ReadWriteBarrier(void);
#pragma intrinsic(_ReadWriteBarrier)
namespace boost
{
namespace detail
{
inline long interlocked_read_acquire(long volatile* x)
{
long const res=*x;
_ReadWriteBarrier();
return res;
}
inline void* interlocked_read_acquire(void* volatile* x)
{
void* const res=*x;
_ReadWriteBarrier();
return res;
}
}
}
#endif

View File

@@ -1,201 +0,0 @@
// Copyright 2006 Roland Schwarz.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_THREAD_RS06041005_HPP
#define BOOST_THREAD_RS06041005_HPP
#include <boost/thread/win32/config.hpp>
#include <boost/utility.hpp>
#include <boost/thread/win32/exceptions.hpp>
namespace boost {
struct xtime;
namespace detail { namespace thread {
template <typename Mutex>
class lock_ops : private noncopyable
{
private:
lock_ops() { }
public:
typedef typename Mutex::cv_state lock_state;
static void lock(Mutex& m)
{
m.do_lock();
}
static bool trylock(Mutex& m)
{
return m.do_trylock();
}
static bool timedlock(Mutex& m, const xtime& xt)
{
return m.do_timedlock(xt);
}
static void unlock(Mutex& m)
{
m.do_unlock();
}
static void lock(Mutex& m, lock_state& state)
{
m.do_lock(state);
}
static void unlock(Mutex& m, lock_state& state)
{
m.do_unlock(state);
}
};
template <typename Mutex>
class scoped_lock : private noncopyable
{
public:
typedef Mutex mutex_type;
explicit scoped_lock(Mutex& mx, bool initially_locked=true)
: m_mutex(mx), m_locked(false)
{
if (initially_locked) lock();
}
~scoped_lock()
{
if (m_locked) unlock();
}
void lock()
{
if (m_locked) throw lock_error();
lock_ops<Mutex>::lock(m_mutex);
m_locked = true;
}
void unlock()
{
if (!m_locked) throw lock_error();
lock_ops<Mutex>::unlock(m_mutex);
m_locked = false;
}
bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; }
private:
Mutex& m_mutex;
bool m_locked;
};
template <typename TryMutex>
class scoped_try_lock : private noncopyable
{
public:
typedef TryMutex mutex_type;
explicit scoped_try_lock(TryMutex& mx)
: m_mutex(mx), m_locked(false)
{
try_lock();
}
scoped_try_lock(TryMutex& mx, bool initially_locked)
: m_mutex(mx), m_locked(false)
{
if (initially_locked) lock();
}
~scoped_try_lock()
{
if (m_locked) unlock();
}
void lock()
{
if (m_locked) throw lock_error();
lock_ops<TryMutex>::lock(m_mutex);
m_locked = true;
}
bool try_lock()
{
if (m_locked) throw lock_error();
return (m_locked = lock_ops<TryMutex>::trylock(m_mutex));
}
void unlock()
{
if (!m_locked) throw lock_error();
lock_ops<TryMutex>::unlock(m_mutex);
m_locked = false;
}
bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; }
private:
TryMutex& m_mutex;
bool m_locked;
};
template <typename TimedMutex>
class scoped_timed_lock : private noncopyable
{
public:
typedef TimedMutex mutex_type;
scoped_timed_lock(TimedMutex& mx, const xtime& xt)
: m_mutex(mx), m_locked(false)
{
timed_lock(xt);
}
scoped_timed_lock(TimedMutex& mx, bool initially_locked)
: m_mutex(mx), m_locked(false)
{
if (initially_locked) lock();
}
~scoped_timed_lock()
{
if (m_locked) unlock();
}
void lock()
{
if (m_locked) throw lock_error();
lock_ops<TimedMutex>::lock(m_mutex);
m_locked = true;
}
bool try_lock()
{
if (m_locked) throw lock_error();
return (m_locked = lock_ops<TimedMutex>::trylock(m_mutex));
}
bool timed_lock(const xtime& xt)
{
if (m_locked) throw lock_error();
return (m_locked = lock_ops<TimedMutex>::timedlock(m_mutex, xt));
}
void unlock()
{
if (!m_locked) throw lock_error();
lock_ops<TimedMutex>::unlock(m_mutex);
m_locked = false;
}
bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; }
private:
TimedMutex& m_mutex;
bool m_locked;
};
} // namespace thread
} // namespace detail
} // namespace boost
#endif // BOOST_THREAD_RS06041005_HPP

View File

@@ -1,272 +0,0 @@
// (C) Copyright 2005-6 Anthony Williams
// Copyright 2006 Roland Schwarz.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_THREAD_RS06041004_HPP
#define BOOST_THREAD_RS06041004_HPP
#include <boost/thread/win32/config.hpp>
#include <boost/thread/win32/basic_timed_mutex.hpp>
#include <boost/utility.hpp>
#include <boost/thread/win32/lock.hpp>
#include <boost/thread/win32/xtime.hpp>
#include <boost/thread/win32/exceptions.hpp>
namespace boost
{
namespace detail
{
typedef ::boost::detail::basic_timed_mutex underlying_mutex;
}
class mutex:
noncopyable,
public ::boost::detail::underlying_mutex
{
public:
mutex()
{
initialize();
}
~mutex()
{
destroy();
}
class scoped_lock
{
protected:
mutex& m;
bool is_locked;
public:
scoped_lock(mutex& m_):
m(m_),is_locked(false)
{
lock();
}
scoped_lock(mutex& m_,bool do_lock):
m(m_),is_locked(false)
{
if(do_lock)
{
lock();
}
}
~scoped_lock()
{
if(locked())
{
m.unlock();
}
}
void lock()
{
if(locked())
{
throw boost::lock_error();
}
m.lock();
is_locked=true;
}
void unlock()
{
if(!locked())
{
throw boost::lock_error();
}
m.unlock();
is_locked=false;
}
operator void* () const
{
return is_locked?const_cast<void*>(static_cast<void const*>(this)):0;
}
bool locked() const
{
return is_locked;
}
};
};
class try_mutex:
noncopyable,
protected ::boost::detail::underlying_mutex
{
public:
try_mutex()
{
initialize();
}
~try_mutex()
{
destroy();
}
class scoped_try_lock
{
protected:
try_mutex& m;
bool is_locked;
public:
scoped_try_lock(try_mutex& m_):
m(m_),is_locked(false)
{
lock();
}
scoped_try_lock(try_mutex& m_,bool do_lock):
m(m_),is_locked(false)
{
if(do_lock)
{
lock();
}
}
~scoped_try_lock()
{
if(locked())
{
m.unlock();
}
}
void lock()
{
if(locked())
{
throw boost::lock_error();
}
m.lock();
is_locked=true;
}
bool try_lock()
{
if(locked())
{
throw boost::lock_error();
}
is_locked=m.try_lock();
return is_locked;
}
void unlock()
{
if(!locked())
{
throw boost::lock_error();
}
m.unlock();
is_locked=false;
}
operator void* () const
{
return is_locked?const_cast<void*>(static_cast<void const*>(this)):0;
}
bool locked() const
{
return is_locked;
}
};
typedef scoped_try_lock scoped_lock;
};
class timed_mutex:
noncopyable,
protected ::boost::detail::basic_timed_mutex
{
public:
timed_mutex()
{
initialize();
}
~timed_mutex()
{
destroy();
}
class scoped_timed_lock
{
protected:
timed_mutex& m;
bool is_locked;
public:
scoped_timed_lock(timed_mutex& m_):
m(m_),is_locked(false)
{
lock();
}
scoped_timed_lock(timed_mutex& m_,::boost::xtime const& target):
m(m_),is_locked(false)
{
timed_lock(target);
}
scoped_timed_lock(timed_mutex& m_,bool do_lock):
m(m_),is_locked(false)
{
if(do_lock)
{
lock();
}
}
~scoped_timed_lock()
{
if(locked())
{
m.unlock();
}
}
void lock()
{
if(locked())
{
throw boost::lock_error();
}
m.lock();
is_locked=true;
}
bool try_lock()
{
is_locked=m.try_lock();
return is_locked;
}
bool timed_lock(::boost::xtime const& target)
{
is_locked=m.timed_lock(target);
return is_locked;
}
void unlock()
{
if(!locked())
{
throw boost::lock_error();
}
m.unlock();
is_locked=false;
}
operator void* () const
{
return is_locked?const_cast<void*>(static_cast<void const*>(this)):0;
}
bool locked() const
{
return is_locked;
}
};
typedef scoped_timed_lock scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
};
}
#endif // BOOST_THREAD_RS06041004_HPP

View File

@@ -1,114 +0,0 @@
#ifndef BOOST_THREAD_WIN32_ONCE_HPP
#define BOOST_THREAD_WIN32_ONCE_HPP
// once.hpp
//
// (C) Copyright 2005-7 Anthony Williams
// (C) Copyright 2005 John Maddock
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <cstring>
#include <cstddef>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/detail/interlocked.hpp>
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/interlocked_read.hpp>
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std
{
using ::strlen;
using ::memcpy;
using ::ptrdiff_t;
}
#endif
namespace boost
{
typedef long once_flag;
#define BOOST_ONCE_INIT 0
namespace detail
{
struct win32_mutex_scoped_lock
{
void* const mutex_handle;
explicit win32_mutex_scoped_lock(void* mutex_handle_):
mutex_handle(mutex_handle_)
{
unsigned long const res=win32::WaitForSingleObject(mutex_handle,win32::infinite);
BOOST_ASSERT(!res);
}
~win32_mutex_scoped_lock()
{
bool const success=win32::ReleaseMutex(mutex_handle)!=0;
BOOST_ASSERT(success);
}
};
template <class I>
void int_to_string(I p, char* buf)
{
unsigned i=0;
for(; i < sizeof(I)*2; ++i)
{
buf[i] = 'A' + static_cast<char>((p >> (i*4)) & 0x0f);
}
buf[i] = 0;
}
unsigned const once_mutex_name_fixed_length=48;
unsigned const once_mutex_name_fixed_buffer_size=once_mutex_name_fixed_length+1;
unsigned const once_mutex_name_length=once_mutex_name_fixed_buffer_size+sizeof(void*)*2+sizeof(unsigned long)*2;
// create a named mutex. It doesn't really matter what this name is
// as long as it is unique both to this process, and to the address of "flag":
inline void* create_once_mutex(char (&mutex_name)[once_mutex_name_length],void* flag_address)
{
static const char fixed_mutex_name[]="{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
BOOST_STATIC_ASSERT(sizeof(fixed_mutex_name) == once_mutex_name_fixed_buffer_size);
std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name));
BOOST_ASSERT(sizeof(mutex_name) == std::strlen(mutex_name) + sizeof(void*)*2 + sizeof(unsigned long)*2 + 1);
BOOST_STATIC_ASSERT(sizeof(void*) == sizeof(std::ptrdiff_t));
detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address), mutex_name + once_mutex_name_fixed_length);
detail::int_to_string(win32::GetCurrentProcessId(), mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2);
BOOST_ASSERT(sizeof(mutex_name) == std::strlen(mutex_name) + 1);
return win32::CreateMutexA(NULL, 0, mutex_name);
}
}
template<typename Function>
void call_once(once_flag& flag,Function f)
{
// Try for a quick win: if the proceedure has already been called
// just skip through:
long const function_complete_flag_value=0xc15730e2;
if(::boost::detail::interlocked_read_acquire(&flag)!=function_complete_flag_value)
{
char mutex_name[::boost::detail::once_mutex_name_length];
void* const mutex_handle(::boost::detail::create_once_mutex(mutex_name,&flag));
BOOST_ASSERT(mutex_handle);
detail::win32::handle_manager const closer(mutex_handle);
detail::win32_mutex_scoped_lock const lock(mutex_handle);
if(flag!=function_complete_flag_value)
{
f();
BOOST_INTERLOCKED_EXCHANGE(&flag,function_complete_flag_value);
}
}
}
}
#endif

View File

@@ -1,528 +0,0 @@
#ifndef BOOST_THREAD_WIN32_READ_WRITE_MUTEX_HPP
#define BOOST_THREAD_WIN32_READ_WRITE_MUTEX_HPP
// (C) Copyright 2006 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/assert.hpp>
#include <boost/detail/interlocked.hpp>
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/interlocked_read.hpp>
#include <boost/static_assert.hpp>
#include <limits.h>
namespace boost
{
class read_write_mutex
{
private:
struct state_data
{
unsigned shared_count:10;
unsigned shared_waiting:10;
unsigned exclusive:1;
unsigned upgradeable:1;
unsigned exclusive_waiting:9;
unsigned exclusive_waiting_blocked:1;
friend bool operator==(state_data const& lhs,state_data const& rhs)
{
return *reinterpret_cast<unsigned const*>(&lhs)==*reinterpret_cast<unsigned const*>(&rhs);
}
};
template<typename T>
T interlocked_compare_exchange(T* target,T new_value,T comparand)
{
BOOST_STATIC_ASSERT(sizeof(T)==sizeof(long));
long const res=BOOST_INTERLOCKED_COMPARE_EXCHANGE(reinterpret_cast<long*>(target),
*reinterpret_cast<long*>(&new_value),
*reinterpret_cast<long*>(&comparand));
return *reinterpret_cast<T const*>(&res);
}
state_data state;
void* semaphores[2];
void* &unlock_sem;
void* &exclusive_sem;
void* upgradeable_sem;
void release_waiters(state_data old_state)
{
if(old_state.exclusive_waiting)
{
bool const success=detail::win32::ReleaseSemaphore(exclusive_sem,1,NULL)!=0;
BOOST_ASSERT(success);
}
if(old_state.shared_waiting || old_state.exclusive_waiting)
{
bool const success=detail::win32::ReleaseSemaphore(unlock_sem,old_state.shared_waiting + (old_state.exclusive_waiting?1:0),NULL)!=0;
BOOST_ASSERT(success);
}
}
public:
read_write_mutex():
unlock_sem(semaphores[0]),
exclusive_sem(semaphores[1])
{
unlock_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
exclusive_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
upgradeable_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
state_data state_={0};
state=state_;
}
~read_write_mutex()
{
detail::win32::CloseHandle(upgradeable_sem);
detail::win32::CloseHandle(unlock_sem);
detail::win32::CloseHandle(exclusive_sem);
}
bool try_lock_shareable()
{
state_data old_state=state;
do
{
state_data new_state=old_state;
if(!new_state.exclusive && !new_state.exclusive_waiting_blocked)
{
++new_state.shared_count;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
while(true);
return !(old_state.exclusive| old_state.exclusive_waiting_blocked);
}
void lock_shareable()
{
while(true)
{
state_data old_state=state;
do
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
{
++new_state.shared_waiting;
}
else
{
++new_state.shared_count;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
while(true);
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
return;
}
unsigned long const res=detail::win32::WaitForSingleObject(unlock_sem,detail::win32::infinite);
BOOST_ASSERT(res==0);
}
}
void unlock_shareable()
{
state_data old_state=state;
do
{
state_data new_state=old_state;
bool const last_reader=!--new_state.shared_count;
if(last_reader)
{
if(new_state.upgradeable)
{
new_state.upgradeable=false;
new_state.exclusive=true;
}
else
{
if(new_state.exclusive_waiting)
{
--new_state.exclusive_waiting;
new_state.exclusive_waiting_blocked=false;
}
new_state.shared_waiting=0;
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
if(last_reader)
{
if(old_state.upgradeable)
{
bool const success=detail::win32::ReleaseSemaphore(upgradeable_sem,1,NULL)!=0;
BOOST_ASSERT(success);
}
else
{
release_waiters(old_state);
}
}
break;
}
old_state=current_state;
}
while(true);
}
void lock()
{
while(true)
{
state_data old_state=state;
do
{
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
++new_state.exclusive_waiting;
new_state.exclusive_waiting_blocked=true;
}
else
{
new_state.exclusive=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
while(true);
if(!old_state.shared_count && !old_state.exclusive)
{
break;
}
bool const success2=detail::win32::WaitForMultipleObjects(2,semaphores,true,detail::win32::infinite)<2;
BOOST_ASSERT(success2);
}
}
void unlock()
{
state_data old_state=state;
do
{
state_data new_state=old_state;
new_state.exclusive=false;
if(new_state.exclusive_waiting)
{
--new_state.exclusive_waiting;
new_state.exclusive_waiting_blocked=false;
}
new_state.shared_waiting=0;
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
while(true);
release_waiters(old_state);
}
void lock_upgradeable()
{
while(true)
{
state_data old_state=state;
do
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgradeable)
{
++new_state.shared_waiting;
}
else
{
++new_state.shared_count;
new_state.upgradeable=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
while(true);
if(!(old_state.exclusive|| old_state.exclusive_waiting_blocked|| old_state.upgradeable))
{
return;
}
unsigned long const res=detail::win32::WaitForSingleObject(unlock_sem,detail::win32::infinite);
BOOST_ASSERT(res==0);
}
}
void unlock_upgradeable()
{
state_data old_state=state;
do
{
state_data new_state=old_state;
new_state.upgradeable=false;
bool const last_reader=!--new_state.shared_count;
if(last_reader)
{
if(new_state.exclusive_waiting)
{
--new_state.exclusive_waiting;
new_state.exclusive_waiting_blocked=false;
}
new_state.shared_waiting=0;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
if(last_reader)
{
release_waiters(old_state);
}
break;
}
old_state=current_state;
}
while(true);
}
void unlock_upgradeable_and_lock()
{
state_data old_state=state;
do
{
state_data new_state=old_state;
bool const last_reader=!--new_state.shared_count;
if(last_reader)
{
new_state.upgradeable=false;
new_state.exclusive=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
if(!last_reader)
{
unsigned long const res=detail::win32::WaitForSingleObject(upgradeable_sem,detail::win32::infinite);
BOOST_ASSERT(res==0);
}
break;
}
old_state=current_state;
}
while(true);
}
void unlock_and_lock_upgradeable()
{
state_data old_state=state;
do
{
state_data new_state=old_state;
new_state.exclusive=false;
new_state.upgradeable=true;
++new_state.shared_count;
if(new_state.exclusive_waiting)
{
--new_state.exclusive_waiting;
new_state.exclusive_waiting_blocked=false;
}
new_state.shared_waiting=0;
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
while(true);
release_waiters(old_state);
}
void unlock_and_lock_shareable()
{
state_data old_state=state;
do
{
state_data new_state=old_state;
new_state.exclusive=false;
++new_state.shared_count;
if(new_state.exclusive_waiting)
{
--new_state.exclusive_waiting;
new_state.exclusive_waiting_blocked=false;
}
new_state.shared_waiting=0;
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
while(true);
release_waiters(old_state);
}
void unlock_upgradeable_and_lock_shareable()
{
state_data old_state=state;
do
{
state_data new_state=old_state;
new_state.upgradeable=false;
if(new_state.exclusive_waiting)
{
--new_state.exclusive_waiting;
new_state.exclusive_waiting_blocked=false;
}
new_state.shared_waiting=0;
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
while(true);
release_waiters(old_state);
}
class scoped_read_lock
{
read_write_mutex& m;
public:
scoped_read_lock(read_write_mutex& m_):
m(m_)
{
m.lock_shareable();
}
~scoped_read_lock()
{
m.unlock_shareable();
}
};
class scoped_write_lock
{
read_write_mutex& m;
bool locked;
public:
scoped_write_lock(read_write_mutex& m_):
m(m_),locked(false)
{
lock();
}
void lock()
{
m.lock();
locked=true;
}
void unlock()
{
m.unlock();
locked=false;
}
~scoped_write_lock()
{
if(locked)
{
unlock();
}
}
};
class scoped_upgradeable_lock
{
read_write_mutex& m;
bool locked;
bool upgraded;
public:
scoped_upgradeable_lock(read_write_mutex& m_):
m(m_),
locked(false),upgraded(false)
{
lock();
}
void lock()
{
m.lock_upgradeable();
locked=true;
}
void upgrade()
{
m.unlock_upgradeable_and_lock();
upgraded=true;
}
void unlock()
{
if(upgraded)
{
m.unlock();
}
else
{
m.unlock_upgradeable();
}
}
~scoped_upgradeable_lock()
{
if(locked)
{
unlock();
}
}
};
};
}
#endif

View File

@@ -1,263 +0,0 @@
#ifndef BOOST_RECURSIVE_MUTEX_WIN32_HPP
#define BOOST_RECURSIVE_MUTEX_WIN32_HPP
// recursive_mutex.hpp
//
// (C) Copyright 2006 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/win32/basic_recursive_mutex.hpp>
#include <boost/utility.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/thread/exceptions.hpp>
namespace boost
{
class recursive_mutex:
noncopyable,
protected ::boost::detail::basic_recursive_mutex
{
public:
recursive_mutex()
{
::boost::detail::basic_recursive_mutex::initialize();
}
~recursive_mutex()
{
::boost::detail::basic_recursive_mutex::destroy();
}
class scoped_lock
{
protected:
recursive_mutex& m;
bool is_locked;
public:
scoped_lock(recursive_mutex& m_):
m(m_),is_locked(false)
{
lock();
}
scoped_lock(recursive_mutex& m_,bool do_lock):
m(m_),is_locked(false)
{
if(do_lock)
{
lock();
}
}
~scoped_lock()
{
if(locked())
{
m.unlock();
}
}
void lock()
{
if(locked())
{
throw boost::lock_error();
}
m.lock();
is_locked=true;
}
void unlock()
{
if(!locked())
{
throw boost::lock_error();
}
m.unlock();
is_locked=false;
}
operator void* () const
{
return is_locked?const_cast<void*>(static_cast<void const*>(this)):0;
}
bool locked() const
{
return is_locked;
}
};
};
class recursive_try_mutex:
noncopyable,
protected ::boost::detail::basic_recursive_mutex
{
public:
recursive_try_mutex()
{
::boost::detail::basic_recursive_mutex::initialize();
}
~recursive_try_mutex()
{
::boost::detail::basic_recursive_mutex::destroy();
}
class scoped_try_lock
{
protected:
recursive_try_mutex& m;
bool is_locked;
public:
scoped_try_lock(recursive_try_mutex& m_):
m(m_),is_locked(false)
{
lock();
}
scoped_try_lock(recursive_try_mutex& m_,bool do_lock):
m(m_),is_locked(false)
{
if(do_lock)
{
lock();
}
}
~scoped_try_lock()
{
if(locked())
{
m.unlock();
}
}
void lock()
{
if(locked())
{
throw boost::lock_error();
}
m.lock();
is_locked=true;
}
bool try_lock()
{
if(locked())
{
throw boost::lock_error();
}
is_locked=m.try_lock();
return is_locked;
}
void unlock()
{
if(!locked())
{
throw boost::lock_error();
}
m.unlock();
is_locked=false;
}
operator void* () const
{
return is_locked?const_cast<void*>(static_cast<void const*>(this)):0;
}
bool locked() const
{
return is_locked;
}
};
typedef scoped_try_lock scoped_lock;
};
class recursive_timed_mutex:
noncopyable,
protected ::boost::detail::basic_recursive_timed_mutex
{
public:
recursive_timed_mutex()
{
::boost::detail::basic_recursive_timed_mutex::initialize();
}
~recursive_timed_mutex()
{
::boost::detail::basic_recursive_timed_mutex::destroy();
}
class scoped_timed_lock
{
protected:
recursive_timed_mutex& m;
bool is_locked;
public:
scoped_timed_lock(recursive_timed_mutex& m_):
m(m_),is_locked(false)
{
lock();
}
scoped_timed_lock(recursive_timed_mutex& m_,::boost::xtime const& target):
m(m_),is_locked(false)
{
timed_lock(target);
}
scoped_timed_lock(recursive_timed_mutex& m_,bool do_lock):
m(m_),is_locked(false)
{
if(do_lock)
{
lock();
}
}
~scoped_timed_lock()
{
if(locked())
{
m.unlock();
}
}
void lock()
{
if(locked())
{
throw boost::lock_error();
}
m.lock();
is_locked=true;
}
bool try_lock()
{
is_locked=m.try_lock();
return is_locked;
}
bool timed_lock(::boost::xtime const& target)
{
is_locked=m.timed_lock(target);
return is_locked;
}
void unlock()
{
if(!locked())
{
throw boost::lock_error();
}
m.unlock();
is_locked=false;
}
operator void* () const
{
return is_locked?const_cast<void*>(static_cast<void const*>(this)):0;
}
bool locked() const
{
return is_locked;
}
};
typedef scoped_timed_lock scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
};
}
#endif

View File

@@ -1,77 +0,0 @@
// Copyright 2006 Roland Schwarz.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_THREAD_RS06041007_HPP
#define BOOST_THREAD_RS06041007_HPP
#include <boost/thread/win32/config.hpp>
#include <boost/utility.hpp>
#include <boost/function.hpp>
#include <boost/thread/win32/mutex.hpp>
#include <list>
#include <memory>
namespace boost {
struct xtime;
// disable warnings about non dll import
// see: http://www.boost.org/more/separate_compilation.html#dlls
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4251 4231 4660 4275)
#endif
class BOOST_THREAD_DECL thread : private noncopyable
{
public:
thread();
explicit thread(const function0<void>& threadfunc);
~thread();
bool operator==(const thread& other) const;
bool operator!=(const thread& other) const;
void join();
static void sleep(const xtime& xt);
static void yield();
private:
void* m_thread;
unsigned int m_id;
bool m_joinable;
};
class BOOST_THREAD_DECL thread_group : private noncopyable
{
public:
thread_group();
~thread_group();
thread* create_thread(const function0<void>& threadfunc);
void add_thread(thread* thrd);
void remove_thread(thread* thrd);
void join_all();
int size();
private:
std::list<thread*> m_threads;
mutex m_mutex;
};
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
} // namespace boost
#endif // BOOST_THREAD_RS06041007_HPP

View File

@@ -1,198 +0,0 @@
#ifndef BOOST_WIN32_THREAD_PRIMITIVES_HPP
#define BOOST_WIN32_THREAD_PRIMITIVES_HPP
// win32_thread_primitives.hpp
//
// (C) Copyright 2005-6 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/thread/exceptions.hpp>
#if defined( BOOST_USE_WINDOWS_H )
# include <windows.h>
namespace boost
{
namespace detail
{
namespace win32
{
typedef ULONG_PTR ulong_ptr;
typedef HANDLE handle;
unsigned const infinite=INFINITE;
unsigned const timeout=WAIT_TIMEOUT;
using ::CreateMutexA;
using ::CreateEventA;
using ::CreateSemaphoreA;
using ::CloseHandle;
using ::ReleaseMutex;
using ::ReleaseSemaphore;
using ::SetEvent;
using ::ResetEvent;
using ::WaitForMultipleObjects;
using ::WaitForSingleObject;
using ::GetCurrentProcessId;
using ::GetCurrentThreadId;
using ::GetCurrentThread;
using ::GetCurrentProcess;
using ::DuplicateHandle;
using ::SleepEx;
using ::QueueUserAPC;
}
}
}
#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
namespace boost
{
namespace detail
{
namespace win32
{
# ifdef _WIN64
typedef unsigned __int64 ulong_ptr;
# else
typedef unsigned long ulong_ptr;
# endif
typedef void* handle;
unsigned const infinite=~0U;
unsigned const timeout=258U;
extern "C"
{
struct _SECURITY_ATTRIBUTES;
__declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*);
__declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*);
__declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*);
__declspec(dllimport) int __stdcall CloseHandle(void*);
__declspec(dllimport) int __stdcall ReleaseMutex(void*);
__declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
__declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
__declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void*,unsigned long);
__declspec(dllimport) int __stdcall ReleaseSemaphore(void*,long,long*);
__declspec(dllimport) void* __stdcall GetCurrentThread();
__declspec(dllimport) void* __stdcall GetCurrentProcess();
__declspec(dllimport) int __stdcall DuplicateHandle(void*,void*,void*,void**,unsigned long,int,unsigned long);
__declspec(dllimport) unsigned long __stdcall SleepEx(unsigned long,int);
typedef void (__stdcall *queue_user_apc_callback_function)(ulong_ptr);
__declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr);
__declspec(dllimport) int __stdcall SetEvent(void*);
__declspec(dllimport) int __stdcall ResetEvent(void*);
__declspec(dllimport) unsigned long __stdcall WaitForMultipleObjects(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds);
}
}
}
}
#else
# error "Win32 functions not available"
#endif
namespace boost
{
namespace detail
{
namespace win32
{
enum event_type
{
auto_reset_event=false,
manual_reset_event=true
};
enum initial_event_state
{
event_initially_reset=false,
event_initially_set=true
};
inline handle create_anonymous_event(event_type type,initial_event_state state)
{
handle const res=CreateEventA(0,type,state,0);
return res?res:throw thread_resource_error();
}
inline handle create_anonymous_semaphore(long initial_count,long max_count)
{
handle const res=CreateSemaphoreA(NULL,initial_count,max_count,NULL);
return res?res:throw thread_resource_error();
}
inline handle duplicate_handle(handle source)
{
handle const current_process=GetCurrentProcess();
long const same_access_flag=2;
handle new_handle=0;
bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
return success?new_handle:throw thread_resource_error();
}
inline void release_semaphore(handle semaphore,long count)
{
bool const success=ReleaseSemaphore(semaphore,count,0)!=0;
BOOST_ASSERT(success);
}
class handle_manager
{
private:
handle handle_to_manage;
handle_manager(handle_manager&);
handle_manager& operator=(handle_manager&);
void cleanup()
{
if(handle_to_manage)
{
unsigned long result=CloseHandle(handle_to_manage);
BOOST_ASSERT(result);
}
}
public:
explicit handle_manager(handle handle_to_manage_):
handle_to_manage(handle_to_manage_)
{}
handle_manager():
handle_to_manage(0)
{}
handle_manager& operator=(handle new_handle)
{
cleanup();
handle_to_manage=new_handle;
}
operator handle() const
{
return handle_to_manage;
}
handle release()
{
handle const res=handle_to_manage;
handle_to_manage=0;
return res;
}
bool operator!() const
{
return !handle_to_manage;
}
~handle_manager()
{
cleanup();
}
};
}
}
}
#endif

View File

@@ -1,106 +0,0 @@
// Copyright (C) 2001-2003 William E. Kempf
// Copyright (C) 2006 Roland Schwarz
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_TSS_RS06092305_HPP
#define BOOST_TSS_RS06092305_HPP
#include <boost/thread/win32/config.hpp>
#include <boost/utility.hpp>
#include <boost/function.hpp>
#include <boost/thread/win32/exceptions.hpp>
namespace boost {
// disable warnings about non dll import
// see: http://www.boost.org/more/separate_compilation.html#dlls
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4251 4231 4660 4275)
#endif
namespace detail {
class BOOST_THREAD_DECL tss : private noncopyable
{
public:
tss(boost::function1<void, void*>* pcleanup) {
if (pcleanup == 0) throw boost::thread_resource_error();
try
{
init(pcleanup);
}
catch (...)
{
delete pcleanup;
throw boost::thread_resource_error();
}
}
void* get() const;
void set(void* value);
void cleanup(void* p);
private:
unsigned int m_slot; //This is a "pseudo-slot", not a native slot
void init(boost::function1<void, void*>* pcleanup);
};
template <typename T>
struct tss_adapter
{
template <typename F>
tss_adapter(const F& cleanup) : m_cleanup(cleanup) { }
void operator()(void* p) { m_cleanup(static_cast<T*>(p)); }
boost::function1<void, T*> m_cleanup;
};
} // namespace detail
template <typename T>
class thread_specific_ptr : private noncopyable
{
public:
thread_specific_ptr()
: m_tss(new boost::function1<void, void*>(
boost::detail::tss_adapter<T>(
&thread_specific_ptr<T>::cleanup)))
{
}
thread_specific_ptr(void (*clean)(T*))
: m_tss(new boost::function1<void, void*>(
boost::detail::tss_adapter<T>(clean)))
{
}
~thread_specific_ptr() { reset(); }
T* get() const { return static_cast<T*>(m_tss.get()); }
T* operator->() const { return get(); }
T& operator*() const { return *get(); }
T* release() { T* temp = get(); if (temp) m_tss.set(0); return temp; }
void reset(T* p=0)
{
T* cur = get();
if (cur == p) return;
m_tss.set(p);
if (cur) m_tss.cleanup(cur);
}
private:
static void cleanup(T* p) { delete p; }
detail::tss m_tss;
};
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
} // namespace boost
#endif //BOOST_TSS_RS06092305_HPP

View File

@@ -1,56 +0,0 @@
// Copyright 2006 Roland Schwarz.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_THREAD_RS06041006_HPP
#define BOOST_THREAD_RS06041006_HPP
#include <boost/thread/win32/config.hpp>
#include <boost/cstdint.hpp>
namespace boost {
enum xtime_clock_types
{
TIME_UTC=1
// TIME_TAI,
// TIME_MONOTONIC,
// TIME_PROCESS,
// TIME_THREAD,
// TIME_LOCAL,
// TIME_SYNC,
// TIME_RESOLUTION
};
struct xtime
{
#if defined(BOOST_NO_INT64_T)
typedef int_fast32_t xtime_sec_t; //INT_FAST32_MIN <= sec <= INT_FAST32_MAX
#else
typedef int_fast64_t xtime_sec_t; //INT_FAST64_MIN <= sec <= INT_FAST64_MAX
#endif
typedef int_fast32_t xtime_nsec_t; //0 <= xtime.nsec < NANOSECONDS_PER_SECOND
xtime_sec_t sec;
xtime_nsec_t nsec;
};
int BOOST_THREAD_DECL xtime_get(struct xtime* xtp, int clock_type);
inline int xtime_cmp(const xtime& xt1, const xtime& xt2)
{
if (xt1.sec == xt2.sec)
return (int)(xt1.nsec - xt2.nsec);
else
return (xt1.sec > xt2.sec) ? 1 : -1;
}
} // namespace boost
#endif //BOOST_THREAD_RS06041006_HPP

View File

@@ -1,85 +0,0 @@
#ifndef BOOST_THREAD_DETAIL_XTIME_UTILS_HPP
#define BOOST_THREAD_DETAIL_XTIME_UTILS_HPP
// xtime_utils.hpp
//
// (C) Copyright 2005 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/win32/xtime.hpp>
#include <limits>
namespace boost
{
namespace detail
{
inline ::boost::xtime get_xtime_sentinel()
{
boost::xtime const sentinel={
(std::numeric_limits<boost::xtime::xtime_sec_t>::max)(),
(std::numeric_limits<boost::xtime::xtime_nsec_t>::max)()
};
return sentinel;
}
// get the number of milliseconds from now to target
// if target is in the past, return 0
// if target cannot be represented as unsigned long, return
// the maximum instead
// 2006-08-04 <roland>
inline unsigned long get_milliseconds_until_time(::boost::xtime target)
{
if(!boost::xtime_cmp(target,get_xtime_sentinel()))
{
return (std::numeric_limits<unsigned long>::max)();
}
boost::xtime now;
boost::xtime_get(&now, boost::TIME_UTC);
if (target.sec < now.sec)
{
return 0;
}
else
{
boost::xtime::xtime_nsec_t const nanoseconds_per_second=1000000000;
boost::xtime::xtime_nsec_t const milliseconds_per_second=1000;
boost::xtime::xtime_nsec_t const nanoseconds_per_millisecond=nanoseconds_per_second/milliseconds_per_second;
if (target.nsec < now.nsec)
{
if (target.sec == now.sec)
{
return 0;
}
target.nsec += nanoseconds_per_second - now.nsec;
target.sec -= now.sec + 1;
}
else
{
target.nsec -= now.nsec;
target.sec -= now.sec;
}
// we are throwing away some bits, but one second after having
// waited for 49 years does not really matter ...
if (target.sec < (std::numeric_limits<unsigned long>::max)()/milliseconds_per_second)
{
return static_cast<unsigned long>(
target.sec*milliseconds_per_second +
(target.nsec+nanoseconds_per_millisecond/2)/nanoseconds_per_millisecond);
}
else
{
return (std::numeric_limits<unsigned long>::max)();
}
}
}
}
}
#endif

View File

@@ -1,16 +1,59 @@
// 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)
// Copyright (C) 2001-2003
// William E. Kempf
//
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#ifndef BOOST_THREAD_RS06040712_HPP
#define BOOST_THREAD_RS06040712_HPP
#ifndef BOOST_XTIME_WEK070601_HPP
#define BOOST_XTIME_WEK070601_HPP
#include <boost/thread/detail/platform.hpp>
#include BOOST_THREAD_PLATFORM(xtime.hpp)
#include <boost/thread/detail/config.hpp>
#endif // BOOST_THREAD_RS06040712_HPP
#include <boost/cstdint.hpp>
namespace boost {
enum xtime_clock_types
{
TIME_UTC=1
// TIME_TAI,
// TIME_MONOTONIC,
// TIME_PROCESS,
// TIME_THREAD,
// TIME_LOCAL,
// TIME_SYNC,
// TIME_RESOLUTION
};
struct xtime
{
#if defined(BOOST_NO_INT64_T)
typedef int_fast32_t xtime_sec_t; //INT_FAST32_MIN <= sec <= INT_FAST32_MAX
#else
typedef int_fast64_t xtime_sec_t; //INT_FAST64_MIN <= sec <= INT_FAST64_MAX
#endif
typedef int_fast32_t xtime_nsec_t; //0 <= xtime.nsec < NANOSECONDS_PER_SECOND
xtime_sec_t sec;
xtime_nsec_t nsec;
};
int BOOST_THREAD_DECL xtime_get(struct xtime* xtp, int clock_type);
inline int xtime_cmp(const xtime& xt1, const xtime& xt2)
{
if (xt1.sec == xt2.sec)
return (int)(xt1.nsec - xt2.nsec);
else
return (xt1.sec > xt2.sec) ? 1 : -1;
}
} // namespace boost
#endif //BOOST_XTIME_WEK070601_HPP

View File

@@ -1,8 +1,8 @@
<html>
<head>
<meta http-equiv="refresh" content="0; URL=doc/index.html">
<meta http-equiv="refresh" content="0; URL=../../doc/html/threads.html">
</head>
<body>
Automatic redirection failed, please go to <a href="doc/index.html">doc/index.html</a>
Automatic redirection failed, please go to <a href="../../doc/html/threads.html">../../doc/html/threads.html</a>
</body>
</html>

47
src/barrier.cpp Normal file
View File

@@ -0,0 +1,47 @@
// 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

677
src/condition.cpp Normal file
View File

@@ -0,0 +1,677 @@
// 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,13 +1,17 @@
// 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)
// Copyright (C) 2001-2003
// William E. Kempf
//
// This work is a reimplementation along the design and ideas
// of 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/win32/config.hpp>
#include <boost/thread/win32/exceptions.hpp>
#include <boost/thread/detail/config.hpp>
#include <boost/thread/exceptions.hpp>
#include <cstring>
#include <string>
@@ -15,7 +19,20 @@
namespace std { using ::strerror; }
# endif
#include "windows.h"
// BOOST_POSIX or BOOST_WINDOWS specify which API to use.
# if !defined( BOOST_WINDOWS ) && !defined( BOOST_POSIX )
# if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)
# define BOOST_WINDOWS
# else
# define BOOST_POSIX
# endif
# endif
# if defined( BOOST_WINDOWS )
# include "windows.h"
# else
# include <errno.h> // for POSIX error codes
# endif
namespace
{
@@ -23,6 +40,7 @@ namespace
std::string system_message(int sys_err_code)
{
std::string str;
# ifdef BOOST_WINDOWS
LPVOID lpMsgBuf;
::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
@@ -40,6 +58,9 @@ std::string system_message(int sys_err_code)
{
str.erase(str.size()-1);
}
# else
str += std::strerror(errno);
# endif
return str;
}

8
src/mac/debug_prefix.hpp Normal file
View File

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

66
src/mac/delivery_man.cpp Normal file
View File

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

84
src/mac/delivery_man.hpp Normal file
View File

@@ -0,0 +1,84 @@
// (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

93
src/mac/dt_scheduler.cpp Normal file
View File

@@ -0,0 +1,93 @@
// (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

63
src/mac/dt_scheduler.hpp Normal file
View File

@@ -0,0 +1,63 @@
// (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

@@ -0,0 +1,60 @@
// (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

@@ -0,0 +1,47 @@
// (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

58
src/mac/init.cpp Normal file
View File

@@ -0,0 +1,58 @@
// (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

34
src/mac/init.hpp Normal file
View File

@@ -0,0 +1,34 @@
// (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

@@ -0,0 +1,24 @@
// (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

@@ -0,0 +1,128 @@
// (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);
}

View File

@@ -0,0 +1,52 @@
// (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 <cstdlib>
#include <Multiprocessing.h>
//
// using declarations
//
using std::size_t;
extern "C" {
//
// prototypes
//
void *malloc(size_t ulSize);
void free(void *pBlock);
}
//
// MSL function replacements
//
// all allocation/deallocation currently goes through MPAllocateAligned/MPFree. This
// solution is sub-optimal at best, but will have to do for now.
void *malloc(size_t ulSize)
{
static bool bIgnored = MPLibraryIsLoaded();
return(MPAllocateAligned(ulSize, kMPAllocateDefaultAligned, 0UL));
}
void free(void *pBlock)
{
if(pBlock == NULL) return;
MPFree(pBlock);
}

View File

@@ -0,0 +1,99 @@
// (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 <new>
#include <Multiprocessing.h>
//
// using declarations
//
using std::size_t;
using std::bad_alloc;
using std::nothrow_t;
using std::nothrow;
//
// local utility functions
//
// all allocation/deallocation currently goes through MPAllocateAligned/MPFree. This
// solution is sub-optimal at best, but will have to do for now.
inline static void *allocate(size_t ulSize, const nothrow_t &)
{
static bool bIgnored = MPLibraryIsLoaded();
return(MPAllocateAligned(ulSize, kMPAllocateDefaultAligned, 0UL));
}
inline static void *allocate(size_t ulSize)
{
void *pBlock = allocate(ulSize, nothrow);
if(pBlock == NULL)
throw(bad_alloc());
return(pBlock);
}
inline static void deallocate(void *pBlock)
{
if(pBlock == NULL) return;
MPFree(pBlock);
}
//
// global operators
//
void *operator new(size_t ulSize)
{
return(allocate(ulSize));
}
void *operator new[](size_t ulSize)
{
return(allocate(ulSize));
}
void *operator new(size_t ulSize, const nothrow_t &rNoThrow)
{
return(allocate(ulSize, rNoThrow));
}
void *operator new[](size_t ulSize, const nothrow_t &rNoThrow)
{
return(allocate(ulSize, rNoThrow));
}
void operator delete(void *pBlock)
{
deallocate(pBlock);
}
void operator delete[](void *pBlock)
{
deallocate(pBlock);
}
void operator delete(void *pBlock, const nothrow_t &)
{
deallocate(pBlock);
}
void operator delete[](void *pBlock, const nothrow_t &)
{
deallocate(pBlock);
}

View File

@@ -0,0 +1,150 @@
// (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>
// we include timesize.mac.h to get whether or not __TIMESIZE_DOUBLE__ is
// defined. This is not safe, given that __TIMESIZE_DOUBLE__ affects MSL
// at MSL's compile time, not ours, so be forgiving if you have changed it
// since you have built MSL.
#include <timesize.mac.h>
#include <time.h>
#include <boost/thread/detail/force_cast.hpp>
#include <boost/thread/xtime.hpp>
#include "execution_context.hpp"
#include <DriverServices.h>
extern "C"
{
clock_t __get_clock();
time_t __get_time();
int __to_gm_time(time_t *pTime);
int __is_dst();
}
static inline uint64_t get_nanoseconds()
{
using boost::detail::thread::force_cast;
return(force_cast<uint64_t>(AbsoluteToNanoseconds(UpTime())));
}
#ifdef __TIMESIZE_DOUBLE__
// return number of microseconds since startup as a double
clock_t __get_clock()
{
static const double k_dNanosecondsPerMicrosecond(1000.0);
return(get_nanoseconds() / k_dNanosecondsPerMicrosecond);
}
#else
// return number of ticks (60th of a second) since startup as a long
clock_t __get_clock()
{
static const uint64_t k_ullTicksPerSecond(60ULL);
static const uint64_t k_ullNanosecondsPerSecond(1000ULL * 1000ULL * 1000ULL);
static const uint64_t k_ullNanosecondsPerTick(k_ullNanosecondsPerSecond / k_ullTicksPerSecond);
return(get_nanoseconds() / k_ullNanosecondsPerTick);
}
#endif
// return number of seconds elapsed since Jan 1, 1970
time_t __get_time()
{
boost::xtime sTime;
int nType = boost::xtime_get(&sTime, boost::TIME_UTC);
assert(nType == boost::TIME_UTC);
return(static_cast<time_t>(sTime.sec));
}
static inline MachineLocation &read_location()
{
static MachineLocation s_sLocation;
assert(boost::threads::mac::at_st());
ReadLocation(&s_sLocation);
return(s_sLocation);
}
static inline MachineLocation &get_location()
{
static MachineLocation &s_rLocation(read_location());
return(s_rLocation);
}
// force the machine location to be cached at static initlialization
static MachineLocation &g_rIgnored(get_location());
static inline long calculate_delta()
{
MachineLocation &rLocation(get_location());
// gmtDelta is a 24-bit, signed integer. We need to strip out the lower 24 bits,
// then sign-extend what we have.
long lDelta = rLocation.u.gmtDelta & 0x00ffffffL;
if((lDelta & 0x00800000L) != 0L)
{
lDelta |= 0xFF000000;
}
return(lDelta);
}
static inline bool check_if_location_is_broken()
{
MachineLocation &rLocation(get_location());
if(rLocation.latitude == 0 && rLocation.longitude == 0 && rLocation.u.gmtDelta == 0)
return(true);
return(false);
}
static inline bool location_is_broken()
{
static bool s_bLocationIsBroken(check_if_location_is_broken());
return(s_bLocationIsBroken);
}
// translate time to GMT
int __to_gm_time(time_t *pTime)
{
if(location_is_broken())
{
return(0);
}
static long s_lDelta(calculate_delta());
*pTime -= s_lDelta;
return(1);
}
static inline bool is_daylight_savings_time()
{
MachineLocation &rLocation(get_location());
return(rLocation.u.dlsDelta != 0);
}
// check if we're in daylight savings time
int __is_dst()
{
if(location_is_broken())
{
return(-1);
}
static bool bIsDaylightSavingsTime(is_daylight_savings_time());
return(static_cast<int>(bIsDaylightSavingsTime));
}

57
src/mac/os.cpp Normal file
View File

@@ -0,0 +1,57 @@
// (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 "os.hpp"
#include <cassert>
#include <Gestalt.h>
namespace boost {
namespace threads {
namespace mac {
namespace os {
// read the OS version from Gestalt
static inline long get_version()
{
long lVersion;
OSErr nErr = Gestalt(gestaltSystemVersion, &lVersion);
assert(nErr == noErr);
return(lVersion);
}
// check if we're running under Mac OS X and cache that information
bool x()
{
static bool bX = (version() >= 0x1000);
return(bX);
}
// read the OS version and cache it
long version()
{
static long lVersion = get_version();
return(lVersion);
}
} // namespace os
} // namespace mac
} // namespace threads
} // namespace boost

37
src/mac/os.hpp Normal file
View File

@@ -0,0 +1,37 @@
// (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_OS_MJM012402_HPP
#define BOOST_OS_MJM012402_HPP
namespace boost {
namespace threads {
namespace mac {
namespace os {
// functions to determine the OS environment. With namespaces, you get a cute call:
// mac::os::x
bool x();
long version();
} // namespace os
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_OS_MJM012402_HPP

46
src/mac/ot_context.cpp Normal file
View File

@@ -0,0 +1,46 @@
// (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 "ot_context.hpp"
#include "execution_context.hpp"
#include <cassert>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
ot_context::ot_context()
{
assert(at_st());
OSStatus lStatus = InitOpenTransportInContext(0UL, &m_pContext);
// TODO - throw on error
assert(lStatus == noErr);
}
ot_context::~ot_context()
{
CloseOpenTransportInContext(m_pContext);
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost

58
src/mac/ot_context.hpp Normal file
View File

@@ -0,0 +1,58 @@
// (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_OT_CONTEXT_MJM012402_HPP
#define BOOST_OT_CONTEXT_MJM012402_HPP
#include <OpenTransport.h>
#include <boost/utility.hpp>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
// class ot_context is intended to be used only as a singleton. All that this class
// does is ask OpenTransport to create him an OTClientContextPtr, and then doles
// this out to anyone who wants it. ot_context should only be instantiated at
// system task time.
class ot_context: private noncopyable
{
protected:
ot_context();
~ot_context();
public:
OTClientContextPtr get_context();
private:
OTClientContextPtr m_pContext;
};
inline OTClientContextPtr ot_context::get_context()
{ return(m_pContext); }
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_OT_CONTEXT_MJM012402_HPP

76
src/mac/package.hpp Normal file
View File

@@ -0,0 +1,76 @@
// (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_PACKAGE_MJM012402_HPP
#define BOOST_PACKAGE_MJM012402_HPP
namespace boost {
namespace threads {
namespace mac {
namespace detail {
class base_package: private noncopyable
{
public:
virtual void accept() = 0;
};
template<class R>
class package: public base_package
{
public:
inline package(function<R> &rFunctor):
m_rFunctor(rFunctor)
{ /* no-op */ }
inline ~package()
{ /* no-op */ }
virtual void accept()
{ m_oR = m_rFunctor(); }
inline R return_value()
{ return(m_oR); }
private:
function<R> &m_rFunctor;
R m_oR;
};
template<>
class package<void>: public base_package
{
public:
inline package(function<void> &rFunctor):
m_rFunctor(rFunctor)
{ /* no-op */ }
inline ~package()
{ /* no-op */ }
virtual void accept()
{ m_rFunctor(); }
inline void return_value()
{ return; }
private:
function<void> &m_rFunctor;
};
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_PACKAGE_MJM012402_HPP

97
src/mac/periodical.hpp Normal file
View File

@@ -0,0 +1,97 @@
// (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_PERIODICAL_MJM012402_HPP
#define BOOST_PERIODICAL_MJM012402_HPP
#include <boost/function.hpp>
#include <boost/utility.hpp>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
// class periodical inherits from its template parameter, which should follow the
// pattern set by classes dt_scheduler and st_scheduler. periodical knows how to
// call a boost::function, where the xx_scheduler classes only know to to call a
// member periodically.
template<class Scheduler>
class periodical: private noncopyable, private Scheduler
{
public:
periodical(function<void> &rFunction);
~periodical();
public:
void start();
void stop();
protected:
virtual void periodic_function();
private:
function<void> m_oFunction;
};
template<class Scheduler>
periodical<Scheduler>::periodical(function<void> &rFunction):
m_oFunction(rFunction)
{
// no-op
}
template<class Scheduler>
periodical<Scheduler>::~periodical()
{
stop();
}
template<class Scheduler>
void periodical<Scheduler>::start()
{
start_polling();
}
template<class Scheduler>
void periodical<Scheduler>::stop()
{
stop_polling();
}
template<class Scheduler>
inline void periodical<Scheduler>::periodic_function()
{
try
{
m_oFunction();
}
catch(...)
{
}
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_PERIODICAL_MJM012402_HPP

9
src/mac/prefix.hpp Normal file
View File

@@ -0,0 +1,9 @@
// (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 NDEBUG
#define TARGET_CARBON 1

View File

@@ -0,0 +1,48 @@
// (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 "remote_call_manager.hpp"
#include <boost/bind.hpp>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
using detail::delivery_man;
remote_call_manager::remote_call_manager():
m_oDTDeliveryMan(),
m_oSTDeliveryMan(),
m_oDTFunction(bind(&delivery_man::accept_deliveries, &m_oDTDeliveryMan)),
m_oSTFunction(bind(&delivery_man::accept_deliveries, &m_oSTDeliveryMan)),
m_oDTPeriodical(m_oDTFunction),
m_oSTPeriodical(m_oSTFunction)
{
m_oDTPeriodical.start();
m_oSTPeriodical.start();
}
remote_call_manager::~remote_call_manager()
{
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost

View File

@@ -0,0 +1,102 @@
// (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_REMOTE_CALL_MANAGER_MJM012402_HPP
#define BOOST_REMOTE_CALL_MANAGER_MJM012402_HPP
#include <boost/utility.hpp>
#include "delivery_man.hpp"
#include "dt_scheduler.hpp"
#include "periodical.hpp"
#include "execution_context.hpp"
#include "st_scheduler.hpp"
namespace boost {
namespace threads {
namespace mac {
namespace detail {
// class remote_call_manager is used by the remote call functions (dt_remote_call and
// st_remote_call) to execute functions in non-MP contexts.
class remote_call_manager: private noncopyable
{
protected:
remote_call_manager();
~remote_call_manager();
public:
template<class R>
R execute_at_dt(function<R> &rFunctor);
template<class R>
R execute_at_st(function<R> &rFunctor);
private:
template<class R>
static R execute_now(function<R> &rFunctor);
private:
delivery_man m_oDTDeliveryMan;
delivery_man m_oSTDeliveryMan;
function<void> m_oDTFunction;
function<void> m_oSTFunction;
periodical<dt_scheduler> m_oDTPeriodical;
periodical<st_scheduler> m_oSTPeriodical;
};
template<class R>
/*static*/ inline R remote_call_manager::execute_now(function<R> &rFunctor)
{
return(rFunctor());
}
template<>
/*static*/ inline void remote_call_manager::execute_now<void>(function<void> &rFunctor)
{
rFunctor();
}
template<class R>
inline R remote_call_manager::execute_at_dt(function<R> &rFunctor)
{
if(at_mp())
{
return(m_oDTDeliveryMan.deliver(rFunctor));
}
return(execute_now(rFunctor));
}
template<class R>
inline R remote_call_manager::execute_at_st(function<R> &rFunctor)
{
if(at_mp())
{
return(m_oSTDeliveryMan.deliver(rFunctor));
}
assert(at_st());
return(execute_now(rFunctor));
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_REMOTE_CALL_MANAGER_MJM012402_HPP

157
src/mac/remote_calls.hpp Normal file
View File

@@ -0,0 +1,157 @@
// (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_REMOTE_CALLS_MJM012402_HPP
#define BOOST_REMOTE_CALLS_MJM012402_HPP
#include <boost/bind.hpp>
#include "remote_call_manager.hpp"
#include <boost/thread/detail/singleton.hpp>
// this file contains macros to generate functions with the signatures:
// ReturnType st_remote_call([pascal] ReturnType (*pfnFunction)(
// [Argument1Type[, Argument2Type[...]]])
// [, Argument1Type oArgument1[, Argument2Type oArgument2[...]]])
// and
// ReturnType dt_remote_call([pascal] ReturnType (*pfnFunction)(
// [Argument1Type[, Argument2Type[...]]])
// [, Argument1Type oArgument1[, Argument2Type oArgument2[...]]])
// in other words, identical to the function pointer versions of boost::bind, but
// with the return type returned. The purpose of these functions is to be able to
// request that a function be called at system task time or deferred task time, then
// sleep until it is called, and finally get back its return value.
#define BOOST_REMOTE_CALL_CLASS_LIST_0
#define BOOST_REMOTE_CALL_CLASS_LIST_1 BOOST_REMOTE_CALL_CLASS_LIST_0, class A1
#define BOOST_REMOTE_CALL_CLASS_LIST_2 BOOST_REMOTE_CALL_CLASS_LIST_1, class A2
#define BOOST_REMOTE_CALL_CLASS_LIST_3 BOOST_REMOTE_CALL_CLASS_LIST_2, class A3
#define BOOST_REMOTE_CALL_CLASS_LIST_4 BOOST_REMOTE_CALL_CLASS_LIST_3, class A4
#define BOOST_REMOTE_CALL_CLASS_LIST_5 BOOST_REMOTE_CALL_CLASS_LIST_4, class A5
#define BOOST_REMOTE_CALL_CLASS_LIST_6 BOOST_REMOTE_CALL_CLASS_LIST_5, class A6
#define BOOST_REMOTE_CALL_CLASS_LIST_7 BOOST_REMOTE_CALL_CLASS_LIST_6, class A7
#define BOOST_REMOTE_CALL_CLASS_LIST_8 BOOST_REMOTE_CALL_CLASS_LIST_7, class A8
#define BOOST_REMOTE_CALL_CLASS_LIST_9 BOOST_REMOTE_CALL_CLASS_LIST_8, class A9
#define BOOST_REMOTE_CALL_ARGUMENT_LIST_0
#define BOOST_REMOTE_CALL_ARGUMENT_LIST_1 BOOST_REMOTE_CALL_ARGUMENT_LIST_0 A1 oA1
#define BOOST_REMOTE_CALL_ARGUMENT_LIST_2 BOOST_REMOTE_CALL_ARGUMENT_LIST_1, A2 oA2
#define BOOST_REMOTE_CALL_ARGUMENT_LIST_3 BOOST_REMOTE_CALL_ARGUMENT_LIST_2, A3 oA3
#define BOOST_REMOTE_CALL_ARGUMENT_LIST_4 BOOST_REMOTE_CALL_ARGUMENT_LIST_3, A4 oA4
#define BOOST_REMOTE_CALL_ARGUMENT_LIST_5 BOOST_REMOTE_CALL_ARGUMENT_LIST_4, A5 oA5
#define BOOST_REMOTE_CALL_ARGUMENT_LIST_6 BOOST_REMOTE_CALL_ARGUMENT_LIST_5, A6 oA6
#define BOOST_REMOTE_CALL_ARGUMENT_LIST_7 BOOST_REMOTE_CALL_ARGUMENT_LIST_6, A7 oA7
#define BOOST_REMOTE_CALL_ARGUMENT_LIST_8 BOOST_REMOTE_CALL_ARGUMENT_LIST_7, A8 oA8
#define BOOST_REMOTE_CALL_ARGUMENT_LIST_9 BOOST_REMOTE_CALL_ARGUMENT_LIST_8, A9 oA9
#define BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_0
#define BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_1 BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_0, oA1
#define BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_2 BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_1, oA2
#define BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_3 BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_2, oA3
#define BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_4 BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_3, oA4
#define BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_5 BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_4, oA5
#define BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_6 BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_5, oA6
#define BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_7 BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_6, oA7
#define BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_8 BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_7, oA8
#define BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_9 BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_8, oA9
#define BOOST_REMOTE_CALL_COMMA_0
#define BOOST_REMOTE_CALL_COMMA_1 ,
#define BOOST_REMOTE_CALL_COMMA_2 ,
#define BOOST_REMOTE_CALL_COMMA_3 ,
#define BOOST_REMOTE_CALL_COMMA_4 ,
#define BOOST_REMOTE_CALL_COMMA_5 ,
#define BOOST_REMOTE_CALL_COMMA_6 ,
#define BOOST_REMOTE_CALL_COMMA_7 ,
#define BOOST_REMOTE_CALL_COMMA_8 ,
#define BOOST_REMOTE_CALL_COMMA_9 ,
// this is the macro that ties it all together. From here, we generate all forms of
// dt_remote_call and st_remote_call.
#define BOOST_REMOTE_CALL(context, stack, n) \
template<class R BOOST_REMOTE_CALL_CLASS_LIST_ ## n> \
inline R context ## _remote_call(stack R (*pfnF)( \
BOOST_REMOTE_CALL_ARGUMENT_LIST_ ## n) \
BOOST_REMOTE_CALL_COMMA_ ## n \
BOOST_REMOTE_CALL_ARGUMENT_LIST_ ## n) \
{ \
using ::boost::detail::thread::singleton; \
using detail::remote_call_manager; \
function<R> oFunc(bind(pfnF BOOST_REMOTE_CALL_FUNCTION_ARGUMENT_LIST_ ## n)); \
remote_call_manager &rManager(singleton<remote_call_manager>::instance()); \
return(rManager.execute_at_ ## context(oFunc)); \
}
namespace boost {
namespace threads {
namespace mac {
BOOST_REMOTE_CALL(st, , 0)
BOOST_REMOTE_CALL(st, , 1)
BOOST_REMOTE_CALL(st, , 2)
BOOST_REMOTE_CALL(st, , 3)
BOOST_REMOTE_CALL(st, , 4)
BOOST_REMOTE_CALL(st, , 5)
BOOST_REMOTE_CALL(st, , 6)
BOOST_REMOTE_CALL(st, , 7)
BOOST_REMOTE_CALL(st, , 8)
BOOST_REMOTE_CALL(st, , 9)
BOOST_REMOTE_CALL(dt, , 0)
BOOST_REMOTE_CALL(dt, , 1)
BOOST_REMOTE_CALL(dt, , 2)
BOOST_REMOTE_CALL(dt, , 3)
BOOST_REMOTE_CALL(dt, , 4)
BOOST_REMOTE_CALL(dt, , 5)
BOOST_REMOTE_CALL(dt, , 6)
BOOST_REMOTE_CALL(dt, , 7)
BOOST_REMOTE_CALL(dt, , 8)
BOOST_REMOTE_CALL(dt, , 9)
BOOST_REMOTE_CALL(st, pascal, 0)
BOOST_REMOTE_CALL(st, pascal, 1)
BOOST_REMOTE_CALL(st, pascal, 2)
BOOST_REMOTE_CALL(st, pascal, 3)
BOOST_REMOTE_CALL(st, pascal, 4)
BOOST_REMOTE_CALL(st, pascal, 5)
BOOST_REMOTE_CALL(st, pascal, 6)
BOOST_REMOTE_CALL(st, pascal, 7)
BOOST_REMOTE_CALL(st, pascal, 8)
BOOST_REMOTE_CALL(st, pascal, 9)
BOOST_REMOTE_CALL(dt, pascal, 0)
BOOST_REMOTE_CALL(dt, pascal, 1)
BOOST_REMOTE_CALL(dt, pascal, 2)
BOOST_REMOTE_CALL(dt, pascal, 3)
BOOST_REMOTE_CALL(dt, pascal, 4)
BOOST_REMOTE_CALL(dt, pascal, 5)
BOOST_REMOTE_CALL(dt, pascal, 6)
BOOST_REMOTE_CALL(dt, pascal, 7)
BOOST_REMOTE_CALL(dt, pascal, 8)
BOOST_REMOTE_CALL(dt, pascal, 9)
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_REMOTE_CALLS_MJM012402_HPP

210
src/mac/safe.cpp Normal file
View File

@@ -0,0 +1,210 @@
// (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 <DriverServices.h>
#include <Events.h>
#include <Multiprocessing.h>
#include <Threads.h>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/thread/detail/force_cast.hpp>
#include <limits>
#include "execution_context.hpp"
using boost::detail::thread::force_cast;
namespace boost {
namespace threads {
namespace mac {
namespace detail {
static OSStatus safe_wait(function<OSStatus, Duration> &rFunction, Duration lDuration);
// we call WNE to allow tasks that own the resource the blue is waiting on system
// task time, in case they are blocked on an ST remote call (or a memory allocation
// for that matter).
static void idle()
{
if(at_st())
{
EventRecord sEvent;
bool bEvent = WaitNextEvent(0U, &sEvent, 0UL, NULL);
}
}
OSStatus safe_wait_on_semaphore(MPSemaphoreID pSemaphoreID, Duration lDuration)
{
function<OSStatus, Duration> oWaitOnSemaphore;
oWaitOnSemaphore = bind(MPWaitOnSemaphore, pSemaphoreID, _1);
return(safe_wait(oWaitOnSemaphore, lDuration));
}
OSStatus safe_enter_critical_region(MPCriticalRegionID pCriticalRegionID, Duration lDuration, MPCriticalRegionID pCriticalRegionCriticalRegionID/* = kInvalidID*/)
{
if(pCriticalRegionCriticalRegionID != kInvalidID)
{
if(at_mp())
{
// enter the critical region's critical region
OSStatus lStatus = noErr;
AbsoluteTime sExpiration;
if(lDuration != kDurationImmediate && lDuration != kDurationForever)
{
sExpiration = AddDurationToAbsolute(lDuration, UpTime());
}
lStatus = MPEnterCriticalRegion(pCriticalRegionCriticalRegionID, lDuration);
assert(lStatus == noErr || lStatus == kMPTimeoutErr);
if(lStatus == noErr)
{
// calculate a new duration
if(lDuration != kDurationImmediate && lDuration != kDurationForever)
{
// check if we have any time left
AbsoluteTime sUpTime(UpTime());
if(force_cast<uint64_t>(sExpiration) > force_cast<uint64_t>(sUpTime))
{
// reset our duration to our remaining time
lDuration = AbsoluteDeltaToDuration(sExpiration, sUpTime);
}
else
{
// no time left
lDuration = kDurationImmediate;
}
}
// if we entered the critical region, exit it again
lStatus = MPExitCriticalRegion(pCriticalRegionCriticalRegionID);
assert(lStatus == noErr);
}
else
{
// otherwise, give up
return(lStatus);
}
}
else
{
// if we're at system task time, try to enter the critical region's critical
// region until we succeed. MP tasks will block on this until we let it go.
OSStatus lStatus;
do
{
lStatus = MPEnterCriticalRegion(pCriticalRegionCriticalRegionID, kDurationImmediate);
} while(lStatus == kMPTimeoutErr);
assert(lStatus == noErr);
}
}
// try to enter the critical region
function<OSStatus, Duration> oEnterCriticalRegion;
oEnterCriticalRegion = bind(MPEnterCriticalRegion, pCriticalRegionID, _1);
OSStatus lStatus = safe_wait(oEnterCriticalRegion, lDuration);
// if we entered the critical region's critical region to get the critical region,
// exit the critical region's critical region.
if(pCriticalRegionCriticalRegionID != kInvalidID && at_mp() == false)
{
lStatus = MPExitCriticalRegion(pCriticalRegionCriticalRegionID);
assert(lStatus == noErr);
}
return(lStatus);
}
OSStatus safe_wait_on_queue(MPQueueID pQueueID, void **pParam1, void **pParam2, void **pParam3, Duration lDuration)
{
function<OSStatus, Duration> oWaitOnQueue;
oWaitOnQueue = bind(MPWaitOnQueue, pQueueID, pParam1, pParam2, pParam3, _1);
return(safe_wait(oWaitOnQueue, lDuration));
}
OSStatus safe_delay_until(AbsoluteTime *pWakeUpTime)
{
if(execution_context() == k_eExecutionContextMPTask)
{
return(MPDelayUntil(pWakeUpTime));
}
else
{
uint64_t ullWakeUpTime = force_cast<uint64_t>(*pWakeUpTime);
while(force_cast<uint64_t>(UpTime()) < ullWakeUpTime)
{
idle();
}
return(noErr);
}
}
OSStatus safe_wait(function<OSStatus, Duration> &rFunction, Duration lDuration)
{
if(execution_context() == k_eExecutionContextMPTask)
{
return(rFunction(lDuration));
}
else
{
uint64_t ullExpiration = 0ULL;
// get the expiration time in UpTime units
if(lDuration == kDurationForever)
{
ullExpiration = (::std::numeric_limits<uint64_t>::max)();
}
else if(lDuration == kDurationImmediate)
{
ullExpiration = force_cast<uint64_t>(UpTime());
}
else
{
AbsoluteTime sExpiration = AddDurationToAbsolute(lDuration, UpTime());
ullExpiration = force_cast<uint64_t>(sExpiration);
}
OSStatus lStatus;
bool bExpired = false;
do
{
lStatus = rFunction(kDurationImmediate);
// mm - "if" #if 0'd out to allow task time to threads blocked on I/O
#if 0
if(lStatus == kMPTimeoutErr)
#endif
{
idle();
}
if(lDuration != kDurationForever)
{
bExpired = (force_cast<uint64_t>(UpTime()) < ullExpiration);
}
} while(lStatus == kMPTimeoutErr && bExpired == false);
return(lStatus);
}
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost

41
src/mac/safe.hpp Normal file
View File

@@ -0,0 +1,41 @@
// (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_SAFE_MJM012402_HPP
#define BOOST_SAFE_MJM012402_HPP
#include <Multiprocessing.h>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
// these functions are used to wain in an execution context-independent manor. All of these
// functions are both MP- and ST-safe.
OSStatus safe_wait_on_semaphore(MPSemaphoreID pSemaphoreID, Duration lDuration);
OSStatus safe_enter_critical_region(MPCriticalRegionID pCriticalRegionID, Duration lDuration, MPCriticalRegionID pCriticalRegionCriticalRegionID = kInvalidID);
OSStatus safe_wait_on_queue(MPQueueID pQueueID, void **pParam1, void **pParam2, void **pParam3, Duration lDuration);
OSStatus safe_delay_until(AbsoluteTime *pWakeUpTime);
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_SAFE_MJM012402_HPP

View File

@@ -0,0 +1,47 @@
// (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 "scoped_critical_region.hpp"
#include "init.hpp"
#include <cassert>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
scoped_critical_region::scoped_critical_region():
m_pCriticalRegionID(kInvalidID)
{
static bool bIgnored = thread_init();
OSStatus lStatus = MPCreateCriticalRegion(&m_pCriticalRegionID);
if(lStatus != noErr || m_pCriticalRegionID == kInvalidID)
throw(thread_resource_error());
}
scoped_critical_region::~scoped_critical_region()
{
OSStatus lStatus = MPDeleteCriticalRegion(m_pCriticalRegionID);
assert(lStatus == noErr);
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost

View File

@@ -0,0 +1,63 @@
// (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_SCOPED_CRITICAL_REGION_MJM012402_HPP
#define BOOST_SCOPED_CRITICAL_REGION_MJM012402_HPP
#include <boost/thread/exceptions.hpp>
#include <Multiprocessing.h>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
// class scoped_critical_region probably needs a new name. Although the current name
// is accurate, it can be read to mean that a critical region is entered for the
// current scope. In reality, a critical region is _created_ for the current scope.
// This class is intended as a replacement for MPCriticalRegionID that will
// automatically create and dispose of itself.
class scoped_critical_region
{
public:
scoped_critical_region();
~scoped_critical_region();
public:
operator const MPCriticalRegionID &() const;
const MPCriticalRegionID &get() const;
private:
MPCriticalRegionID m_pCriticalRegionID;
};
// these are inlined for speed.
inline scoped_critical_region::operator const MPCriticalRegionID &() const
{ return(m_pCriticalRegionID); }
inline const MPCriticalRegionID &scoped_critical_region::get() const
{ return(m_pCriticalRegionID); }
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_SCOPED_CRITICAL_REGION_MJM012402_HPP

85
src/mac/st_scheduler.cpp Normal file
View File

@@ -0,0 +1,85 @@
// (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 "st_scheduler.hpp"
#include <cassert>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
#if TARGET_CARBON
st_scheduler::st_scheduler():
m_uppTask(NULL),
m_pTimer(NULL)
{
m_uppTask = NewEventLoopTimerUPP(task_entry);
// TODO - throw on error
assert(m_uppTask != NULL);
}
st_scheduler::~st_scheduler()
{
DisposeEventLoopTimerUPP(m_uppTask);
m_uppTask = NULL;
}
void st_scheduler::start_polling()
{
assert(m_pTimer == NULL);
OSStatus lStatus = InstallEventLoopTimer(GetMainEventLoop(),
0 * kEventDurationSecond,
kEventDurationMillisecond,
m_uppTask,
this,
&m_pTimer);
// TODO - throw on error
assert(lStatus == noErr);
}
void st_scheduler::stop_polling()
{
assert(m_pTimer != NULL);
OSStatus lStatus = RemoveEventLoopTimer(m_pTimer);
assert(lStatus == noErr);
m_pTimer = NULL;
}
/*static*/ pascal void st_scheduler::task_entry(EventLoopTimerRef /*pTimer*/, void *pRefCon)
{
st_scheduler *pThis = reinterpret_cast<st_scheduler *>(pRefCon);
assert(pThis != NULL);
pThis->task();
}
void st_scheduler::task()
{
periodic_function();
}
#else
# error st_scheduler unimplemented!
#endif
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost

67
src/mac/st_scheduler.hpp Normal file
View File

@@ -0,0 +1,67 @@
// (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_ST_SCHEDULER_MJM012402_HPP
#define BOOST_ST_SCHEDULER_MJM012402_HPP
#include <CarbonEvents.h>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
// class st_scheduler calls its pure-virtual periodic_function method periodically at
// system task time. This is generally 40Hz under Mac OS 9.
class st_scheduler
{
public:
st_scheduler();
virtual ~st_scheduler();
protected:
void start_polling();
void stop_polling();
private:
virtual void periodic_function() = 0;
#if TARGET_CARBON
// use event loop timers under Carbon
private:
static pascal void task_entry(EventLoopTimerRef pTimer, void *pRefCon);
void task();
private:
EventLoopTimerUPP m_uppTask;
EventLoopTimerRef m_pTimer;
#else
// this can be implemented using OT system tasks. This would be mostly a copy-and-
// paste of the dt_scheduler code, replacing DeferredTask with SystemTask and DT
// with ST.
# error st_scheduler unimplemented!
#endif
};
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_ST_SCHEDULER_MJM012402_HPP

View File

@@ -0,0 +1,56 @@
// (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 "thread_cleanup.hpp"
namespace boost {
namespace threads {
namespace mac {
namespace detail {
namespace {
TaskStorageIndex g_ulIndex(0UL);
} // anonymous namespace
void do_thread_startup()
{
if(g_ulIndex == 0UL)
{
OSStatus lStatus = MPAllocateTaskStorageIndex(&g_ulIndex);
assert(lStatus == noErr);
}
set_thread_cleanup_task(NULL);
}
void do_thread_cleanup()
{
void (*pfnTask)() = MPGetTaskValue(g_ulIndex)
}
void set_thread_cleanup_task(void (*pfnTask)())
{
lStatus = MPSetTaskValue(g_ulIndex, reinterpret_cast<TaskStorageValue>(pfnTask));
assert(lStatus == noErr);
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost

View File

@@ -0,0 +1,36 @@
// (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_THREAD_CLEANUP_MJM012402_HPP
#define BOOST_THREAD_CLEANUP_MJM012402_HPP
namespace boost {
namespace threads {
namespace mac {
namespace detail {
void do_thread_startup();
void do_thread_cleanup();
void set_thread_cleanup_task();
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_THREAD_CLEANUP_MJM012402_HPP

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