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

Compare commits

...

131 Commits

Author SHA1 Message Date
Anthony Williams
ab1c01b17a declared _ReadWriteBarrier intrinsic; added explicit check for zero to ReleaseSemaphore call
[SVN r39700]
2007-10-05 10:41:16 +00:00
Anthony Williams
bb06946bf1 reverted condition
[SVN r39698]
2007-10-05 09:56:20 +00:00
Anthony Williams
68a7a469ca reverted condition.hpp
[SVN r39696]
2007-10-05 09:55:12 +00:00
Anthony Williams
b2a095098d header-only once for POSIX
[SVN r39695]
2007-10-05 09:52:08 +00:00
Anthony Williams
b5ac347a0b Initial pthreads implementation
[SVN r38179]
2007-07-11 08:31:24 +00:00
Anthony Williams
cf15597a9e Added timeout constant
[SVN r37650]
2007-05-09 14:37:56 +00:00
Anthony Williams
ab0e9930c5 Added copyright and licence
[SVN r37189]
2007-03-15 13:53:43 +00:00
Anthony Williams
d0d1db2feb New condvar implementation that doesn't depend on APC calls, so OS can pick thread to wake
[SVN r37188]
2007-03-15 13:39:59 +00:00
Anthony Williams
89348a9569 basic timed mutex uses an Auto-Reset Event rather than a semaphore; changed thread_primitives to avoid use of macros
[SVN r36067]
2006-11-17 10:45:27 +00:00
Anthony Williams
f260fd62d4 inherit publicly from underlying mutex
[SVN r36066]
2006-11-17 09:07:29 +00:00
Anthony Williams
e2550db927 More tests for try_lock_shareable
[SVN r35870]
2006-11-06 12:17:34 +00:00
Anthony Williams
0d763fe627 Added try_lock_shareable
[SVN r35869]
2006-11-06 09:32:26 +00:00
Anthony Williams
9895e74560 Added upgradeable stuff
[SVN r35798]
2006-10-30 21:36:44 +00:00
Anthony Williams
82aa808b3b Current read-write mutex impl doesn't support upgrading
[SVN r35752]
2006-10-27 15:18:59 +00:00
Anthony Williams
fb683c8d95 New, fairer and faster read-write mutex algorithm
[SVN r35751]
2006-10-27 15:18:00 +00:00
Anthony Williams
819c67d52b Increased count limits to use all available space in state field; extracted create_anonymous_event; ensure shared event is correctly
set


[SVN r35659]
2006-10-18 13:15:41 +00:00
Anthony Williams
95a476a4cc Updated tests for read_write_mutex, and fixed initialization of events
[SVN r35648]
2006-10-17 17:22:57 +00:00
Anthony Williams
c4625de938 Updated read-write mutex implementation to support upgradeable locks too
[SVN r35499]
2006-10-05 14:42:08 +00:00
Anthony Williams
eeb77fdd87 New look read-write mutex
[SVN r35497]
2006-10-05 09:38:31 +00:00
Anthony Williams
7aed765a77 Only get the semaphore once at the beginning of lock/timed_lock
[SVN r35494]
2006-10-05 07:34:28 +00:00
Anthony Williams
5a4f798320 Avoid doing an extra CAS if the same number of threads are waiting when we wake up as when we go to sleep
[SVN r35487]
2006-10-04 11:28:26 +00:00
Anthony Williams
8f611e4d19 Improved algorithm of basic_timed_mutex, and changed boost::mutex to use that as the underlying type
[SVN r35486]
2006-10-04 11:09:55 +00:00
Anthony Williams
a646f1c818 Changed tests that rely on condition variables to use the new basic_condition<lock_type> rather than plain condition
[SVN r35485]
2006-10-04 11:06:24 +00:00
Anthony Williams
3d4743972e New lock algorithm with
[SVN r35454]
2006-10-03 10:16:22 +00:00
Anthony Williams
553aad753b Experimental change to template the whole condition variable on the lock type, rather than the wait functions
[SVN r35362]
2006-09-28 11:41:14 +00:00
Anthony Williams
f8a08dfaad condition doesn't need to be a friend of these classes in the new implementation
[SVN r35361]
2006-09-28 11:31:40 +00:00
Anthony Williams
956ed86655 Added missing include
[SVN r35318]
2006-09-25 09:09:02 +00:00
Roland Schwarz
e258fb3fe9 Added pthread compile comments for win32
[SVN r35309]
2006-09-24 13:55:47 +00:00
Roland Schwarz
676eb029b8 Examples compile with bbv1
[SVN r35308]
2006-09-24 13:08:22 +00:00
Roland Schwarz
6459de79c3 More sources added
[SVN r35290]
2006-09-23 15:37:42 +00:00
Roland Schwarz
af774310ef disable MSVC DLL warnings for derivation from noncopyable
[SVN r35281]
2006-09-22 17:00:21 +00:00
Roland Schwarz
b1c5977064 cleaned up time conversions for pthread implementation
[SVN r35280]
2006-09-22 16:56:06 +00:00
Anthony Williams
d92430c8ee Added explicit check for value!=0, to remove warning
[SVN r35273]
2006-09-22 10:31:25 +00:00
Anthony Williams
ce384ef3d8 Ensure thread handle is closed correctly. Fix race conditions on notify.
[SVN r35272]
2006-09-22 09:41:34 +00:00
Roland Schwarz
c2cfd16c6c replaced <library-file> by <library>
[SVN r35251]
2006-09-21 16:31:56 +00:00
Anthony Williams
fcfd30f124 Don't unlink a thread that's been notified when it wakes, as the unlink is done as part of the notify
Hold the gate whilst we notify all the waiting threads, so they don't unlink out from under us.


[SVN r35222]
2006-09-20 10:06:49 +00:00
Roland Schwarz
20cc8e6c30 corrected PTW32_LIB variable
[SVN r35220]
2006-09-19 20:59:40 +00:00
Anthony Williams
4bff122033 We don't need to lock round every notify when notifying all, since we've already isolated the list
[SVN r35202]
2006-09-19 14:11:45 +00:00
Roland Schwarz
49e437f11e using modules.peek to access environment variables for pthread
[SVN r35167]
2006-09-18 19:28:28 +00:00
Roland Schwarz
63bad0ad64 build support for boost.build v2
[SVN r35166]
2006-09-18 18:47:47 +00:00
Roland Schwarz
33ff838081 <sysinclude> really needs to refer to $(BOOST_ROOT). Relative paths not working.
[SVN r35162]
2006-09-18 18:02:29 +00:00
Anthony Williams
5328b43191 Serialize the final checks, too, so we don't get race conditions in the BOOST_CHECK_EQUAL in call_once_thread
[SVN r34842]
2006-08-07 16:32:26 +00:00
Anthony Williams
7aac1e69af New once test under BSL
[SVN r34841]
2006-08-07 16:31:32 +00:00
Anthony Williams
94207924ad Eliminated some "magic numbers"
[SVN r34840]
2006-08-07 16:14:42 +00:00
Roland Schwarz
3671f1792d compiler choked on conversion to long in function get_milliseconds_until_time
[SVN r34816]
2006-08-04 16:57:57 +00:00
Roland Schwarz
3da29cb470 corrected typo
[SVN r34815]
2006-08-04 10:39:46 +00:00
Roland Schwarz
4448aa7fb9 disable warnings of non dll base class for noncopyable. This is necessary for bbv2 since the warning level now is W3
[SVN r34814]
2006-08-04 10:35:19 +00:00
Roland Schwarz
71358d8842 Allow examples to be built out of boost source tree.
[SVN r34584]
2006-07-17 10:19:36 +00:00
Roland Schwarz
5366b629d3 Fallback to time if neither gettimeofday nor clock_gettime available.
[SVN r34583]
2006-07-17 10:17:12 +00:00
Roland Schwarz
01b2d5c088 bbv1 Jamfile restructured
[SVN r34582]
2006-07-17 10:15:17 +00:00
Roland Schwarz
8d22f58bc3 Native files now without platform tag.
[SVN r34581]
2006-07-17 10:12:43 +00:00
Anthony Williams
be64ba98b3 Ensure all checks are guarded by a mutex, to avoid race conditions in the test library
[SVN r34503]
2006-07-10 20:53:56 +00:00
Roland Schwarz
ad551dd333 xtime source added
[SVN r34318]
2006-06-16 13:40:30 +00:00
Anthony Williams
1e055e618d try_lock should throw if already locked
[SVN r34313]
2006-06-15 20:10:42 +00:00
Anthony Williams
46064d1b20 Added test to ensure that try_lock locks if not already locked
[SVN r34312]
2006-06-15 20:01:37 +00:00
Anthony Williams
08cf6a81a5 Changes test_scoped_try_lock over to being a templated test case
[SVN r34300]
2006-06-14 07:52:29 +00:00
Anthony Williams
8ce25c6ecd Changed scoped_lock_test to templated test case, in order to get better error messages
[SVN r34299]
2006-06-14 07:48:05 +00:00
Anthony Williams
01f93931cb timed_mutex and recursive_timed_mutex have scoped_locks
[SVN r34298]
2006-06-14 07:31:13 +00:00
Anthony Williams
0d3f4a0b7c recursive_try_mutex has both a scoped_lock and a scoped_try_lock
[SVN r34297]
2006-06-13 21:08:02 +00:00
Anthony Williams
29a1903c4b recursive_mutex::scoped_lock should support scoped_lock concept
[SVN r34295]
2006-06-13 20:36:27 +00:00
Anthony Williams
08041bf58e try_mutex locks throw if unlocked twice
[SVN r34249]
2006-06-08 16:39:21 +00:00
Anthony Williams
781794aa2d Templated test_throws_if_unlock_called_when_already_unlocked
[SVN r34248]
2006-06-08 16:32:40 +00:00
Anthony Williams
36c1198113 Added more tests for try_mutex::scoped_try_lock
[SVN r34247]
2006-06-08 16:31:15 +00:00
Anthony Williams
552dfff988 try_mutex_scoped_lock throws if you try and lock it twice
[SVN r34246]
2006-06-08 16:30:14 +00:00
Anthony Williams
6efc06f50c templated test_throws_if_lock_called_when_already_locked
[SVN r34245]
2006-06-08 16:22:33 +00:00
Anthony Williams
e72cb93fe0 Templated test_locked_after_lock_called
[SVN r34243]
2006-06-08 14:53:02 +00:00
Anthony Williams
d57be95047 Templated more tests
[SVN r34242]
2006-06-08 14:48:46 +00:00
Anthony Williams
1d1989bbfe Templated test_initially_locked_with_bool_parameter_true
[SVN r34241]
2006-06-08 14:42:41 +00:00
Anthony Williams
11178cdc84 Templated test_initially_locked, and applied to boost::try_mutex::scoped_lock too
[SVN r34240]
2006-06-08 14:40:43 +00:00
Anthony Williams
54d37cd6af Added more checks round scoped_lock concept
[SVN r34239]
2006-06-08 14:33:29 +00:00
Anthony Williams
ede873549b Throw lock error if we try and unlock twice
[SVN r34238]
2006-06-08 14:24:23 +00:00
Anthony Williams
83a2a4ec38 Started to add tests for locking concepts; ensure mutex::scoped_lock throws when try to lock if already locked
[SVN r34237]
2006-06-08 14:12:10 +00:00
Anthony Williams
29e3665ead scoped_read_lock calls m.cond.notify_one, so it passes test
[SVN r34236]
2006-06-08 09:57:00 +00:00
Anthony Williams
acd9b9db7e Two tests in
[SVN r33904]
2006-05-02 09:23:33 +00:00
Anthony Williams
71c652dd9f Basic condition-based read-write mutex
[SVN r33850]
2006-04-28 08:20:18 +00:00
Anthony Williams
6afcf7615d Use headers from most general point rather than most specific
[SVN r33845]
2006-04-27 21:07:30 +00:00
Anthony Williams
70302577f9 Empty read_write_mutex supports any number of readers
[SVN r33844]
2006-04-27 20:39:36 +00:00
Anthony Williams
b5fdb39877 Updated to fix line endings
[SVN r33838]
2006-04-27 14:04:45 +00:00
Anthony Williams
26f3f0fd2d Changed the Comparison for the condition-based test in test_timedlock to state what we really mean
[SVN r33837]
2006-04-27 14:03:39 +00:00
Anthony Williams
562a748bc6 Moved more stuff over to new platform layout; made tests work on win32
[SVN r33680]
2006-04-12 16:48:10 +00:00
Roland Schwarz
45ca67ec26 obsolete code
[SVN r33672]
2006-04-11 22:23:47 +00:00
Roland Schwarz
65f466c813 platform split
[SVN r33669]
2006-04-11 19:54:45 +00:00
Roland Schwarz
2b37cee9e5 platform split
[SVN r33668]
2006-04-11 19:49:21 +00:00
Roland Schwarz
ad33e705b2 platform split
[SVN r33667]
2006-04-11 19:42:57 +00:00
Roland Schwarz
a639fe4dbe platform split
[SVN r33666]
2006-04-11 19:35:10 +00:00
Roland Schwarz
8806d38775 platform split
[SVN r33665]
2006-04-11 19:24:06 +00:00
Anthony Williams
ba49aaa0f7 Added "unspecified" read-write sync policy, for use in read-write mutex tests
[SVN r33564]
2006-04-06 09:13:22 +00:00
Anthony Williams
1a92100467 Don't make qualified calls where we don't have to
[SVN r33556]
2006-04-05 11:46:12 +00:00
Anthony Williams
ef6dc83fa8 Use BOOST_INTERLOCKED_EXCHANGE_ADD in preference to BOOST_INTERLOCKED_COMPARE_EXCHANGE, since this should be faster
[SVN r33555]
2006-04-05 11:45:11 +00:00
Anthony Williams
48f550d403 Updated copyright
[SVN r33554]
2006-04-05 11:43:07 +00:00
Anthony Williams
3c9be720b8 Simplified code by extracting create_once_mutex, so the essence of call_once is clarified.
Use boost::detail::interlocked_read rather than BOOST_INTERLOCKED_COMPARE_EXCHANGE to check flag value


[SVN r33553]
2006-04-05 11:42:07 +00:00
Anthony Williams
b3ba8802bf Better express intent in structure of call_once
[SVN r33457]
2006-03-23 16:11:52 +00:00
Anthony Williams
0fddf00c8f Removed using declaration for get_active_count, since we don't need it, and VC6 moans about it
[SVN r33411]
2006-03-20 22:08:33 +00:00
Anthony Williams
bb7976f666 Tidied up access for condition members
[SVN r33345]
2006-03-14 23:43:23 +00:00
Anthony Williams
3ad4fb38b5 Eliminated redundant #ifdef parts
[SVN r33335]
2006-03-13 17:00:46 +00:00
Anthony Williams
deaccce853 Corrected #ifdefs for WINTHREADS
[SVN r33331]
2006-03-13 10:07:49 +00:00
Anthony Williams
6aabcaac5c Added appropriate support for QueueUserAPC condition implementation
[SVN r33330]
2006-03-13 08:29:17 +00:00
Anthony Williams
d07407306f Added boost::detail::get_xtime_sentinel, which always yields 2^32-1 (INFINITE) seconds until expiry
[SVN r33329]
2006-03-13 08:14:16 +00:00
Anthony Williams
4231423773 Reduced duplication by extracting do_notify_one
[SVN r33304]
2006-03-10 10:54:27 +00:00
Anthony Williams
46b66d5268 Reduced scope of locking
[SVN r33303]
2006-03-10 10:33:37 +00:00
Anthony Williams
9c439a73db Inlined barrier code, new implementation of condition based on QueueUserAPC. Blocks all waits and notifies whilst notifying.
[SVN r33302]
2006-03-10 10:07:01 +00:00
Anthony Williams
cdd57f50ef Added recursive_timed_mutex
[SVN r33279]
2006-03-09 11:13:29 +00:00
Anthony Williams
8c2ded3235 Win32 implementation of boost::timed_mutex
[SVN r33272]
2006-03-08 22:24:52 +00:00
Anthony Williams
d3b590f213 Assert rather than throw when using checked mutexes
[SVN r33231]
2006-03-06 09:47:09 +00:00
Anthony Williams
7fcdd5d9e2 Added basic_checked_mutex, and make use of it dependent on BOOST_USE_CHECKED_MUTEX
[SVN r33208]
2006-03-03 09:35:41 +00:00
Anthony Williams
9ceee4b030 New implementations of mutex and recursive mutex for win32
[SVN r33172]
2006-02-28 11:27:19 +00:00
Anthony Williams
50f8f34ab8 Simplified wait functions
[SVN r32393]
2006-01-24 11:24:00 +00:00
Anthony Williams
d76e67ffe2 Updated tests, to ensure unblocked_count is guarded by mutex when reading, and added new test for unblocking only one writer
[SVN r31627]
2005-11-12 10:21:39 +00:00
Anthony Williams
617729f2ae Added new test for unblocking all readers to read_write_mutex code. Added necessary implementation.
[SVN r31122]
2005-09-26 07:09:09 +00:00
Anthony Williams
e8363511d0 Moved BOOST_INTERLOCKED_READ stuff into its own header
[SVN r31098]
2005-09-23 17:24:29 +00:00
Anthony Williams
4749f47f00 Verify that only one writer permitted at once
[SVN r31064]
2005-09-20 22:09:49 +00:00
Anthony Williams
07af8a5605 Removed duplication between reader_thread and writer_thread into a template locking_thread
[SVN r31063]
2005-09-20 21:51:02 +00:00
Anthony Williams
cc89b8d2c6 A locked reader blocks a waiting writer
[SVN r31062]
2005-09-20 21:42:45 +00:00
Anthony Williams
946d45ee70 Added brute force test for multiple readers
[SVN r31061]
2005-09-20 21:20:31 +00:00
Anthony Williams
8a3b5145ac reverted QueueUserAPC changes
[SVN r31052]
2005-09-20 07:27:35 +00:00
Anthony Williams
1af9fb7267 Wake up threads using QueueUserAPC rather than triggering the semaphore.
[SVN r31047]
2005-09-19 22:31:21 +00:00
Anthony Williams
6fe2e36fb0 Put a mutex around the increment in init_once_value, to ensure that if two threads call init_once_value, the increment is done
correctly.


[SVN r31046]
2005-09-19 21:09:14 +00:00
Anthony Williams
e5ada85386 Extended stress test: 100 threads, loop 100 times on same thread.
[SVN r31045]
2005-09-19 20:59:49 +00:00
Anthony Williams
a9760cd2e6 Added test to verify that threads block on a mutex, and only one waiting thread is released when the mutex is unlocked.
[SVN r31040]
2005-09-19 15:11:41 +00:00
Anthony Williams
3e0ce8d25a Added a looping test to check for cross-thread sync problems
[SVN r31016]
2005-09-17 22:20:35 +00:00
Anthony Williams
7d59bbbad5 Set semaphore handle back to NULL on destruction
[SVN r31011]
2005-09-16 13:58:44 +00:00
Anthony Williams
c7a85f366c New read_write_mutex implementation for win32. No try/timed varieties, and no support for read/write priority policies.
[SVN r30994]
2005-09-15 10:47:29 +00:00
Anthony Williams
8b3773f157 Trimmed included headers
[SVN r30986]
2005-09-14 15:44:28 +00:00
Anthony Williams
cb27585fa2 Added new implementation of timed_mutex for win32
[SVN r30985]
2005-09-14 15:20:24 +00:00
Anthony Williams
d3ee1b804a Added new implementation of timed_mutex for win32
[SVN r30984]
2005-09-14 15:10:41 +00:00
Anthony Williams
48ff760e18 Remove references to WINTHREADS from the generic code, as windows threads handled in separate header
[SVN r30982]
2005-09-14 12:49:52 +00:00
Anthony Williams
ba0bdc6489 Use lightweight_mutex for mutex impl. Added basic condition implementation.
[SVN r30981]
2005-09-14 12:43:02 +00:00
Anthony Williams
953461904c Added licence text
[SVN r30979]
2005-09-14 10:44:27 +00:00
Anthony Williams
c956bc9ad7 Moved lightweight_mutex_win32.hpp and mutex_win32.hpp into boost source tree
[SVN r30978]
2005-09-14 10:35:12 +00:00
Anthony Williams
91d88bb24a Added lightweight_mutex_win32.hpp
[SVN r30977]
2005-09-14 10:18:33 +00:00
nobody
545a0f5c86 This commit was manufactured by cvs2svn to create branch
'thread_rewrite'.

[SVN r30953]
2005-09-13 14:20:32 +00:00
131 changed files with 7448 additions and 10901 deletions

View File

@@ -1,127 +1,122 @@
# Copyright (C) 2001-2003
# William E. Kempf
# Copyright 2006 Roland Schwarz.
# Distributed under the Boost Software License, Version 1.0. (See
# accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
# Permission to use, copy, modify, distribute and sell this software
# and its documentation for any purpose is hereby granted without fee,
# provided that the above copyright notice appear in all copies and
# that both that copyright notice and this permission notice appear
# in supporting documentation. William E. Kempf makes no representations
# about the suitability of this software for any purpose.
# It is provided "as is" without express or implied warranty.
#
# Boost.Threads build Jamfile
#
# Additional configuration variables used:
# See threads.jam.
# This work is a reimplementation along the design and ideas
# of William E. Kempf.
# Declare the location of this subproject relative to the root.
subproject libs/thread/build ;
# Include threads.jam for Boost.Threads global build information.
# This greatly simplifies the Jam code needed to configure the build
# for the various Win32 build types.
import ./threads ;
{
CPP_SOURCES =
barrier
condition
exceptions
mutex
once
recursive_mutex
read_write_mutex
thread
tss_hooks
tss_dll
tss_pe
tss
xtime
;
# pthreads is compiled on all platforms when available
if [ threads::is-pthread-available ] {
template pthread_base
: ## sources ##
[ threads::cpp_source ../src/pthread :
thread
mutex
recursive_mutex
condition
exceptions
xtime
once
tss
]
: ## requirements ##
threads::lib-pthread
<sysinclude>$(BOOST_ROOT)
<threading>multi
<define>BOOST_THREAD_POSIX
common-variant-tag
<borland><*><cxxflags>-w-8004
<borland><*><cxxflags>-w-8057
;
template boost_thread_lib_base
: ## sources ##
<template>thread_base
../src/$(CPP_SOURCES).cpp
: ## requirements ##
<sysinclude>$(BOOST_ROOT) #:should be unnecessary (because already included in thread_base)
<define>BOOST_THREAD_BUILD_LIB=1
# the common names rule ensures that the library will
# be named according to the rules used by the install
# and auto-link features:
common-variant-tag
: ## default build ##
;
lib boost_thread_pthread
: <template>pthread_base
: ## requirements ##
<define>BOOST_THREAD_BUILD_LIB=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 ##
;
dll boost_thread_pthread
: <template>pthread_base
: ## requirements ##
<runtime-link>dynamic
<define>BOOST_THREAD_BUILD_DLL=1
;
lib $(boost_thread_lib_name)
: ## sources ##
<template>boost_thread_lib_base
: ## requirements ##
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name)
: ## default build ##
;
stage bin-stage
: <dll>boost_thread_pthread
<lib>boost_thread_pthread
;
dll $(boost_thread_lib_name)
: ## sources ##
<template>boost_thread_dll_base
: ## requirements ##
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name)
: ## default build ##
;
install thread_pthread lib
: <dll>boost_thread_pthread
<lib>boost_thread_pthread
;
stage bin-stage
: <dll>$(boost_thread_lib_name)
<lib>$(boost_thread_lib_name)
;
# the next is true on platforms where pthreads is native threading lib
if [ threads::is-native-on-build-os pthread ] {
lib boost_thread
: <template>pthread_base
: ## requirements ##
<define>BOOST_THREAD_BUILD_LIB=1
;
install thread lib
: <dll>$(boost_thread_lib_name)
<lib>$(boost_thread_lib_name)
;
if $(boost_thread_lib_settings_ptw32)
{
lib $(boost_thread_lib_name_ptw32)
: ## sources ##
<template>boost_thread_lib_base
: ## requirements ##
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name_ptw32)
$(boost_thread_lib_settings_ptw32)
: ## default build ##
;
dll $(boost_thread_lib_name_ptw32)
: ## sources ##
<template>boost_thread_dll_base
: ## requirements ##
<define>BOOST_THREAD_LIB_NAME=$(boost_thread_lib_name_ptw32)
$(boost_thread_lib_settings_ptw32)
: ## default build ##
;
stage bin-stage
: <dll>$(boost_thread_lib_name_ptw32)
<lib>$(boost_thread_lib_name_ptw32)
;
install thread lib
: <dll>$(boost_thread_lib_name_ptw32)
<lib>$(boost_thread_lib_name_ptw32)
;
}
dll boost_thread
: <template>pthread_base
: ## requirements ##
<runtime-link>dynamic
<define>BOOST_THREAD_BUILD_DLL=1
;
}
}
if [ threads::is-native-on-build-os win32 ] {
template win32_base
: ## sources ##
[ threads::cpp_source ../src/win32 :
thread
exceptions
xtime
tss
tss_hooks
tss_dll
tss_pe
]
: ## requirements ##
<sysinclude>$(BOOST_ROOT)
<threading>multi
common-variant-tag
<borland><*><cxxflags>-w-8004
<borland><*><cxxflags>-w-8057
;
lib boost_thread
: <template>win32_base
: ## requirements ##
<define>BOOST_THREAD_BUILD_LIB=1
;
dll boost_thread
: <template>win32_base
: ## requirements ##
<runtime-link>dynamic
<define>BOOST_THREAD_BUILD_DLL=1
;
}
stage bin-stage
: <dll>boost_thread
<lib>boost_thread
;
install thread lib
: <dll>boost_thread
<lib>boost_thread
;

View File

@@ -1,26 +1,61 @@
import os ;
# 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.
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 ;
}
import thread ;
project boost/thread
: source-location ../src
: usage-requirements $(usage)
: requirements $(reqts) <threading>multi
: default-build <threading>multi
: source-location ../src
: requirements <threading>multi
<link>static:<define>BOOST_THREAD_BUILD_LIB=1
<link>shared:<define>BOOST_THREAD_BUILD_DLL=1
: default-build <threading>multi [ thread.default-api ]
;
CPP_SOURCES = condition mutex recursive_mutex thread xtime once
exceptions barrier tss tss_hooks tss_dll tss_pe ;
# build the pthread based variant
lib boost_thread_pthread
: ## sources ##
pthread/thread.cpp
pthread/mutex.cpp
pthread/recursive_mutex.cpp
pthread/condition.cpp
pthread/exceptions.cpp
pthread/xtime.cpp
pthread/tss.cpp
: ## requirements ##
<define>BOOST_THREAD_POSIX
<thrd-api>pthread
;
# use pthread on platforms where pthread is considered native
lib boost_thread
: ## sources ##
pthread/thread.cpp
pthread/mutex.cpp
pthread/recursive_mutex.cpp
pthread/condition.cpp
pthread/exceptions.cpp
pthread/xtime.cpp
pthread/tss.cpp
: ## requirements ##
<define>BOOST_THREAD_POSIX
<thrd-api>pthread
;
# the win32 native variant
lib boost_thread
: $(CPP_SOURCES).cpp
;
: ## 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
;

70
build/thread.jam Normal file
View File

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

View File

@@ -1,70 +1,65 @@
# Copyright (C) 2001-2003
# William E. Kempf
# Copyright 2006 Roland Schwarz.
# Distributed under the Boost Software License, Version 1.0. (See
# accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
# Permission to use, copy, modify, distribute and sell this software
# and its documentation for any purpose is hereby granted without fee,
# provided that the above copyright notice appear in all copies and
# that both that copyright notice and this permission notice appear
# in supporting documentation. William E. Kempf makes no representations
# about the suitability of this software for any purpose.
# It is provided "as is" without express or implied warranty.
# This work is a reimplementation along the design and ideas
# of William E. Kempf.
# Additional configuration variables used:
# 1. PTW32_DIR and PTW32_LIB may be used on Win32 platforms to specify that
# a version of Boost.Threads should be built that uses the
# the pthreads-win32 library instead of the Win32 native threading APIs.
# This feature is mostly used for testing and it's generally recommended
# that you use the Win32 native threading libraries instead.
#
# PTW32_Dir should be set to the installation path of the
# pthreads-win32 library and PTW32_LIB should be set to the name of the
# library variant to link against (see the pthreads-win32 documentation).
# Example: jam -sPTW32_DIR="c:\pthreads-win32" -sPTW32_LIB="pthreadVCE.lib"
# Alternately, environment variables having the names PTW32_DIR and PTW32_LIB
# can be set instead of passing these values on the command line.
#
# In either case, libraries having the names boost_thread_ptw32<tags>.dll
# and libboost_thread_ptw32<tags>.lib will be built
# in addition to the usual boost_thread<tags>.dll and
# libboost_thread<tags>.lib. Link with one of the ptw32 versions
# of the Boost.Threads libraries to use the version of Boost.Threads
# that is implemented using pthreads-win32 (you will need to #define
# BOOST_THREAD_NO_LIB or BOOST_ALL_NO_LIB to disable auto-linking
# if your platform supports auto-linking in order to prevent
# your build from attempting to link to two different versions of
# the Boost.Threads library).
# Do some OS-specific setup
# find out if pthread is available on current build platform
rule threads::is-pthread-available
{
#thread library name
boost_thread_lib_name = boost_thread ;
#thread library name with "pthreads-win32" library
boost_thread_lib_name_ptw32 = boost_thread_ptw32 ;
if $(NT)
{
if $(PTW32_DIR)
{
if $(PTW32_LIB)
{
boost_thread_lib_settings_ptw32 =
<define>BOOST_HAS_PTHREADS
<define>PtW32NoCatchWarn
<include>$(PTW32_DIR)/pre-built/include
<library-file>$(PTW32_DIR)/pre-built/lib/$(PTW32_LIB)
;
}
}
}
template thread_base
: ## sources ##
: ## requirements ##
<sysinclude>$(BOOST_ROOT)
<threading>multi
<borland><*><cxxflags>-w-8004
<borland><*><cxxflags>-w-8057
: ## default build ##
;
if $(OS) = "NT" {
if $(PTW32_INCLUDE) && $(PTW32_LIB) {
return true ;
}
else {
ECHO "******************************************************" ;
ECHO "Building Boost.Thread without pthread support" ;
ECHO "If you need pthread you should specify the paths." ;
ECHO "For example:" ;
ECHO "PTW32_INCLUDE=C:\\Program Files\\ptw32\\Pre-built2\\include" ;
ECHO "PTW32_LIB=C:\\Program Files\\ptw32\\Pre-built2\\lib\\pthreadVC2.lib" ;
ECHO "******************************************************" ;
}
}
else if $(OS) = "LINUX" {
return true ;
}
else { ## assume pthread is available on unknown os for now
return true ;
}
}
# find the native library variant for current build os
rule threads::is-native-on-build-os ( libvariant )
{
if $(OS) = "NT" {
if $(libvariant) = win32 { return true ; }
}
else if $(OS) = "LINUX" {
if $(libvariant) = pthread { return true ; }
}
else { ## assume pthread is native on others for now
if $(libvariant) = pthread { return true ; }
}
}
# utility to prepend the source path to the cpp sources
rule threads::cpp_source ( path : sources * )
{
return $(path)/$(sources).cpp ;
}
# impose the pthread library and include path on the requirements
rule threads::lib-pthread ( toolset variant : subvariant-path properties * )
{
if $(OS) = "NT" && $(PTW32_INCLUDE) && $(PTW32_LIB) {
properties = [ impose-requirements $(properties) :
<define>BOOST_HAS_PTHREADS
<include>$(PTW32_INCLUDE)
<library-file>$(PTW32_LIB) ] ;
}
return $(subvariant-path) $(properties) ;
}

Binary file not shown.

View File

@@ -1,54 +1,52 @@
# Copyright (C) 2001-2003
# William E. Kempf
# Copyright (C) 2006 Roland Schwarz.
# Distributed under the Boost Software License, Version 1.0. (See
# accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
# Permission to use, copy, modify, distribute and sell this software
# and its documentation for any purpose is hereby granted without fee,
# provided that the above copyright notice appear in all copies and
# that both that copyright notice and this permission notice appear
# in supporting documentation. William E. Kempf makes no representations
# about the suitability of this software for any purpose.
# It is provided "as is" without express or implied warranty.
# This work is a reimplementation along the design and ideas
# of William E. Kempf.
#
# Boost.Threads example Jamfile
#
# Additional configuration variables used:
# 1. PTW32 may be used on Win32 platforms to specify that the pthreads-win32
# library should be used instead of "native" threads. This feature is
# mostly used for testing and it's generally recommended you use the
# native threading libraries instead. PTW32 should be set to be a list
# of two strings, the first specifying the installation path of the
# pthreads-win32 library and the second specifying which library
# variant to link against (see the pthreads-win32 documentation).
# Example: jam -sPTW32="c:\pthreads-win32 pthreadVCE.lib"
# Declare the location of this subproject relative to the root.
subproject libs/thread/example ;
# The threading library is available in two versions.
# Native to the environment or based ontop pthread.
# To select which version to use you need to define
# BOOST_THREAD_POSIX when compiling your sources.
# If BOOST_THREAD_POSIX is defined this will choose
# pthread implementation.
# You also need to specify the correct library version by
# specifying the the <lib> or <dll> tags.
# <lib>@boost/libs/thread/build/boost_thread for static native and
# <lib>@boost/libs/thread/build/boost_thread_pthread static pthread.
# If your compiler does not have the pthread lib in a standard
# include path, you need to specify that too, with <include> and
# <library-file>.
# Include threads.jam for Boost.Threads global build information.
# This greatly simplifies the Jam code needed to configure the build
# for the various Win32 build types.
import ../build/threads ;
project-root ;
{
template example
## sources ##
: <template>thread_base
<dll>../build/boost_thread
## requirements ##
:
## default build ##
:
;
template example
: ## sources ##
<lib>@boost/libs/thread/build/boost_thread
#<lib>@boost/libs/thread/build/boost_thread_pthread
#<dll>@boost/libs/thread/build/boost_thread
#<dll>@boost/libs/thread/build/boost_thread_pthread
: ## requirements ##
<include>$(BOOST_ROOT)
# uncomment below to get pthread on windows
#<define>BOOST_THREAD_POSIX
#<include>$(PTW32_INCLUDE)
#<library-file>$(PTW32_LIB)
: ## default build ##
<threading>multi
;
exe monitor : <template>example monitor.cpp ;
exe starvephil : <template>example starvephil.cpp ;
exe tennis : <template>example tennis.cpp ;
exe condition : <template>example condition.cpp ;
exe mutex : <template>example mutex.cpp ;
exe once : <template>example once.cpp ;
exe recursive_mutex : <template>example recursive_mutex.cpp ;
exe thread : <template>example thread.cpp ;
exe thread_group : <template>example thread_group.cpp ;
exe tss : <template>example tss.cpp ;
exe xtime : <template>example xtime.cpp ;
}
exe monitor : <template>example monitor.cpp ;
exe starvephil : <template>example starvephil.cpp ;
exe tennis : <template>example tennis.cpp ;
exe condition : <template>example condition.cpp ;
exe mutex : <template>example mutex.cpp ;
exe once : <template>example once.cpp ;
exe recursive_mutex : <template>example recursive_mutex.cpp ;
exe thread : <template>example thread.cpp ;
exe thread_group : <template>example thread_group.cpp ;
exe tss : <template>example tss.cpp ;
exe xtime : <template>example xtime.cpp ;

53
example/Jamrules Normal file
View File

@@ -0,0 +1,53 @@
# Copyright 2003 William E. Kempf
# Copyright 2006 Roland Schwarz
# Distributed under the Boost Software License, Version 1.0. (See
# accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
# This work is a reimplementation along the design and ideas
# of William E. Kempf.
project example ;
# If you move this example from its place in the Boost tree, edit this
# path to point at the root directory of your Boost installation (the
# one containing a subdirectory called "boost/".
path-global BOOST_ROOT : ../../.. ;
# Makes a project id for boost so that other Boost.Build projects can
# refer to it by name.
#
project boost : $(BOOST_ROOT) ;
# Attn: path-global was broken in my version of bbv1, which prevented specifying
# BOOST_ROOT as a relative path. So I needed to apply
# the below fix in allyourbase.jam as shown below:
#
#rule project ( name : location ? )
#{
# if ! $(location)
# {
# gPROJECT($(name)) = $(gPROJECT($(PROJECT))) ;
# PROJECT($(gPROJECT($(name)))) = $(name) ;
# PROJECT = $(name) ;
# }
# else
# {
# gPROJECT($(name)) = [ root-paths $(location) : [ root-paths $($(gTOP)) : [ PWD ] ] ] ;
# # speedsnail
# # Root the path globals to fix a bug which prevented to use them from an external
# # project. The fix is as as uninvasive as possible, as it will only trigger when
# # an external project is declared. So it will not interfere with the build of the
# # boost library. I took this route, as at the time of this fix, the bbv1 is expected
# # to be retired soon.
# # N.B.: The path-globals rule is expected to be invoked from Jamrules files only.
# local val ;
# for val in $(gPATH_GLOBALS) {
# gPATH_GLOBAL_VALUE($(val)) = [ root-paths $(gPATH_GLOBAL_VALUE($(val))) :
# [ root-paths $($(gTOP)) : [ PWD ] ]
# ] ;
# }
# local [ protect-subproject ] ;
# enter-subproject @$(name) ;
# }
#}

22
example/boost-build.jam Executable file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,39 +0,0 @@
// 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,104 +0,0 @@
#ifndef BOOST_WIN32_ONCE_HPP
#define BOOST_WIN32_ONCE_HPP
// once.hpp
//
// (C) Copyright 2005 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/detail/win32_thread_primitives.hpp>
namespace boost
{
typedef long once_flag;
#define BOOST_ONCE_INIT 0
namespace detail
{
struct handle_closer
{
void* const handle_to_close;
handle_closer(void* handle_to_close_):
handle_to_close(handle_to_close_)
{}
~handle_closer()
{
BOOST_CLOSE_HANDLE(handle_to_close);
}
};
struct mutex_releaser
{
void* const mutex_to_release;
mutex_releaser(void* mutex_to_release_):
mutex_to_release(mutex_to_release_)
{}
~mutex_releaser()
{
BOOST_RELEASE_MUTEX(mutex_to_release);
}
};
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;
}
}
template<typename Function>
void call_once(Function f,once_flag& flag)
{
//
// Try for a quick win: if the proceedure has already been called
// just skip through:
//
long const function_complete_flag_value=0xc15730e2;
if(!BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag,function_complete_flag_value,
function_complete_flag_value))
{
//
// create a name for our 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":
//
char mutex_name[49+sizeof(void*)*2+sizeof(unsigned long)*2] = { "{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag" };
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), mutex_name + 48);
detail::int_to_string(BOOST_GET_PROCESS_ID(), mutex_name + 48 + sizeof(void*)*2);
BOOST_ASSERT(sizeof(mutex_name) == std::strlen(mutex_name) + 1);
void* const mutex_handle(BOOST_CREATE_MUTEX(NULL, 0, mutex_name));
BOOST_ASSERT(mutex_handle);
detail::handle_closer const closer(mutex_handle);
BOOST_WAIT_FOR_SINGLE_OBJECT(mutex_handle,BOOST_INFINITE);
detail::mutex_releaser const releaser(mutex_handle);
if(!BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag,function_complete_flag_value,
function_complete_flag_value))
{
f();
BOOST_INTERLOCKED_EXCHANGE(&flag,function_complete_flag_value);
}
}
}
}
#endif

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,59 +0,0 @@
// 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,52 +0,0 @@
#ifndef BOOST_WIN32_THREAD_PRIMITIVES_HPP
#define BOOST_WIN32_THREAD_PRIMITIVES_HPP
// win32_thread_primitives.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/config.hpp>
#if defined( BOOST_USE_WINDOWS_H )
# include <windows.h>
# define BOOST_CLOSE_HANDLE ::CloseHandle
# define BOOST_RELEASE_MUTEX ::ReleaseMutex
# define BOOST_CREATE_MUTEX ::CreateMutexA
# define BOOST_GET_PROCESS_ID ::GetCurrentProcessId
# define BOOST_WAIT_FOR_SINGLE_OBJECT ::WaitForSingleObject
# define BOOST_CREATE_SEMAPHORE ::CreateSemaphoreA
# define BOOST_RELEASE_SEMAPHORE ::ReleaseSemaphore
# define BOOST_INFINITE INFINITE
#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
namespace boost
{
namespace detail
{
extern "C" __declspec(dllimport) int __stdcall CloseHandle(void*);
extern "C" __declspec(dllimport) int __stdcall ReleaseMutex(void*);
extern "C" struct _SECURITY_ATTRIBUTES;
extern "C" __declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*);
extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
extern "C" __declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void*,unsigned long);
extern "C" __declspec(dllimport) int __stdcall ReleaseSemaphore(void*,long,long*);
extern "C" __declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*);
}
}
# define BOOST_CLOSE_HANDLE ::boost::detail::CloseHandle
# define BOOST_RELEASE_MUTEX ::boost::detail::ReleaseMutex
# define BOOST_CREATE_MUTEX ::boost::detail::CreateMutexA
# define BOOST_GET_PROCESS_ID ::boost::detail::GetCurrentProcessId
# define BOOST_WAIT_FOR_SINGLE_OBJECT ::boost::detail::WaitForSingleObject
# define BOOST_CREATE_SEMAPHORE ::boost::detail::CreateSemaphoreA
# define BOOST_RELEASE_SEMAPHORE ::boost::detail::ReleaseSemaphore
# define BOOST_INFINITE 0xffffffff
#else
# error "Win32 functions not available"
#endif
#endif

View File

@@ -1,101 +1,16 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright 2006 Roland Schwarz.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_THREAD_EXCEPTIONS_PDM070801_H
#define BOOST_THREAD_EXCEPTIONS_PDM070801_H
#ifndef BOOST_THREAD_RS06040710_HPP
#define BOOST_THREAD_RS06040710_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/platform.hpp>
#include BOOST_THREAD_PLATFORM(exceptions.hpp)
// pdm: Sorry, but this class is used all over the place & I end up
// with recursive headers if I don't separate it
// wek: Not sure why recursive headers would cause compilation problems
// given the include guards, but regardless it makes sense to
// seperate this out any way.
#include <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.
#endif // BOOST_THREAD_RS06040710_HPP

View File

@@ -1,167 +1,16 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright 2006 Roland Schwarz.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_MUTEX_WEK070601_HPP
#define BOOST_MUTEX_WEK070601_HPP
#ifndef BOOST_THREAD_RS06040704_HPP
#define BOOST_THREAD_RS06040704_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/platform.hpp>
#include BOOST_THREAD_PLATFORM(mutex.hpp)
#include <boost/utility.hpp>
#include <boost/thread/detail/lock.hpp>
#endif // BOOST_THREAD_RS06040704_HPP
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
#endif
#if defined(BOOST_HAS_MPTASKS)
# include "scoped_critical_region.hpp"
#endif
namespace boost {
struct xtime;
class BOOST_THREAD_DECL mutex
: private noncopyable
{
public:
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,48 +1,16 @@
// Copyright (C) 2001-2003
// William E. Kempf
#ifndef BOOST_THREAD_ONCE_HPP
#define BOOST_THREAD_ONCE_HPP
// once.hpp
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// (C) Copyright 2006 Anthony Williams
//
// (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)
#ifndef BOOST_ONCE_WEK080101_HPP
#define BOOST_ONCE_WEK080101_HPP
#include <boost/thread/detail/platform.hpp>
#include BOOST_THREAD_PLATFORM(once.hpp)
#include <boost/thread/detail/config.hpp>
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
#endif
#if defined(BOOST_HAS_WINTHREADS)
#include <boost/thread/detail/once_win32.hpp>
#else
namespace boost {
#if defined(BOOST_HAS_PTHREADS)
typedef pthread_once_t once_flag;
#define BOOST_ONCE_INIT PTHREAD_ONCE_INIT
#endif
void BOOST_THREAD_DECL call_once(void (*func)(), once_flag& flag);
} // namespace boost
#endif
// Change Log:
// 1 Aug 01 WEKEMPF Initial version.
// 6 Sep 05 Anthony Williams. Split win32 stuff into detail/once_win32.hpp
#endif // BOOST_ONCE_WEK080101_HPP

View File

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

View File

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

View File

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

View File

@@ -1,21 +1,18 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright 2006 Roland Schwarz.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_XLOCK_WEK070601_HPP
#define BOOST_XLOCK_WEK070601_HPP
#ifndef BOOST_THREAD_RS06040708_HPP
#define BOOST_THREAD_RS06040708_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/pthread/config.hpp>
#include <boost/utility.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/pthread/exceptions.hpp>
namespace boost {
@@ -205,10 +202,4 @@ private:
} // namespace detail
} // namespace boost
#endif // BOOST_XLOCK_WEK070601_HPP
// Change Log:
// 8 Feb 01 WEKEMPF Initial version.
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
// 30 Jul 01 WEKEMPF Moved lock types into boost::detail::thread. Renamed
// some types. Added locked() methods.
#endif // BOOST_THREAD_RS06040708_HPP

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,121 +1,16 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright 2006 Roland Schwarz.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_TSS_WEK070601_HPP
#define BOOST_TSS_WEK070601_HPP
#ifndef BOOST_TSS_RS06092303_HPP
#define BOOST_TSS_RS06092303_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/platform.hpp>
#include BOOST_THREAD_PLATFORM(tss.hpp)
#include <boost/utility.hpp>
#include <boost/function.hpp>
#include <boost/thread/exceptions.hpp>
#endif // BOOST_TSS_RS06092301_HPP
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
#elif defined(BOOST_HAS_MPTASKS)
# include <Multiprocessing.h>
#endif
namespace boost {
namespace detail {
class BOOST_THREAD_DECL tss : private noncopyable
{
public:
tss(boost::function1<void, void*>* pcleanup) {
if (pcleanup == 0) throw boost::thread_resource_error();
try
{
init(pcleanup);
}
catch (...)
{
delete pcleanup;
throw boost::thread_resource_error();
}
}
void* get() const;
void set(void* value);
void cleanup(void* p);
private:
unsigned int m_slot; //This is a "pseudo-slot", not a native slot
void init(boost::function1<void, void*>* pcleanup);
};
#if defined(BOOST_HAS_MPTASKS)
void thread_cleanup();
#endif
template <typename T>
struct tss_adapter
{
template <typename F>
tss_adapter(const F& cleanup) : m_cleanup(cleanup) { }
void operator()(void* p) { m_cleanup(static_cast<T*>(p)); }
boost::function1<void, T*> m_cleanup;
};
} // namespace detail
template <typename T>
class thread_specific_ptr : private noncopyable
{
public:
thread_specific_ptr()
: m_tss(new boost::function1<void, void*>(
boost::detail::tss_adapter<T>(
&thread_specific_ptr<T>::cleanup)))
{
}
thread_specific_ptr(void (*clean)(T*))
: m_tss(new boost::function1<void, void*>(
boost::detail::tss_adapter<T>(clean)))
{
}
~thread_specific_ptr() { reset(); }
T* get() const { return static_cast<T*>(m_tss.get()); }
T* operator->() const { return get(); }
T& operator*() const { return *get(); }
T* release() { T* temp = get(); if (temp) m_tss.set(0); return temp; }
void reset(T* p=0)
{
T* cur = get();
if (cur == p) return;
m_tss.set(p);
if (cur) m_tss.cleanup(cur);
}
private:
static void cleanup(T* p) { delete p; }
detail::tss m_tss;
};
} // namespace boost
#endif //BOOST_TSS_WEK070601_HPP
// Change Log:
// 6 Jun 01
// WEKEMPF Initial version.
// 30 May 02 WEKEMPF
// Added interface to set specific cleanup handlers.
// Removed TLS slot limits from most implementations.
// 22 Mar 04 GlassfordM for WEKEMPF
// Fixed: thread_specific_ptr::reset() doesn't check error returned
// by tss::set(); tss::set() now throws if it fails.
// Fixed: calling thread_specific_ptr::reset() or
// thread_specific_ptr::release() causes double-delete: once on
// reset()/release() and once on ~thread_specific_ptr().

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,16 +1,13 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright 2006 Roland Schwarz.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_THREAD_CONFIG_WEK01032003_HPP
#define BOOST_THREAD_CONFIG_WEK01032003_HPP
#ifndef BOOST_THREAD_RS06041002_HPP
#define BOOST_THREAD_RS06041002_HPP
#include <boost/config.hpp>
@@ -77,10 +74,4 @@
#include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
#endif // BOOST_THREAD_CONFIG_WEK1032003_HPP
// Change Log:
// 22 Jan 05 Roland Schwarz (speedsnail)
// Usage of BOOST_HAS_DECLSPEC macro.
// Default again is static lib usage.
// BOOST_DYN_LINK only defined when autolink included.
#endif // BOOST_THREAD_RS06041002_HPP

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,14 +1,16 @@
// (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)
// 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.
#if !defined(BOOST_TLS_HOOKS_HPP)
#define BOOST_TLS_HOOKS_HPP
#ifndef BOOST_TLS_HOOKS_RS06092306_HPP
#define BOOST_TLS_HOOKS_RS06092306_HPP
#include <boost/thread/detail/config.hpp>
#if defined(BOOST_HAS_WINTHREADS)
#include <boost/thread/win32/config.hpp>
typedef void (__cdecl *thread_exit_handler)(void);
@@ -20,16 +22,12 @@
//Currently only implemented for Win32, but should
//later be implemented for all platforms.
//Used by Win32 implementation of Boost.Threads
//tss to peform cleanup.
//tss to perform cleanup.
//Like the C runtime library atexit() function,
//which it mimics, at_thread_exit() returns
//zero if successful and a nonzero
//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
@@ -73,6 +71,4 @@
//cleanup has been implemented and to force
//it to be linked into the Boost.Threads library.
#endif //defined(BOOST_HAS_WINTHREADS)
#endif //!defined(BOOST_TLS_HOOKS_HPP)
#endif //BOOST_TLS_HOOKS_RS06092306_HPP

View File

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

View File

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

View File

@@ -1,59 +1,16 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright 2006 Roland Schwarz.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// This work is a reimplementation along the design and ideas
// of William E. Kempf.
#ifndef BOOST_XTIME_WEK070601_HPP
#define BOOST_XTIME_WEK070601_HPP
#ifndef BOOST_THREAD_RS06040712_HPP
#define BOOST_THREAD_RS06040712_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/detail/platform.hpp>
#include BOOST_THREAD_PLATFORM(xtime.hpp)
#include <boost/cstdint.hpp>
#endif // BOOST_THREAD_RS06040712_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,47 +0,0 @@
// Copyright (C) 2002-2003
// David Moore, William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#include <boost/thread/detail/config.hpp>
#include <boost/thread/barrier.hpp>
#include <string> // see http://article.gmane.org/gmane.comp.lib.boost.devel/106981
namespace boost {
barrier::barrier(unsigned int count)
: m_threshold(count), m_count(count), m_generation(0)
{
if (count == 0)
throw std::invalid_argument("count cannot be zero.");
}
barrier::~barrier()
{
}
bool barrier::wait()
{
boost::mutex::scoped_lock lock(m_mutex);
unsigned int gen = m_generation;
if (--m_count == 0)
{
m_generation++;
m_count = m_threshold;
m_cond.notify_all();
return true;
}
while (gen == m_generation)
m_cond.wait(lock);
return false;
}
} // namespace boost

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,52 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
//
// includes
//
#include <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

@@ -1,99 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
//
// includes
//
#include <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

@@ -1,150 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#include <cassert>
// 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));
}

View File

@@ -1,57 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#include "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

View File

@@ -1,37 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#ifndef BOOST_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

View File

@@ -1,46 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#include "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

View File

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

View File

@@ -1,76 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#ifndef BOOST_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

View File

@@ -1,97 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#ifndef BOOST_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

View File

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

View File

@@ -1,48 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#include "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

@@ -1,102 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#ifndef BOOST_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

View File

@@ -1,157 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#ifndef BOOST_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

View File

@@ -1,210 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#include <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

View File

@@ -1,41 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#ifndef BOOST_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

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

@@ -1,63 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#ifndef BOOST_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

View File

@@ -1,85 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#include "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

View File

@@ -1,67 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#ifndef BOOST_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

@@ -1,56 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#include "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

@@ -1,36 +0,0 @@
// (C) Copyright Mac Murrett 2001.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org for most recent version.
#ifndef BOOST_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

View File

@@ -1,566 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#include <boost/thread/detail/config.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/limits.hpp>
#include <string>
#include <stdexcept>
#include <cassert>
#include "timeconv.inl"
#if defined(BOOST_HAS_WINTHREADS)
# include <new>
# include <boost/thread/once.hpp>
# include <windows.h>
# include <time.h>
# include "mutex.inl"
#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 {
#if defined(BOOST_HAS_WINTHREADS)
mutex::mutex()
: m_mutex(0)
, m_critical_section(false)
{
m_critical_section = true;
if (m_critical_section)
m_mutex = new_critical_section();
else
m_mutex = new_mutex(0);
}
mutex::~mutex()
{
if (m_critical_section)
delete_critical_section(m_mutex);
else
delete_mutex(m_mutex);
}
void mutex::do_lock()
{
if (m_critical_section)
wait_critical_section_infinite(m_mutex);
else
wait_mutex(m_mutex, INFINITE);
}
void mutex::do_unlock()
{
if (m_critical_section)
release_critical_section(m_mutex);
else
release_mutex(m_mutex);
}
void mutex::do_lock(cv_state&)
{
do_lock();
}
void mutex::do_unlock(cv_state&)
{
do_unlock();
}
try_mutex::try_mutex()
: m_mutex(0)
, m_critical_section(false)
{
m_critical_section = has_TryEnterCriticalSection();
if (m_critical_section)
m_mutex = new_critical_section();
else
m_mutex = new_mutex(0);
}
try_mutex::~try_mutex()
{
if (m_critical_section)
delete_critical_section(m_mutex);
else
delete_mutex(m_mutex);
}
void try_mutex::do_lock()
{
if (m_critical_section)
wait_critical_section_infinite(m_mutex);
else
wait_mutex(m_mutex, INFINITE);
}
bool try_mutex::do_trylock()
{
if (m_critical_section)
return wait_critical_section_try(m_mutex);
else
return wait_mutex(m_mutex, 0) == WAIT_OBJECT_0;
}
void try_mutex::do_unlock()
{
if (m_critical_section)
release_critical_section(m_mutex);
else
release_mutex(m_mutex);
}
void try_mutex::do_lock(cv_state&)
{
do_lock();
}
void try_mutex::do_unlock(cv_state&)
{
do_unlock();
}
timed_mutex::timed_mutex()
: m_mutex(0)
{
m_mutex = new_mutex(0);
}
timed_mutex::~timed_mutex()
{
delete_mutex(m_mutex);
}
void timed_mutex::do_lock()
{
wait_mutex(m_mutex, INFINITE);
}
bool timed_mutex::do_trylock()
{
return wait_mutex(m_mutex, 0) == WAIT_OBJECT_0;
}
bool timed_mutex::do_timedlock(const xtime& xt)
{
for (;;)
{
int milliseconds;
to_duration(xt, milliseconds);
int res = wait_mutex(m_mutex, milliseconds);
if (res == WAIT_TIMEOUT)
{
boost::xtime cur;
boost::xtime_get(&cur, boost::TIME_UTC);
if (boost::xtime_cmp(xt, cur) > 0)
continue;
}
return res == WAIT_OBJECT_0;
}
}
void timed_mutex::do_unlock()
{
release_mutex(m_mutex);
}
void timed_mutex::do_lock(cv_state&)
{
do_lock();
}
void timed_mutex::do_unlock(cv_state&)
{
do_unlock();
}
#elif defined(BOOST_HAS_PTHREADS)
mutex::mutex()
{
int res = 0;
res = pthread_mutex_init(&m_mutex, 0);
if (res != 0)
throw thread_resource_error();
}
mutex::~mutex()
{
int res = 0;
res = pthread_mutex_destroy(&m_mutex);
assert(res == 0);
}
void mutex::do_lock()
{
int res = 0;
res = pthread_mutex_lock(&m_mutex);
if (res == EDEADLK) throw lock_error();
assert(res == 0);
}
void mutex::do_unlock()
{
int res = 0;
res = pthread_mutex_unlock(&m_mutex);
if (res == EPERM) throw lock_error();
assert(res == 0);
}
void mutex::do_lock(cv_state&)
{
}
void mutex::do_unlock(cv_state& state)
{
state.pmutex = &m_mutex;
}
try_mutex::try_mutex()
{
int res = 0;
res = pthread_mutex_init(&m_mutex, 0);
if (res != 0)
throw thread_resource_error();
}
try_mutex::~try_mutex()
{
int res = 0;
res = pthread_mutex_destroy(&m_mutex);
assert(res == 0);
}
void try_mutex::do_lock()
{
int res = 0;
res = pthread_mutex_lock(&m_mutex);
if (res == EDEADLK) throw lock_error();
assert(res == 0);
}
bool try_mutex::do_trylock()
{
int res = 0;
res = pthread_mutex_trylock(&m_mutex);
if (res == EDEADLK) throw lock_error();
assert(res == 0 || res == EBUSY);
return res == 0;
}
void try_mutex::do_unlock()
{
int res = 0;
res = pthread_mutex_unlock(&m_mutex);
if (res == EPERM) throw lock_error();
assert(res == 0);
}
void try_mutex::do_lock(cv_state&)
{
}
void try_mutex::do_unlock(cv_state& state)
{
state.pmutex = &m_mutex;
}
timed_mutex::timed_mutex()
: m_locked(false)
{
int res = 0;
res = pthread_mutex_init(&m_mutex, 0);
if (res != 0)
throw thread_resource_error();
res = pthread_cond_init(&m_condition, 0);
if (res != 0)
{
pthread_mutex_destroy(&m_mutex);
throw thread_resource_error();
}
}
timed_mutex::~timed_mutex()
{
assert(!m_locked);
int res = 0;
res = pthread_mutex_destroy(&m_mutex);
assert(res == 0);
res = pthread_cond_destroy(&m_condition);
assert(res == 0);
}
void timed_mutex::do_lock()
{
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
while (m_locked)
{
res = pthread_cond_wait(&m_condition, &m_mutex);
assert(res == 0);
}
assert(!m_locked);
m_locked = true;
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
}
bool timed_mutex::do_trylock()
{
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
bool ret = false;
if (!m_locked)
{
m_locked = true;
ret = true;
}
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
return ret;
}
bool timed_mutex::do_timedlock(const xtime& xt)
{
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
timespec ts;
to_timespec(xt, ts);
while (m_locked)
{
res = pthread_cond_timedwait(&m_condition, &m_mutex, &ts);
assert(res == 0 || res == ETIMEDOUT);
if (res == ETIMEDOUT)
break;
}
bool ret = false;
if (!m_locked)
{
m_locked = true;
ret = true;
}
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
return ret;
}
void timed_mutex::do_unlock()
{
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
assert(m_locked);
m_locked = false;
res = pthread_cond_signal(&m_condition);
assert(res == 0);
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
}
void timed_mutex::do_lock(cv_state&)
{
int res = 0;
while (m_locked)
{
res = pthread_cond_wait(&m_condition, &m_mutex);
assert(res == 0);
}
assert(!m_locked);
m_locked = true;
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
}
void timed_mutex::do_unlock(cv_state& state)
{
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
assert(m_locked);
m_locked = false;
res = pthread_cond_signal(&m_condition);
assert(res == 0);
state.pmutex = &m_mutex;
}
#elif defined(BOOST_HAS_MPTASKS)
using threads::mac::detail::safe_enter_critical_region;
mutex::mutex()
{
}
mutex::~mutex()
{
}
void mutex::do_lock()
{
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
m_mutex_mutex);
assert(lStatus == noErr);
}
void mutex::do_unlock()
{
OSStatus lStatus = noErr;
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
}
void mutex::do_lock(cv_state& /*state*/)
{
do_lock();
}
void mutex::do_unlock(cv_state& /*state*/)
{
do_unlock();
}
try_mutex::try_mutex()
{
}
try_mutex::~try_mutex()
{
}
void try_mutex::do_lock()
{
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
m_mutex_mutex);
assert(lStatus == noErr);
}
bool try_mutex::do_trylock()
{
OSStatus lStatus = noErr;
lStatus = MPEnterCriticalRegion(m_mutex, kDurationImmediate);
assert(lStatus == noErr || lStatus == kMPTimeoutErr);
return lStatus == noErr;
}
void try_mutex::do_unlock()
{
OSStatus lStatus = noErr;
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
}
void try_mutex::do_lock(cv_state& /*state*/)
{
do_lock();
}
void try_mutex::do_unlock(cv_state& /*state*/)
{
do_unlock();
}
timed_mutex::timed_mutex()
{
}
timed_mutex::~timed_mutex()
{
}
void timed_mutex::do_lock()
{
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
m_mutex_mutex);
assert(lStatus == noErr);
}
bool timed_mutex::do_trylock()
{
OSStatus lStatus = noErr;
lStatus = MPEnterCriticalRegion(m_mutex, kDurationImmediate);
assert(lStatus == noErr || lStatus == kMPTimeoutErr);
return(lStatus == noErr);
}
bool timed_mutex::do_timedlock(const xtime& xt)
{
int microseconds;
to_microduration(xt, microseconds);
Duration lDuration = kDurationMicrosecond * microseconds;
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, lDuration, m_mutex_mutex);
assert(lStatus == noErr || lStatus == kMPTimeoutErr);
return(lStatus == noErr);
}
void timed_mutex::do_unlock()
{
OSStatus lStatus = noErr;
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
}
void timed_mutex::do_lock(cv_state& /*state*/)
{
do_lock();
}
void timed_mutex::do_unlock(cv_state& /*state*/)
{
do_unlock();
}
#endif
} // namespace boost
// Change Log:
// 8 Feb 01 WEKEMPF Initial version.

View File

@@ -1,124 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
namespace {
#if defined(BOOST_HAS_WINTHREADS)
//:PREVENT THIS FROM BEING DUPLICATED
typedef BOOL (WINAPI* TryEnterCriticalSection_type)(LPCRITICAL_SECTION lpCriticalSection);
TryEnterCriticalSection_type g_TryEnterCriticalSection = 0;
boost::once_flag once_init_TryEnterCriticalSection = BOOST_ONCE_INIT;
void init_TryEnterCriticalSection()
{
//TryEnterCriticalSection is only available on WinNT 4.0 or later;
//it is not available on Win9x.
OSVERSIONINFO version_info = {sizeof(OSVERSIONINFO)};
::GetVersionEx(&version_info);
if (version_info.dwPlatformId == VER_PLATFORM_WIN32_NT &&
version_info.dwMajorVersion >= 4)
{
if (HMODULE kernel_module = GetModuleHandle(TEXT("KERNEL32.DLL")))
g_TryEnterCriticalSection = reinterpret_cast<TryEnterCriticalSection_type>(GetProcAddress(kernel_module, "TryEnterCriticalSection"));
}
}
inline bool has_TryEnterCriticalSection()
{
boost::call_once(init_TryEnterCriticalSection, once_init_TryEnterCriticalSection);
return g_TryEnterCriticalSection != 0;
}
inline HANDLE mutex_cast(void* p)
{
return reinterpret_cast<HANDLE>(p);
}
inline LPCRITICAL_SECTION critical_section_cast(void* p)
{
return reinterpret_cast<LPCRITICAL_SECTION>(p);
}
inline void* new_critical_section()
{
try
{
LPCRITICAL_SECTION critical_section = new CRITICAL_SECTION;
if (critical_section == 0) throw boost::thread_resource_error();
InitializeCriticalSection(critical_section);
return critical_section;
}
catch(...)
{
throw boost::thread_resource_error();
}
}
inline void* new_mutex(const char* name)
{
#if defined(BOOST_NO_ANSI_APIS)
USES_CONVERSION;
HANDLE mutex = CreateMutexW(0, 0, A2CW(name));
#else
HANDLE mutex = CreateMutexA(0, 0, name);
#endif
if (mutex == 0 || mutex == INVALID_HANDLE_VALUE) //:xxx (check for both values?)
throw boost::thread_resource_error();
return reinterpret_cast<void*>(mutex);
}
inline void delete_critical_section(void* mutex)
{
DeleteCriticalSection(critical_section_cast(mutex));
delete critical_section_cast(mutex);
}
inline void delete_mutex(void* mutex)
{
int res = 0;
res = CloseHandle(mutex_cast(mutex));
assert(res);
}
inline void wait_critical_section_infinite(void* mutex)
{
EnterCriticalSection(critical_section_cast(mutex)); //:xxx Can throw an exception under low memory conditions
}
inline bool wait_critical_section_try(void* mutex)
{
BOOL res = g_TryEnterCriticalSection(critical_section_cast(mutex));
return res != 0;
}
inline int wait_mutex(void* mutex, int time)
{
unsigned int res = 0;
res = WaitForSingleObject(mutex_cast(mutex), time);
//:xxx assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
return res;
}
inline void release_critical_section(void* mutex)
{
LeaveCriticalSection(critical_section_cast(mutex));
}
inline void release_mutex(void* mutex)
{
BOOL res = FALSE;
res = ReleaseMutex(mutex_cast(mutex));
assert(res);
}
#endif
}

View File

@@ -1,99 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#include <boost/thread/detail/config.hpp>
#ifndef BOOST_HAS_WINTHREADS
#include <boost/detail/workaround.hpp>
#include <boost/thread/once.hpp>
#include <cstdio>
#include <cassert>
#if defined(BOOST_HAS_MPTASKS)
# include <Multiprocessing.h>
#endif
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::sprintf; }
#endif
#if defined(BOOST_HAS_PTHREADS)
namespace {
pthread_key_t key;
pthread_once_t once = PTHREAD_ONCE_INIT;
typedef void (*once_callback)();
}
extern "C" {
static void key_init()
{
pthread_key_create(&key, 0);
}
static void do_once()
{
once_callback* cb = reinterpret_cast<once_callback*>(
pthread_getspecific(key));
(**cb)();
}
}
#elif defined(BOOST_HAS_MPTASKS)
namespace {
void *remote_call_proxy(void *pData)
{
std::pair<void (*)(), boost::once_flag *> &rData(
*reinterpret_cast<std::pair<void (*)(), boost::once_flag *> *>(pData));
if(*rData.second == false)
{
rData.first();
*rData.second = true;
}
return(NULL);
}
}
#endif
namespace boost {
void call_once(void (*func)(), once_flag& flag)
{
#if defined(BOOST_HAS_PTHREADS)
pthread_once(&once, &key_init);
pthread_setspecific(key, &func);
pthread_once(&flag, do_once);
#elif defined(BOOST_HAS_MPTASKS)
if(flag == false)
{
// all we do here is make a remote call to blue, as blue is not
// reentrant.
std::pair<void (*)(), once_flag *> sData(func, &flag);
MPRemoteCall(remote_call_proxy, &sData, kMPOwningProcessRemoteContext);
assert(flag == true);
}
#endif
}
}
#endif
// Change Log:
// 1 Aug 01 WEKEMPF Initial version.
// 6 Sep 05 Anthony Williams. Removed win32 implementation

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