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

Compare commits

...

455 Commits

Author SHA1 Message Date
Beman Dawes
9c5df23f20 1.37.0 Beta 1
[SVN r49441]
2008-10-23 11:39:59 +00:00
Anthony Williams
0997fad8ec Merged Boost.Thread changes from trunk
[SVN r49324]
2008-10-13 20:30:13 +00:00
Anthony Williams
8749696538 Merged Thread doc changes from trunk
[SVN r48038]
2008-08-08 20:38:50 +00:00
Anthony Williams
9beea23f63 Merged thread doc changes from trunk
[SVN r47827]
2008-07-26 08:39:51 +00:00
Anthony Williams
2978d43a5d Merged thread doc changes from trunk
[SVN r47701]
2008-07-23 09:37:02 +00:00
Anthony Williams
a264766584 Merged changes over from trunk
[SVN r47700]
2008-07-23 09:35:40 +00:00
Anthony Williams
f03a9bfcf3 Merged thread changes from trunk
[SVN r47211]
2008-07-08 07:44:55 +00:00
Anthony Williams
60fdcddcb5 Merge of new boost.thread code along with required changes from boost.bind
[SVN r46474]
2008-06-18 13:01:08 +00:00
Anthony Williams
525d190f91 removed declaration of undefined type exclusive_lock
[SVN r43850]
2008-03-25 07:59:58 +00:00
Anthony Williams
1e0154335b Imported revision #43730 from trunk to eliminate some warnings
[SVN r43743]
2008-03-21 15:04:10 +00:00
Anthony Williams
413c29a5e4 New documentation for thread library imported from trunk revision 43671
[SVN r43674]
2008-03-17 13:59:17 +00:00
Anthony Williams
30bb6143c1 Test and fix for bug #1693 to ensure thread_specific_ptr::release works as desired imported from trunk changeset 43666
[SVN r43673]
2008-03-17 13:46:19 +00:00
Anthony Williams
991ac727c6 Imported changeset 43461 to fix issue #1665
[SVN r43520]
2008-03-05 20:47:56 +00:00
Daniel James
569a78649f Merged revisions 43211,43214-43219,43222-43225,43227-43238,43242,43244-43245,43249-43250,43257-43259,43261,43263,43265,43267-43268,43270-43271,43273,43275-43279,43284-43289,43291,43295,43297-43298,43304-43305,43307,43313,43315,43324,43326-43327,43331,43333,43339-43343,43345,43348,43350,43352-43353,43355-43356,43358,43360,43366-43367,43369-43370,43372-43376,43378-43389,43394,43396-43398,43400-43401,43403-43404,43406-43408,43413-43415,43417-43418,43420,43422-43423 via svnmerge from
https://svn.boost.org/svn/boost/trunk

........
  r43417 | danieljames | 2008-02-26 22:04:55 +0000 (Tue, 26 Feb 2008) | 2 lines
  
  Fix a link to Boost.Bimap.
........
  r43418 | danieljames | 2008-02-26 22:07:25 +0000 (Tue, 26 Feb 2008) | 2 lines
  
  Change another link that's no longer in the repository to link to the website.
........
  r43422 | danieljames | 2008-02-27 18:51:14 +0000 (Wed, 27 Feb 2008) | 1 line
  
  Fix broken copyright urls. Fixes #1573.
........
  r43423 | danieljames | 2008-02-27 19:22:01 +0000 (Wed, 27 Feb 2008) | 1 line
  
  Fix incorrect links to copyright of the form 'http:#www.boost.org
........


[SVN r43425]
2008-02-27 20:00:24 +00:00
Anthony Williams
7caec1ec33 Fix for ticket #1547 --- Change use of NULL to 0
[SVN r43268]
2008-02-15 17:56:13 +00:00
Anthony Williams
7fd3fb48b1 Pulling changeset 43094 over from trunk
[SVN r43227]
2008-02-12 20:49:56 +00:00
Anthony Williams
a32a3b37db Merged latest changes to boost.thread over from trunk
[SVN r42230]
2007-12-21 11:51:05 +00:00
Beman Dawes
88f6076f3c Full merge from trunk at revision 41356 of entire boost-root tree.
[SVN r41370]
2007-11-25 18:38:02 +00:00
Beman Dawes
b4d12e08dd Full merge from trunk at revision 41356 of entire boost-root tree.
[SVN r41369]
2007-11-25 18:07:19 +00:00
Anthony Williams
332dd988e4 Integrate TSS with thread data; test to ensure cleanup done for native threads as well as boost::thread-launched threads now runs for pthread API as well as win32 API
[SVN r41320]
2007-11-23 23:09:36 +00:00
Anthony Williams
bce8db41d7 Removed thread::self in favour of allowing interruption through a thread::id; no longer requires DuplicateHandle
[SVN r41311]
2007-11-22 22:01:30 +00:00
Anthony Williams
f6fd70245d changed platform split to allow bjam to track includes and check dependencies
[SVN r41273]
2007-11-21 10:44:22 +00:00
Anthony Williams
4ff0a055d6 added copyright
[SVN r41226]
2007-11-19 14:29:22 +00:00
Anthony Williams
c9140267a5 fixed problems with TSS cleanup when using LoadLibrary and when threads finish after thread_specific_ptr instance has been destroyed
[SVN r41223]
2007-11-19 12:29:14 +00:00
Anthony Williams
72fcee4e5e fixed TSS cleanup on 64-bit Windows
[SVN r41222]
2007-11-19 12:17:31 +00:00
Beman Dawes
9c8e512edd // Add or correct comment identifying Boost library this header is associated with.
[SVN r41173]
2007-11-17 20:13:16 +00:00
Anthony Williams
3c191af34a New implementation of pthread_once based on Mike Burrows' algorithm
[SVN r41160]
2007-11-16 22:51:52 +00:00
Beman Dawes
5e0b2d7370 Get rid of .cvsignore files
[SVN r41107]
2007-11-15 15:20:27 +00:00
Anthony Williams
5994abd453 fixes for pthread implementation
[SVN r41090]
2007-11-14 14:49:58 +00:00
Anthony Williams
67a2d119c0 interrupt and join all threads in a group if an exception is thrown during a test
[SVN r41087]
2007-11-14 12:17:41 +00:00
Anthony Williams
114215088a interrupt and join all threads in a group if an exception is thrown during a test
[SVN r41084]
2007-11-14 11:56:53 +00:00
Anthony Williams
a78e2b793e ignore and join all threads in group on exception
[SVN r41083]
2007-11-14 11:08:09 +00:00
Anthony Williams
519ed3834e Integrated TSS with storage of thread data; cleaned up the heap allocation functions to throw bad_alloc if they run out of memory
[SVN r41056]
2007-11-13 09:27:11 +00:00
Roland Schwarz
22647135fa Added static linking support for mingw compiler on windows.
[SVN r40999]
2007-11-10 19:25:45 +00:00
Roland Schwarz
58c741e9ca Reverted the previous commit, until I find a better solution...
[SVN r40959]
2007-11-09 09:28:29 +00:00
Roland Schwarz
ef9083089e Force static linking for toolsets mingw and boorland.
[SVN r40958]
2007-11-09 08:31:45 +00:00
Anthony Williams
5de1582a0a Added missing licence and copyright
[SVN r40884]
2007-11-07 12:10:17 +00:00
Anthony Williams
39c864e31f use condition so we know when threads have unblocked, to avoid hard-coding a delay
[SVN r40846]
2007-11-06 17:15:50 +00:00
Anthony Williams
320cb63df4 Use BOOST_VERIFY instead of BOOST_ASSERT in many places in order to avoid unused variable warnings
[SVN r40792]
2007-11-05 16:47:25 +00:00
Roland Schwarz
c246222ded Cosmetic change to please gcc.
[SVN r40791]
2007-11-05 16:22:17 +00:00
Roland Schwarz
b7edb2873c Usage requirements added.
[SVN r40790]
2007-11-05 16:12:49 +00:00
Anthony Williams
89f2032c0d Use pthread_equal for comparing pthread_t IDs; use BOOST_VERIFY instead of BOOST_ASSERT in many places in order to avoid unused variable warnings
[SVN r40787]
2007-11-05 14:16:21 +00:00
Anthony Williams
d2f8230093 threadapi is a composite feature again
[SVN r40774]
2007-11-05 10:15:24 +00:00
Roland Schwarz
9f6b5d169a Get rid of "unsused variable" warnings by making use of BOOST_VERIFY.
This changeset is for pthread only.


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

in libs/<library>/build.


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

[SVN r38286]
2007-07-24 19:28:14 +00:00
Thomas Witt
8f61694057 Fix #1039.
[SVN r37948]
2007-06-08 18:48:50 +00:00
Thomas Witt
67f7de5305 Fix #996.
[SVN r37815]
2007-05-29 17:12:59 +00:00
Anthony Williams
6faecefb73 Fix for ticket #906
[SVN r37740]
2007-05-22 15:38:58 +00:00
Anthony Williams
68c5bd44e8 undone accidental commit
[SVN r37647]
2007-05-09 07:04:46 +00:00
Anthony Williams
3656277053 Removed read_write_mutex source files and header
[SVN r37646]
2007-05-09 07:02:13 +00:00
Thomas Witt
19846ff356 Fix Xml error. This change is already in HEAD.
[SVN r37499]
2007-04-24 16:11:17 +00:00
Rene Rivera
a11bd6ebd9 Put in the build support for using the doxproc, Python based, Doxygen to BoostBook translator.
[SVN r37457]
2007-04-17 04:44:59 +00:00
Roland Schwarz
db2aaa04fd Merged from HEAD.
[SVN r36923]
2007-02-11 13:55:21 +00:00
Roland Schwarz
9889bf50a2 FAQ Entry: Passing parameters during thread creation.
[SVN r36922]
2007-02-11 13:52:28 +00:00
Roland Schwarz
b48f9aa609 Merged patch from trunk.
[SVN r36921]
2007-02-11 13:14:44 +00:00
Roland Schwarz
d75fb2deda Applying long outstanding patch.
See:http://thread.gmane.org/gmane.comp.lib.boost.devel/118863/focus=118912


[SVN r36920]
2007-02-11 12:00:38 +00:00
Anthony Williams
7915ab1ec6 Fixed typos and improved phrasing
[SVN r36751]
2007-01-18 17:33:50 +00:00
Roland Schwarz
f0faf88d66 Updated the build instructions and acknowledgements.
[SVN r36706]
2007-01-12 16:48:02 +00:00
Roland Schwarz
7dd7537f5f renamed back to .v2 since build process is broken otherwise.
[SVN r36641]
2007-01-07 14:53:25 +00:00
Roland Schwarz
f51680e8d9 Renamed Jamfile.
[SVN r36640]
2007-01-07 14:08:02 +00:00
Roland Schwarz
a6bc072c6d removing obsolete files
[SVN r36639]
2007-01-07 14:05:30 +00:00
Roland Schwarz
85f2508157 Updating build instructions.
[SVN r36638]
2007-01-07 12:33:42 +00:00
Roland Schwarz
ebb6c8d637 Corrected a typo; more prominent note of unavailability of RW-Mutex.
[SVN r36565]
2007-01-02 21:44:39 +00:00
Roland Schwarz
ddc83e270c Corrected a typo, and reactivated links to read_write mutex.
[SVN r36560]
2007-01-01 16:45:52 +00:00
Roland Schwarz
0173148a2e Recovered file, since it is linked to rest of doc.
[SVN r36559]
2007-01-01 14:10:28 +00:00
Roland Schwarz
69a4ec6c00 QNX debuging
[SVN r36489]
2006-12-22 13:40:38 +00:00
Roland Schwarz
2d52219af2 Merged from HEAD
[SVN r36488]
2006-12-22 10:38:23 +00:00
Roland Schwarz
6355a5b28d Changes for WINCE
[SVN r36484]
2006-12-22 09:40:17 +00:00
Roland Schwarz
1f87a9e4c0 Temporary test code for QNX debugging.
[SVN r36430]
2006-12-16 16:17:55 +00:00
Roland Schwarz
ba8afde42b Additional asserions in an attempt to find the errors on QNX.
[SVN r36395]
2006-12-14 21:44:20 +00:00
Roland Schwarz
93f677cba6 Changed back to CHECK since WARNING not showing up in regression tables.
[SVN r36387]
2006-12-14 17:51:25 +00:00
Roland Schwarz
595bbee41e Converted back to CHECK since warnings not showing up in regression tables.
[SVN r36386]
2006-12-14 17:49:21 +00:00
Roland Schwarz
dfd865d67d Fixed missing tss_null file.
[SVN r36332]
2006-12-11 19:51:14 +00:00
Roland Schwarz
cb3f3a1f64 Fixed the missing tss_nul file for testing.
[SVN r36331]
2006-12-11 19:22:40 +00:00
Vladimir Prus
96a04402db Merge from HEAD.
Allow building of shared versions of some Boost.Test libraries.
Adjust tests to use always use static linking to Boost.Test, since
linking to the shared version requires test changes.

Patch from Juergen Hunold.


[SVN r35990]
2006-11-10 19:59:52 +00:00
Vladimir Prus
0e44838905 Allow building of shared versions of some Boost.Test libraries.
Adjust tests to use always use static linking to Boost.Test, since
linking to the shared version requires test changes.

Patch from Juergen Hunold.


[SVN r35989]
2006-11-10 19:09:56 +00:00
Anthony Williams
78e644c7c1 removed docs for read_write_mutex
[SVN r35976]
2006-11-10 15:51:13 +00:00
Rene Rivera
89cc7fc34e Remove obsolete Boost.Build v1 files.
[SVN r35880]
2006-11-06 17:10:46 +00:00
Roland Schwarz
974754598e Removed recursive_mutex from library builds and regression testing for RC_1_34_0 branch.
[SVN r35818]
2006-11-03 04:39:17 +00:00
Roland Schwarz
87acbb406d Forced read_write_mutex unusable for RC_1_34_0 branch.
[SVN r35817]
2006-11-03 04:37:45 +00:00
Roland Schwarz
597517157c Updated documentation for the RC_1_34_0 branch to reflect current state of read_write_mutex.
[SVN r35816]
2006-11-03 04:05:55 +00:00
Roland Schwarz
a0b816be8c Get rid of dll import warnings for noncopyable classes
[SVN r35797]
2006-10-30 19:35:40 +00:00
Roland Schwarz
64cd268fc7 Get rid of dll import warnings for nocopyable classes
[SVN r35796]
2006-10-30 19:27:51 +00:00
Roland Schwarz
4a056924d2 Added a warning about usage of read_write_mutex.
[SVN r35675]
2006-10-20 17:26:18 +00:00
Roland Schwarz
d5a81f990c Inified spelling of thread library in documentation. (singular)
Added RC_1_34_0 release notes.


[SVN r35619]
2006-10-15 14:52:54 +00:00
Roland Schwarz
f048dd81f2 Merged changes from RC_1_34_0
[SVN r35616]
2006-10-15 10:27:28 +00:00
Roland Schwarz
5746f2214c cosmetics
[SVN r35615]
2006-10-15 10:10:47 +00:00
Roland Schwarz
099af669d4 Made fail of cleanup test for native API a warning.
[SVN r35614]
2006-10-15 10:03:35 +00:00
Roland Schwarz
79cac706a7 Unified spelling of thread library in documentation. (singular)
[SVN r35590]
2006-10-13 16:48:50 +00:00
Roland Schwarz
df229074ac Made size() a constant member function.
[SVN r35589]
2006-10-13 16:41:51 +00:00
Anthony Williams
191c27e856 Added missing #include
[SVN r35577]
2006-10-12 16:30:27 +00:00
Anthony Williams
e5ee01b43c Remove spurious #endif
[SVN r35576]
2006-10-12 14:52:43 +00:00
Anthony Williams
c46b040f6f Applied some of David Deakins' patches for WinCE
[SVN r35532]
2006-10-10 07:34:48 +00:00
Markus Schöpflin
da8c92f057 Reverted last checkin. Works when patching the compiler.
[SVN r35495]
2006-10-05 08:08:40 +00:00
Roland Schwarz
866b33c808 Untabified file
[SVN r35458]
2006-10-03 18:23:06 +00:00
Roland Schwarz
182daf0b17 Disabled certain borland warnings
[SVN r35449]
2006-10-02 21:22:49 +00:00
Roland Schwarz
2552febc2a Made non-availability of automatic TSS cleanup for native Windows threads a warning instead of an error.
[SVN r35448]
2006-10-02 21:19:55 +00:00
Roland Schwarz
eb9db9b683 Added changes for MSVC 7.0
[SVN r35445]
2006-10-02 18:17:26 +00:00
Roland Schwarz
11dbdfca4d added assertions around gettimeofday and clock_gettime
[SVN r35439]
2006-10-02 09:45:28 +00:00
Markus Schöpflin
f49de9ec10 Disable threading tests on Tru64/GCC-4.1.1.
[SVN r35438]
2006-10-02 09:07:47 +00:00
Roland Schwarz
3a7e569a65 Test if this turns regressions green on win x64 platforms
[SVN r35437]
2006-10-02 07:49:04 +00:00
Roland Schwarz
c376c1a62a Removed the "intentional memory leak" of the TSS implementation.
[SVN r35434]
2006-10-01 12:57:18 +00:00
Roland Schwarz
72e4794f5b Removed the "intentional memory leak" of the TSS implementation
[SVN r35426]
2006-09-29 19:24:19 +00:00
Roland Schwarz
fbbc52063a avoid complaints of boostinspect about unnamed namespace usage
[SVN r35412]
2006-09-29 07:49:51 +00:00
Roland Schwarz
78b4fe3d07 avoid complaints of boostinspect about unnamed namespace usage
[SVN r35411]
2006-09-29 07:36:49 +00:00
Anthony Williams
c30b65a0ea Added #ifdef _WIN64 around a direct call to InterlockedCompareExchange rather than the existing call through ice_wrapper. The
platform SDK library for Win64 doesn't include a library version of InterlockedCompareExchange which the ice_wrapper code requires.


[SVN r35340]
2006-09-26 16:31:41 +00:00
Roland Schwarz
b8c8b250b1 Removed try catch(...) from thread proxy
[SVN r35328]
2006-09-26 03:05:06 +00:00
Roland Schwarz
b26d01c8d7 Fixed on of the memory leaks related to TSS
[SVN r35324]
2006-09-25 23:53:10 +00:00
Hartmut Kaiser
1cb08ff60c Changed Boost.Thread to use the Boost license.
[SVN r35115]
2006-09-14 23:02:29 +00:00
Hartmut Kaiser
4dbd8a66af Changed Boost.Thread to use the Boost license.
[SVN r35115]
2006-09-14 23:02:29 +00:00
Hartmut Kaiser
cb4d739fd1 Changed Boost.Thread to use the Boost license.
[SVN r35112]
2006-09-14 21:51:01 +00:00
Anthony Williams
11f913e8fb added BSL for files with authors in blanket_permissions.txt
[SVN r35090]
2006-09-13 14:11:49 +00:00
Anthony Williams
0b6054a919 added boostinspect:nolicense to files with old license from William Kempf
[SVN r35087]
2006-09-13 08:54:53 +00:00
Anthony Williams
e7620a1050 added boostinspect:nolicense to files with old license from William Kempf
[SVN r35086]
2006-09-13 08:33:30 +00:00
Anthony Williams
d3d7fd9317 Added call to TlsFree
[SVN r34843]
2006-08-07 16:34:54 +00:00
Peter Dimov
acf0f97663 Simplification, avoids a false leak report
[SVN r34706]
2006-07-24 19:00:30 +00:00
Peter Dimov
34bd87cea7 Moved the on_thread_exit call to a destructor
[SVN r34469]
2006-07-06 19:47:12 +00:00
Peter Dimov
228f11262e Removed the infamous catch(...)
[SVN r34467]
2006-07-06 13:45:13 +00:00
Nicola Musatti
811a03f281 Updated Borland workaround
[SVN r33942]
2006-05-05 21:13:45 +00:00
Anthony Williams
9683e0f1cc Added patch from http://lists.boost.org/Archives/boost/2005/05/86395.php to fix bug
https://sourceforge.net/tracker/index.php?func=detail&aid=1424965&group_id=7586&atid=107586


[SVN r33802]
2006-04-25 10:06:38 +00:00
Anthony Williams
2528bd0b8f Added patch from http://lists.boost.org/Archives/boost/2005/05/86395.php to fix bug
https://sourceforge.net/tracker/index.php?func=detail&aid=1424965&group_id=7586&atid=107586


[SVN r33802]
2006-04-25 10:06:38 +00:00
Vladimir Prus
ed587be470 Merge from trunk
[SVN r33597]
2006-04-07 14:01:36 +00:00
Vladimir Prus
674ae6d571 Remove declaration of 'pthread'. It was hack
[SVN r33596]
2006-04-07 14:00:27 +00:00
Vladimir Prus
690d44e2e6 Setup usage requirements for dllimport/dllexport.
[SVN r33431]
2006-03-22 08:49:42 +00:00
nobody
55b48874a4 This commit was manufactured by cvs2svn to create branch 'RC_1_34_0'.
[SVN r33417]
2006-03-21 02:26:31 +00:00
Vladimir Prus
720ccdb474 See the BOOST_THREAD_BUILD_DLL and BOOST_THREAD_BUILD_LIB defines as
appropriate.

Supposedly this will fix the test_tss_lib failure.


[SVN r32911]
2006-02-14 07:11:15 +00:00
Vladimir Prus
a556ff6560 Update Jamfile.v2
[SVN r32705]
2006-02-07 12:49:34 +00:00
Vladimir Prus
33c0af8253 Update Jamfile.v2
[SVN r32699]
2006-02-07 11:23:34 +00:00
Vladimir Prus
86072f95ac Update libs/thread/example/Jamfile.v2
[SVN r32271]
2006-01-10 08:14:25 +00:00
Martin Wille
c7b96bcd7d -- bug #548104
( http://sourceforge.net/tracker/index.php?func=detail&aid=548104&group_id=7586&atid=107586 )


[SVN r32232]
2006-01-06 09:35:28 +00:00
Marshall Clow
572c18302f Bug #1239052
[SVN r32225]
2006-01-05 00:46:16 +00:00
Marshall Clow
efd1bdec23 Bug #1364416
[SVN r32224]
2006-01-05 00:45:43 +00:00
Douglas Gregor
ba86f9ff13 Merged from Version_1_33_1
[SVN r31954]
2005-12-08 04:19:11 +00:00
John Maddock
56b07cb5c0 Bring dynamic linking into line with the rest of Boost.
[SVN r31628]
2005-11-12 10:23:25 +00:00
John Maddock
358e32e98f Remove <runtime-link>static requirement: it's not universally supported.
[SVN r31095]
2005-09-23 15:09:33 +00:00
Anthony Williams
01297016bd Reverted trunk to before adding new threads code
[SVN r30957]
2005-09-13 18:44:59 +00:00
Anthony Williams
64b5b67661 Updated thread primitives to include semaphore functions
[SVN r30952]
2005-09-13 14:20:31 +00:00
Anthony Williams
b6f0ec7fd9 Moved win32 thread sync primitives to their own file
[SVN r30947]
2005-09-13 13:48:01 +00:00
Anthony Williams
e9c0b5e0c5 Nibble mask is 0x0f, not 0x7f
[SVN r30888]
2005-09-09 12:51:17 +00:00
Anthony Williams
4a005ea288 New version of call_once for win32
[SVN r30847]
2005-09-07 15:02:16 +00:00
John Maddock
9658b69af4 Added config and header include changes needed to support MSVC + STLport 5.0.
[SVN r30701]
2005-08-27 10:25:15 +00:00
Douglas Gregor
e3c9446e29 Merged from 1.33.0 release
[SVN r30540]
2005-08-12 13:02:37 +00:00
Douglas Gregor
aa240e61d9 Clear up broken links, tabs, etc
[SVN r30077]
2005-07-14 15:47:04 +00:00
Douglas Gregor
2954e932ce Fix test_read_write_mutex, from Tobias Schwinger
[SVN r29988]
2005-07-11 15:06:09 +00:00
Douglas Gregor
5be79cc858 Unbolidify Threads title
[SVN r29938]
2005-07-07 18:06:26 +00:00
Martin Wille
4a9d97d22d -- made the initialization order for the members of
boost::detail::thread::read_write_mutex_impl
   consistent with the declaration.


[SVN r29913]
2005-07-06 21:36:56 +00:00
Martin Wille
f4f3433854 -- fixed order of member initialization
[SVN r29881]
2005-07-03 16:51:35 +00:00
Michael Glassford
26bffa3740 Rename binder to eliminate name conflicts with type traits.
[SVN r29229]
2005-05-26 14:12:41 +00:00
Michael Glassford
69e52a9882 Fix CW 8.3 warnings.
[SVN r28638]
2005-05-03 20:42:09 +00:00
Michael Glassford
cc8de48849 Commit Caleb Epstein patch to fix errors due to Boost.Test not being thread safe.
[SVN r28537]
2005-04-29 20:38:46 +00:00
Michael Glassford
9d7c119f94 Fixed CodeWarrior 8.3 warnings.
[SVN r28497]
2005-04-27 01:22:12 +00:00
Vladimir Prus
6ba9fd1b60 Sync with V1
[SVN r28369]
2005-04-21 08:17:12 +00:00
Michael Glassford
fb6250eb94 Completely rewrite tests to eliminate most calls to Sleep(), which was making the tests take far too long.
[SVN r28331]
2005-04-19 20:52:08 +00:00
Michael Glassford
bc73368c96 Remove line that could cause unnecessary extra waiting.
[SVN r28330]
2005-04-19 20:49:59 +00:00
Michael Glassford
3068f0c62c Fix undefined BOOST_READ_WRITE_MUTEX_TRACE in non-BOOST_HAS_WINTHREADS builds.
[SVN r27924]
2005-04-02 04:31:10 +00:00
Michael Glassford
8e00803c83 Don't include explicit instantiations in release builds (they increase the code size significantly).
[SVN r27887]
2005-03-30 16:59:07 +00:00
Michael Glassford
087b69b629 Fix build errors on some Win32 machines.
[SVN r27884]
2005-03-30 14:51:09 +00:00
Michael Glassford
3b237267fb Added more debugging aids, assertions. Corrected errors, including hangs, at the cost or making the read-write mutex even larger. The whole read-write mutex is too complicated; the design needs to be revisited.
[SVN r27874]
2005-03-29 21:46:38 +00:00
Michael Glassford
b9dbb1ed45 Expand read_write_mutex regression tests.
[SVN r27873]
2005-03-29 21:23:39 +00:00
Michael Glassford
41d3b29ec0 Add assert() at beginning of thread::join().
[SVN r27868]
2005-03-29 16:19:32 +00:00
Michael Glassford
05ceb8b1e2 Fix Sourceforge issue #828980, "comparisons in libs/thread/src/timeconv.inl".
[SVN r27867]
2005-03-29 15:43:00 +00:00
Michael Glassford
80d3925b8d Remove obsolete header.
[SVN r27718]
2005-03-17 02:03:31 +00:00
Michael Glassford
2cd6cbeacc Change assert() in recursive_try_mutex::do_trylock() to handle the case of pthread_mutex_trylock returning EBUSY.
[SVN r27717]
2005-03-17 01:55:44 +00:00
Michael Glassford
6382846f6c Add thread_group::size() method.
[SVN r27716]
2005-03-17 01:46:11 +00:00
Stefan Slapeta
349d0fd74b replaced BOOST_TEST
[SVN r27054]
2005-02-03 13:48:49 +00:00
Beman Dawes
9c88855bf4 correct date (Andreas Wachowski)
[SVN r26826]
2005-01-24 01:51:16 +00:00
Roland Schwarz
f0e6cdfcb5 ptw32 can be used again
[SVN r26802]
2005-01-22 13:43:48 +00:00
Roland Schwarz
af9864a1b5 Making use of BOOST_HAS_DECLSPEC macro
[SVN r26801]
2005-01-22 13:22:29 +00:00
Stefan Slapeta
8ac145e667 removed requirement of static rt for static lib
[SVN r26480]
2004-12-09 10:42:09 +00:00
Michael Glassford
39f7afc7d0 Reword comment to make its meaning clearer.
[SVN r26453]
2004-12-06 21:00:16 +00:00
Aleksey Gurtovoy
113b974bb7 merge RC_1_32_0 fixes
[SVN r26333]
2004-11-28 04:44:21 +00:00
Stefan Slapeta
c747a6ff4e Fix uninitialized variables
[SVN r25410]
2004-09-26 09:32:04 +00:00
Stefan Slapeta
107d11cfd5 Fix to make auto tss cleanup work for Intel Compiler
[SVN r25374]
2004-09-23 11:39:14 +00:00
Rene Rivera
a4d2cd94b9 Move <threadind>multi from default build, to the requirement it is.
[SVN r25195]
2004-09-18 18:24:03 +00:00
Rene Rivera
3d9fb84fc9 Move definition of __STD_CONSTANT_MACROS to be above first indirect inclusion of <cstdint> to fix compilation problem with MSL.
[SVN r25181]
2004-09-17 23:31:13 +00:00
Michael Glassford
e500bc075e Make recent xtime_get() changes more portable and easier to understand.
[SVN r25160]
2004-09-16 20:39:49 +00:00
Michael Glassford
25e8fa0e11 Fixed bug in pthreads implementation that caused incorrect behavior when used with condition variables.
[SVN r25151]
2004-09-16 17:49:16 +00:00
Michael Glassford
5f27fb2607 Add newline to end of file.
[SVN r24976]
2004-09-08 15:58:40 +00:00
Michael Glassford
d977cedb78 Fix gcc warning about inline function being marked as dllimport.
[SVN r24975]
2004-09-08 15:57:03 +00:00
Stefan Slapeta
454b58cdf0 Configure Intel for Windows like MSVC
[SVN r24805]
2004-08-29 14:13:47 +00:00
Michael Glassford
82a632b0f9 Remove cast from FILETIME to __int64, which may have alignment issues on, e.g. IA64.
[SVN r24786]
2004-08-27 14:31:28 +00:00
Michael Glassford
43cbe3f1f8 Include detail/config.hpp; fix include path.
[SVN r24607]
2004-08-19 19:39:16 +00:00
Michael Glassford
d027cec8a6 Remove accidental checkin.
[SVN r24606]
2004-08-19 19:33:46 +00:00
Michael Glassford
e53c2c52ee Add <threading>multi to work around what appears to be a bjam bug.
[SVN r24605]
2004-08-19 19:31:23 +00:00
Michael Glassford
5ff0ecc12d Remove previous checkin, which should have been in test\\jamfile, not build\\jamfile.
[SVN r24604]
2004-08-19 19:27:15 +00:00
Michael Glassford
9c1f421ccb Add <threading>multi to work around regression test build errors.
[SVN r24603]
2004-08-19 19:12:57 +00:00
Michael Glassford
66850bc057 Add <threading>multi to work around what appears to be a bjam bug.
[SVN r24601]
2004-08-19 17:16:50 +00:00
Michael Glassford
33da34b4bf Don't use subtraction to compare xtime.sec because it could overflow.
[SVN r24361]
2004-08-09 21:46:34 +00:00
Michael Glassford
792cd49310 Add #define BOOST_THREAD_TEST to command line so code can behave differently when being tested.
[SVN r24360]
2004-08-09 21:43:24 +00:00
Michael Glassford
37fdb5e2b0 Removed unnecessary casts that were causing warnings on DEC C++ 6.5 compiler.
[SVN r24359]
2004-08-09 21:39:03 +00:00
Michael Stevens
88cd251db7 tss changes to match Jamfile 1.32
[SVN r24356]
2004-08-09 16:22:43 +00:00
Michael Glassford
4038d18fc8 Only implement functions if not already implemented elsewhere to prevent linking problems.
[SVN r24341]
2004-08-08 11:17:21 +00:00
Michael Glassford
59bf92a183 Write info to cout to help debug problems.
[SVN r24339]
2004-08-08 01:20:37 +00:00
Michael Glassford
57879155d2 Fixed incorrect test.
[SVN r24336]
2004-08-07 16:10:56 +00:00
Michael Glassford
96d43cebc0 Added tests (currently only on Win32, where there's most likely to be a problem) to make sure tss works properly with threads not created by Boost.
[SVN r24325]
2004-08-06 15:50:11 +00:00
Michael Glassford
8e13857b29 Unlock mutex sooner to allow recursive calls to on_thread_exit().
[SVN r24324]
2004-08-06 15:31:08 +00:00
Michael Glassford
8c6e454697 Uncommented call to on_process_enter(). Fixed line endings.
[SVN r24322]
2004-08-06 11:55:51 +00:00
Michael Glassford
4c7c7df89b Fixed typos.
[SVN r24320]
2004-08-06 11:54:11 +00:00
Michael Glassford
515e6d8635 Completely restructured tss cleanup. Automatic tss cleanup in Win32 static Boost.Threads library now works for both VC++ 6 and 7.1 (probably also 7.0, but this hasn't been tested).
[SVN r24312]
2004-08-05 18:13:43 +00:00
Michael Glassford
bbd941e2df Updated release notes for static liking of Boost.Threads to reflect recent changes.
[SVN r24311]
2004-08-05 18:08:09 +00:00
Michael Glassford
3edba1bf19 Changed default linking option on non-Win32 platforms from dynamic to static linking.
[SVN r24310]
2004-08-05 18:06:34 +00:00
Michael Glassford
4ad99d8242 Completely restructured tss cleanup. Automatic tss cleanup in Win32 static Boost.Threads library now works for both VC++ 6 and 7.1 (probably also 7.0, but this hasn't been tested).
[SVN r24307]
2004-08-05 17:33:07 +00:00
Michael Glassford
c0aeaecc14 Add tests for statically linked Boost.Threads.
[SVN r24274]
2004-08-03 21:19:08 +00:00
Michael Glassford
792be9e687 Add on_process_enter() and on_thread_enter(); make tss cleanup more robust.
[SVN r24258]
2004-08-03 01:38:04 +00:00
Michael Glassford
fd65337f43 Add tests for statically linked and dynamically linked versions of Boost.Threads.
[SVN r24257]
2004-08-03 01:33:24 +00:00
Michael Glassford
9de9726e6f Removed erroneous call to on_process_exit().
[SVN r24237]
2004-08-01 19:25:05 +00:00
Michael Glassford
522037ca4a Add automatic tss cleanup to statically linked Win32 Boost.Threads library (currently works only for VC++ 7.1).
[SVN r24236]
2004-08-01 17:50:11 +00:00
Michael Glassford
8fc3d1f718 Add automatic tss cleanup to statically linked Win32 Boost.Threads library (currently works only for VC++ 7.1).
[SVN r24235]
2004-08-01 17:26:45 +00:00
Michael Glassford
cebaf27ee8 Set thread cleanup handlers to null when deleting it so that calling on_thread_exit() twice doesn't use an invalid pointer.
[SVN r24228]
2004-08-01 12:07:11 +00:00
Michael Glassford
b62503f274 Call tss cleanup after thread function exits even in dll builds of Boost.Threads (win32 only).
[SVN r24227]
2004-08-01 11:39:59 +00:00
Aleksey Gurtovoy
af50c640ab MSVC 6.5 + STLPort 4.5.3 workaround
[SVN r24207]
2004-07-31 12:27:25 +00:00
Michael Glassford
b5c5fbe0f5 #include <string> before every #<stdexcept> to eliminate compile errors on VC++ 6 with STLPort-4.5.3 when standard exceptions are thrown with a string literal passed to the constructor.
[SVN r24159]
2004-07-29 14:25:30 +00:00
Douglas Gregor
b88ae8105e Converted to Boost Software License, Version 1.0
[SVN r24055]
2004-07-26 00:32:12 +00:00
Michael Glassford
9ad04bb65e Handle locks that timeout.
[SVN r23999]
2004-07-23 18:39:50 +00:00
Michael Glassford
13bbaab1c4 Removed incorrect assertions.
[SVN r23916]
2004-07-21 20:57:31 +00:00
Michael Glassford
09ca8d1728 Update copyright to use Boost License 1.0, with permission from Mac Murrett.
[SVN r23914]
2004-07-21 20:44:45 +00:00
Michael Glassford
9797a93d86 Fix typos.
[SVN r23913]
2004-07-21 20:43:54 +00:00
Michael Glassford
d29dae72de Clean up scheduling algorithms to pass unit tests and hopefully eliminate reported deadlocks. Still needs work, but should be better than before.
[SVN r23849]
2004-07-20 20:25:18 +00:00
Vladimir Prus
59fba2bff6 Fix minor issue gcc 3.4 found. The test was trying to pass rvalue to
function taking reference, and this requires, according to standard,
accessible copy ctor, which boost::thread does not have.


[SVN r23838]
2004-07-20 13:13:22 +00:00
Michael Glassford
0350d4c501 Renamed add_thread_exit() to at_thread_exit(), a better name.
[SVN r23796]
2004-07-19 14:25:00 +00:00
Vladimir Prus
d3e4a90e70 More V2 Jamfile tweaks.
[SVN r23764]
2004-07-19 07:12:45 +00:00
Michael Glassford
8ebb19fd18 Call on_thread_exit() after thread function has exited to clean up tss on boost-created threads.
[SVN r23715]
2004-07-17 23:15:50 +00:00
Michael Glassford
02ddc33e6c Replace tabs with spaces.
[SVN r23714]
2004-07-17 23:13:06 +00:00
Michael Glassford
410e8efeba Fix warnings on some compilers.
[SVN r23691]
2004-07-17 15:31:28 +00:00
Rene Rivera
e9f8e0bad9 Prevent use of auto-link functionality as it can't be used within regression testing.
[SVN r23667]
2004-07-17 05:44:06 +00:00
Rene Rivera
f69e0313dc Add an import to std namespace in boost_error function for tools/runtimes that put snprintf and related functions there. This fixes the unqualified use of snprintf (as _sntprintf) in CodeWarrior 8.
[SVN r23666]
2004-07-17 05:42:22 +00:00
Rene Rivera
baa9b396d9 Fix some compilation problems on Win32 platforms because of inconsistent line-endings.
[SVN r23663]
2004-07-17 04:33:59 +00:00
Michael Glassford
a82b0c516d Remove line-continuation inside #if (cwpro8 seemed not to like it).
[SVN r23662]
2004-07-17 03:52:59 +00:00
Michael Glassford
43e2192aa2 Proofreading changes.
[SVN r23661]
2004-07-17 03:39:07 +00:00
Michael Glassford
4cd6453cac Fix compile errors: some compilers don't like an enum and the namespace it is in to have the same name.
[SVN r23660]
2004-07-17 03:37:00 +00:00
Michael Glassford
921d4c24c2 Fixed many compile errors.
[SVN r23659]
2004-07-17 03:34:51 +00:00
Michael Glassford
4fc7653b12 Move instructions detailing how to use pthreads-win32 into common file threads.jam.
[SVN r23650]
2004-07-16 20:50:18 +00:00
Michael Glassford
9d0e39a7c2 Move instructions detailing how to use pthreads-win32 into common file threads.jam.
[SVN r23645]
2004-07-16 19:58:32 +00:00
Michael Glassford
7aa979cf5b Add instructions detailing how to use pthreads-win32.
[SVN r23643]
2004-07-16 19:57:59 +00:00
Michael Glassford
0aa50614d7 Add missing typenames, fix duplicate explicit template instantiation.
[SVN r23610]
2004-07-16 02:27:29 +00:00
Michael Glassford
6f402c7362 Add "<sysinclude>$(BOOST_ROOT)" to templates to get boost include files on compiler command line.
[SVN r23603]
2004-07-15 20:41:38 +00:00
Michael Glassford
2bf43a124d Document read_lock, write_lock, and related classes.
[SVN r23590]
2004-07-15 15:29:03 +00:00
Michael Glassford
3573c53eda Add notes about liability of mutex, lock, read/write mutex, nad read/write lock concepts to change; document read_lock, write_lock, and related classes; document throwing promote().
[SVN r23589]
2004-07-15 15:27:39 +00:00
Michael Glassford
4546ec4ef7 Detail newest changes.
[SVN r23587]
2004-07-15 15:22:44 +00:00
Michael Glassford
2f7337aaf6 Remove invalid line ending, "\\r\\n\\n".
[SVN r23555]
2004-07-14 18:49:51 +00:00
Michael Glassford
046698bcc2 Remove invalid typename (accepted by MSVC++ 6 and 7.1, but not by some compilers).
[SVN r23547]
2004-07-14 15:29:30 +00:00
Michael Glassford
06d7bf21d5 Add newline at end of file.
[SVN r23499]
2004-07-13 15:24:11 +00:00
Michael Glassford
e7b9ccdf10 Fix compile error.
[SVN r23498]
2004-07-13 15:18:16 +00:00
Michael Glassford
1e15b043a0 Add hooks for users to provide there own tss cleanup in win32 statically linked builds.
[SVN r23493]
2004-07-13 14:51:23 +00:00
Michael Glassford
6c5f3d76e2 Modify constructors; add promote() that throws exception if it fails; fix enum definition.
[SVN r23492]
2004-07-13 14:42:26 +00:00
Michael Glassford
8679d6f6af Removed enums that will no longer be used.
[SVN r23491]
2004-07-13 14:40:08 +00:00
Michael Glassford
f1c7d0f354 Fix enum definition; add newline at end of file.
[SVN r23490]
2004-07-13 14:39:25 +00:00
Michael Glassford
261e413500 Add promote() that throws exception if it fails; fix enum definition.
[SVN r23489]
2004-07-13 14:38:42 +00:00
Michael Glassford
094e41d7a7 Add newline at end of file.
[SVN r23488]
2004-07-13 14:37:50 +00:00
Michael Glassford
e20299c8ee Add promote() that throws exception if it fails.
[SVN r23487]
2004-07-13 14:36:59 +00:00
Michael Glassford
f8962b7ad2 Changes for WinCE.
[SVN r23486]
2004-07-13 14:34:20 +00:00
Michael Glassford
c34f829c3e Add lock_state and blocking_mode needed by read_write_lock and related classes.
[SVN r23418]
2004-07-09 11:08:54 +00:00
Michael Glassford
46264e4a4a Apply patch for SGI MIPSpro compiler.
[SVN r23406]
2004-07-08 14:42:04 +00:00
Michael Glassford
096df68ea6 Add title.
[SVN r23405]
2004-07-08 13:52:15 +00:00
Vladimir Prus
35f2055a1e Fix some typos. Thanks to Jurgen Hunold for the patch.
[SVN r23404]
2004-07-08 13:46:51 +00:00
Michael Glassford
e1353eefb3 Proofreeding changes.
[SVN r23381]
2004-07-06 18:44:33 +00:00
Michael Glassford
4911a532bf Merge read/write mutex from thread_dev branch.
[SVN r23380]
2004-07-06 17:35:53 +00:00
Michael Glassford
96362e03aa Changes for WinCE.
[SVN r23379]
2004-07-06 17:33:49 +00:00
Michael Glassford
049b4e09fe Changes for WinCE.
[SVN r23378]
2004-07-06 17:28:24 +00:00
Michael Glassford
828c0e28af Win32: use CreateMutexA instead of CreateMutex to prevent compile errors in Unicode builds.
[SVN r23377]
2004-07-06 17:22:21 +00:00
Michael Glassford
15a638edc0 Merge exception class changes thread_dev branch (thread exceptions now have a common base class and methods for reporting the OS error that caused the exception to be thrown, if any).
[SVN r23376]
2004-07-06 17:20:55 +00:00
Michael Glassford
fc8f1b1075 Merge read/write mutex from thread_dev branch.
[SVN r23375]
2004-07-06 17:11:31 +00:00
Michael Glassford
318a8e38c9 Merge exception class changes thread_dev branch (thread exceptions now have a common base class and methods for reporting the OS error that caused the exception to be thrown, if any).
[SVN r23374]
2004-07-06 17:09:11 +00:00
Michael Glassford
f0dbb02a9f Disable auto-link when building static library.
[SVN r23373]
2004-07-06 17:03:43 +00:00
Michael Glassford
649b777b76 Merge from thread_dev branch: convert documentation to BoostBook format.
[SVN r23300]
2004-07-01 14:06:07 +00:00
Michael Glassford
6fad43670a Merge from thread_dev branch: convert documentation to BoostBook format.
[SVN r23299]
2004-07-01 14:01:51 +00:00
Michael Glassford
e24b16229e Cleanup: always #include <boost/thread/detail/config.hpp> first; eliminate tabs; etc.
[SVN r23197]
2004-06-25 20:46:31 +00:00
Michael Glassford
21b4b81810 Cleanup: always #include <boost/thread/detail/config.hpp> first; eliminate tabs; etc.
[SVN r23191]
2004-06-25 20:27:13 +00:00
Michael Glassford
1096b1e28e Cleanup: always #include <boost/thread/detail/config.hpp> first; eliminate tabs; etc.
[SVN r23190]
2004-06-25 20:22:02 +00:00
Michael Glassford
03458fedef Add option to build as static library.
[SVN r23189]
2004-06-25 20:17:19 +00:00
Michael Glassford
c1a2004344 Cleanup: always #include <boost/thread/detail/config.hpp> first; eliminate tabs; etc.
[SVN r23188]
2004-06-25 20:04:34 +00:00
Michael Glassford
2adb13a209 Cleanup: always #include <boost/thread/detail/config.hpp> first; TimedLock concept is a refinement of TryLock.
[SVN r23181]
2004-06-25 14:35:55 +00:00
Michael Glassford
dba194ddb9 Change enumeration from anonymous to xtime_clock_types and remove unused clock types.
[SVN r23150]
2004-06-22 21:25:58 +00:00
Vladimir Prus
8179f041e6 Update V2 Jamfiles
[SVN r23076]
2004-06-10 12:22:55 +00:00
Vladimir Prus
a13c7a4d84 Add newline at the end of file, to stop gcc warning
[SVN r23075]
2004-06-10 12:20:01 +00:00
Michael Glassford
bbf92bb971 Fix gcc 3.3.1 compiler warning.
[SVN r23007]
2004-06-02 18:53:39 +00:00
Victor A. Wagner Jr.
b33f413635 Removed the extra cr from the end of line sequence in the source
[SVN r22982]
2004-05-31 11:48:48 +00:00
Michael Glassford
58ffb2bc16 Win32: use critical section instead of mutex whenever possible; abstract common code into functions.
[SVN r22828]
2004-05-15 02:03:48 +00:00
Michael Glassford
0ed112631c Merge tss changes from thread_dev branch.
[SVN r22560]
2004-03-27 02:03:52 +00:00
Michael Glassford
9cfe8e9422 Add missing pthread_mutexattr_destroy() to recursive_mutex::recursive_mutex() and recursive_try_mutex::recursive_try_mutex().
[SVN r22527]
2004-03-19 21:24:50 +00:00
Eric Niebler
7d3fe72970 remove minmax hack from win32.hpp and fix all places that could be affected by the minmax macros
[SVN r22394]
2004-02-26 18:27:02 +00:00
Michael Glassford
ac422138fa Merge barrier from thread_dev branch.
[SVN r22374]
2004-02-23 17:53:56 +00:00
Michael Glassford
bf8746454a Merge barrier from thread_dev branch.
[SVN r22373]
2004-02-23 17:29:40 +00:00
Michael Glassford
b61aa5b4ba Merge changes from thread_dev branch.
[SVN r22323]
2004-02-19 01:24:50 +00:00
Michael Glassford
c2bcd08168 Merge minor changes from thread_dev branch.
[SVN r22322]
2004-02-19 01:16:06 +00:00
Michael Glassford
48593b8868 Merge minor changes from thread_dev branch.
[SVN r22308]
2004-02-18 01:15:36 +00:00
Michael Glassford
83d4dc1831 Merge minor changes from thread_dev branch.
[SVN r22307]
2004-02-18 00:53:09 +00:00
John Maddock
0696f3cc41 Added auto-link code to thread library
[SVN r21575]
2004-01-10 12:16:42 +00:00
Rene Rivera
515590495a Fix tabs in file.
[SVN r21399]
2003-12-26 23:26:49 +00:00
John Maddock
7221bca909 Added <runtime-link>dynamic requirement to dll build.
[SVN r21355]
2003-12-20 12:55:40 +00:00
John Maddock
ed64a8cd12 Changed #errors to use new requires_threads.hpp header instead.
[SVN r21351]
2003-12-20 11:56:37 +00:00
Beman Dawes
cbd30d22ff fix links broken by index.htm to index.html renaming
[SVN r21233]
2003-12-12 00:00:13 +00:00
Dave Abrahams
0c74dbd436 * Fixed Boost.Thread jamfile to add the missing #include paths
* Modified Python testing code to use the facilities of testing.jam,
  so that it can be processed with process_jam_log

* Updated Python library tests to use a test suite

* Added Python test suite to status/Jamfile

* Added --run-all-tests option to force tests to run even when up-to-date.


Also,
boost-base.jam:

    Added some missing rule signatures

    RUN_LD_LIBRARY_PATH became LINK_LIBPATH because it was only really
    used during linking.

    Reformed the movement of path variables up the dependency graph

    Removed the defunct Run rule

    Set up generalized constants for path manipulation

darwin-tools.jam, gcc-tools.jam:

   use LINK_LIBPATH

python.jam:

   Reformed the choice of Python executable

testing.jam:

   Refactored testing code so it could be used for Python

   Now building all environment variable setup code ahead of time

   RUN_TEST became TEST_EXE


[SVN r20815]
2003-11-15 15:41:41 +00:00
Rene Rivera
49356cc931 Add install definitions for new common install configuration.
[SVN r20409]
2003-10-19 19:52:56 +00:00
Vladimir Prus
ceee6e8b17 Add V2 Jamfile
[SVN r20271]
2003-10-07 08:10:42 +00:00
Dave Abrahams
61ab2754d2 Use the import rule
[SVN r19968]
2003-09-08 17:38:49 +00:00
Dave Abrahams
2de3df61e8 Updates for Win32 builds
[SVN r19727]
2003-08-22 03:41:42 +00:00
Dave Abrahams
b84d7aa06d Port "conditin.hpp" typo fix over from Version_1_30_2
[SVN r19725]
2003-08-21 22:51:38 +00:00
Dave Abrahams
ed48f900a3 Compile on Windows; add some requirements and default-build (though
the latter shouldn't be neccessary?!)


[SVN r19715]
2003-08-20 13:51:35 +00:00
Beman Dawes
d197a49707 fix typo
[SVN r19214]
2003-07-19 14:21:00 +00:00
Beman Dawes
b8ccaa3bf6 Add Wirth's view of semaphores
[SVN r19213]
2003-07-19 14:08:32 +00:00
Beman Dawes
507a684b21 Add [Brinch Hansen 02]
[SVN r19212]
2003-07-19 14:07:50 +00:00
Beman Dawes
c969c9387a Expand semaphore FAQ
[SVN r18952]
2003-07-07 00:39:06 +00:00
William E. Kempf
1709db4953 Fixed exception handling bug in once.cpp.
[SVN r18933]
2003-07-03 13:31:27 +00:00
William E. Kempf
4d1c9ba316 Attempted to fix race condition in test_tss.cpp.
[SVN r18838]
2003-06-18 20:50:15 +00:00
William E. Kempf
45b0396355 Removed Borland warnings.
[SVN r17605]
2003-02-23 17:38:11 +00:00
William E. Kempf
1df2169e48 Removed new(nothrow) calls.
[SVN r17586]
2003-02-22 04:54:19 +00:00
William E. Kempf
2c056b3621 Added acknowledgement for Martin Johnson's help with shared library implementation
[SVN r17510]
2003-02-18 17:02:29 +00:00
William E. Kempf
680119006c Unlocked mutex in all control paths in notify_all
[SVN r17509]
2003-02-18 16:59:03 +00:00
Björn Karlsson
c4ac4b7538 Added copyright statement
[SVN r17222]
2003-02-05 08:38:32 +00:00
William E. Kempf
ff5d3b49ca Updated format (removed tabs) and added missing copyrights
[SVN r17214]
2003-02-04 23:23:02 +00:00
William E. Kempf
e101c878f0 Updated format (removed tabs) and added missing copyrights
[SVN r17213]
2003-02-04 23:08:28 +00:00
William E. Kempf
125193dcfa Turned all tests into 'timed_test's.
[SVN r17053]
2003-01-27 22:44:06 +00:00
Beman Dawes
77efa9810d Local include util.inl
[SVN r17041]
2003-01-25 14:23:36 +00:00
William E. Kempf
7f03d1917b Removed accidental sleep
[SVN r17035]
2003-01-24 18:15:22 +00:00
William E. Kempf
55b4ca9350 Added 'timed_test' support to prevent deadlocks in tests
[SVN r17032]
2003-01-24 16:51:13 +00:00
William E. Kempf
7196a0f9d2 Updated build files
[SVN r17021]
2003-01-23 23:23:36 +00:00
William E. Kempf
2caabde5ca Updated Jamfile to use test-suite
[SVN r17014]
2003-01-23 19:47:29 +00:00
Vladimir Prus
137d7663c1 Change use-requirements to usage-requirements in some library Jamfiles.
[SVN r16884]
2003-01-13 12:31:12 +00:00
Vladimir Prus
508b71a921 Update V2 Jamfile for Boost.
[SVN r16882]
2003-01-13 10:05:01 +00:00
Beman Dawes
5d90820005 fix bookmarks
[SVN r16827]
2003-01-09 13:37:41 +00:00
Beman Dawes
84727e90b1 fix invalid bookmarks
[SVN r16825]
2003-01-09 13:22:04 +00:00
William E. Kempf
9a1e3d3320 Added <boost/thread.hpp>.
[SVN r16796]
2003-01-08 15:08:32 +00:00
William E. Kempf
d33e0c8ee1 Fixed Unicode problem (CreateMutex - CreateMutexA)
[SVN r16770]
2003-01-06 16:06:37 +00:00
William E. Kempf
3332649480 Fixed bug in to_duration.
[SVN r16769]
2003-01-06 15:55:57 +00:00
William E. Kempf
c918b66199 Switched to a DLL implementation
[SVN r16742]
2003-01-03 21:03:43 +00:00
William E. Kempf
dbbf56e17a Updated to new test library name
[SVN r16732]
2003-01-02 16:26:03 +00:00
William E. Kempf
c77500c15a Updated Jamfile to remove unused code
[SVN r16725]
2002-12-30 23:14:30 +00:00
Dave Abrahams
75084aaa96 HP aCC workarounds
[SVN r16518]
2002-12-04 17:56:59 +00:00
William E. Kempf
35714c8f1c Added new tutorials
[SVN r16007]
2002-10-28 14:17:49 +00:00
William E. Kempf
3699cc97a6 Added new tutorial files
[SVN r16005]
2002-10-28 14:10:14 +00:00
Vladimir Prus
5a7377acda Made Boost.Thread compile with V2.
[SVN r15969]
2002-10-23 13:22:56 +00:00
Beman Dawes
6aaee629b5 Fix acknowledgements and copyright
[SVN r15759]
2002-10-07 00:07:46 +00:00
Björn Karlsson
b465fe569c Merged from branch to trunk
[SVN r15613]
2002-10-01 15:00:37 +00:00
Björn Karlsson
5e6f72a688 Merged from branch to trunk
[SVN r15524]
2002-09-26 09:17:19 +00:00
William E. Kempf
51f80f6c15 Removed incorrect usages of typename
[SVN r15185]
2002-09-06 19:49:10 +00:00
William E. Kempf
45c314e594 Changed tabs to spaces.
[SVN r15180]
2002-09-06 15:35:39 +00:00
William E. Kempf
cfce0892e0 Added tutorial sources. Changed tabs to spaces.
[SVN r15179]
2002-09-06 15:34:48 +00:00
William E. Kempf
05d1abf030 Added build documentation. Changed tabs to spaces.
[SVN r15178]
2002-09-06 15:33:54 +00:00
Dave Abrahams
6c24a2626b Fix stupid mistake
[SVN r15058]
2002-08-22 16:13:59 +00:00
Dave Abrahams
870c75bd12 Stop using unit-test since it has problems with JAMSHELL setting with gcc
[SVN r15033]
2002-08-21 15:29:18 +00:00
William E. Kempf
5fdd771708 Fixed some bugs and warnings produced by borland and gcc
[SVN r14944]
2002-08-17 16:34:23 +00:00
William E. Kempf
06f39ac409 Changed examples in documents to links to actual code
[SVN r14939]
2002-08-16 21:43:31 +00:00
William E. Kempf
c92b0a2fb7 An attempt to make InterlockedCompareExchange more portable
[SVN r14938]
2002-08-16 21:19:48 +00:00
William E. Kempf
8a8d0e05ca Added pre-Win64 support for InterlockedCompareExchange
[SVN r14937]
2002-08-16 20:16:03 +00:00
William E. Kempf
74bae2baac Added library-root level index.html for Boost.Threads
[SVN r14914]
2002-08-15 23:37:20 +00:00
William E. Kempf
4ba48676bd Fixed some warnings produced by Borland in the regression test
[SVN r14875]
2002-08-15 03:39:24 +00:00
William E. Kempf
78480e7951 Removed subdirectories
[SVN r14870]
2002-08-15 01:39:07 +00:00
William E. Kempf
4cb9c412e8 Added examples from documentation
[SVN r14869]
2002-08-15 01:22:29 +00:00
William E. Kempf
75c83fed96 Fixed time precision bugs. Switched to Interlocked* methods for once.
[SVN r14867]
2002-08-15 00:05:54 +00:00
William E. Kempf
391de20ae0 Added test_xtime.cpp
[SVN r14852]
2002-08-14 20:39:32 +00:00
William E. Kempf
1e2a9e8971 Fixed Jamfile issues with tests
[SVN r14818]
2002-08-13 19:19:09 +00:00
William E. Kempf
43cbd3a283 Split up tests into seperate files and switched fully to unit test framework
[SVN r14780]
2002-08-12 05:43:10 +00:00
William E. Kempf
31cf6b5e64 Initial switch to Boost.Test unit test framework
[SVN r14779]
2002-08-12 00:09:33 +00:00
Dave Abrahams
99109ab78b respect <sysinclude>
[SVN r13995]
2002-05-21 16:24:07 +00:00
William E. Kempf
a80d5f159d Merged from RC_1_28_0 branch
[SVN r13905]
2002-05-15 14:35:39 +00:00
William E. Kempf
7ba4fc4aed Changed logic_error to runtime_error for thread_resource_error
[SVN r13644]
2002-05-03 16:19:13 +00:00
William E. Kempf
9fb31e9868 Updated documentation for pending release
[SVN r13606]
2002-05-01 15:37:25 +00:00
William E. Kempf
3a2246de5b Fixed broken links
[SVN r13570]
2002-04-26 21:15:40 +00:00
William E. Kempf
e7c4e2fa57 Removed boost/thread/config.hpp and changed Boost.Threads exceptions to derive from logic_error
[SVN r13568]
2002-04-26 20:56:49 +00:00
William E. Kempf
724ab285f0 Updated the rest of the documentation to the new templates.
[SVN r13567]
2002-04-26 20:41:25 +00:00
William E. Kempf
d60e66fb00 More Boost.Threads doc changes
[SVN r13453]
2002-04-11 22:15:26 +00:00
William E. Kempf
97cdaca028 Boost.Threads documentation updates.
[SVN r13439]
2002-04-10 22:08:15 +00:00
Dave Abrahams
3044c8f905 Bug fix
[SVN r13341]
2002-04-01 20:13:43 +00:00
William E. Kempf
2775a2a945 Updated <runtime-link> info in Jamfile
[SVN r13198]
2002-03-14 23:29:18 +00:00
William E. Kempf
c43c1febba Fixed bug in example in mutex.html
[SVN r13197]
2002-03-14 23:24:16 +00:00
William E. Kempf
ceb6471d57 Updated thread.html for new documentation style.
[SVN r13196]
2002-03-14 23:23:48 +00:00
William E. Kempf
b99cc044f3 Updated Jamfile
[SVN r13095]
2002-03-05 16:27:46 +00:00
Rene Rivera
d91429dcec Moved the <runtime-link> to the build request.
[SVN r13018]
2002-03-02 18:41:22 +00:00
William E. Kempf
b1d1f7d8f1 Jamfile modifications
[SVN r13001]
2002-03-01 23:10:11 +00:00
Dave Abrahams
86b608cf41 Updates to work on Linux
[SVN r12981]
2002-02-28 12:35:05 +00:00
Dave Abrahams
f263f75751 Killed bogus runtime-link specification
[SVN r12946]
2002-02-27 02:11:12 +00:00
William E. Kempf
24bec05b86 Added .cvsignore and updated Jam stuff
[SVN r12944]
2002-02-26 21:02:13 +00:00
William E. Kempf
ce1a5e9359 fixed missing } bug
[SVN r12903]
2002-02-22 18:32:08 +00:00
William E. Kempf
311525bc06 replaced <dll>thread_mon with $(THREADMON_DLL)
[SVN r12902]
2002-02-22 18:31:20 +00:00
William E. Kempf
ecdfd96529 fixed typename warnings
[SVN r12901]
2002-02-22 18:30:34 +00:00
William E. Kempf
5aab32bc1a More Jamfile changes.
[SVN r12857]
2002-02-18 23:04:25 +00:00
William E. Kempf
e152a1c6f2 Updated Jamfiles for new Boost.Build system
[SVN r12856]
2002-02-18 23:02:38 +00:00
Rene Rivera
e84fde78ec Updated the basic Jamfiles for the new Boost.Build changes.
[SVN r12798]
2002-02-14 04:08:20 +00:00
William E. Kempf
6ec4652bcf Updated thread documentation to use new templates.
[SVN r12785]
2002-02-11 23:13:04 +00:00
William E. Kempf
a5239c820b Fixed tabs in files
[SVN r12622]
2002-02-01 17:31:46 +00:00
William E. Kempf
41b001b22c Removed warnings reported by gcc.
[SVN r12492]
2002-01-24 19:17:36 +00:00
William E. Kempf
34e903b8b0 Fixed bug in example.
[SVN r12489]
2002-01-24 19:13:19 +00:00
Mac Murrett
2b67e953fd Changed prefix file to debug_prefix.hpp
[SVN r12487]
2002-01-24 17:33:03 +00:00
Mac Murrett
aa0d3adf1d *** empty log message ***
[SVN r12486]
2002-01-24 17:26:13 +00:00
Mac Murrett
a1f57a8a80 *** empty log message ***
[SVN r12485]
2002-01-24 17:19:44 +00:00
William E. Kempf
6bc82a8580 Added Mac Carbon implementation to Boost.Threads.
[SVN r12480]
2002-01-24 16:32:23 +00:00
William E. Kempf
c4c2e5d3a2 Fixed bug in notify_one that caused deadlock.
[SVN r12178]
2001-12-31 17:18:46 +00:00
Dave Abrahams
dd7d4b2173 Metrowerks needs BOOST_NO_STD_LOCALE in config to be able to compile regex
regex test Jamfile updates so that some tests will actually run
warning suppression for condition.cpp

unit-test rule now accepts input files
updated metrowerks and borland to properly set up path for running tests

----------------------------------------------------------------------
Modified Files:
	boost/config/compiler/metrowerks.hpp
	libs/python/src/gen_function.py libs/regex/test/Jamfile
 Tag: thread-initial
	libs/thread/src/condition.cpp
 No tag
	tools/build/boost-base.jam tools/build/borland-tools.jam
	tools/build/metrowerks-tools.jam
----------------------------------------------------------------------


[SVN r11853]
2001-12-02 17:43:45 +00:00
Beman Dawes
2719c4d545 Try to get the date stamps in sync
[SVN r11618]
2001-11-07 00:37:59 +00:00
Beman Dawes
33c1e36b54 Add "Why has semaphore disappeared" FAQ
[SVN r11586]
2001-11-05 15:42:10 +00:00
William E. Kempf
e7e46e185e Fixed bug found compiling with gcc.
[SVN r11584]
2001-11-05 15:13:57 +00:00
William E. Kempf
9200d48873 Added lock_ops<> detail concept.
[SVN r11540]
2001-11-02 23:34:50 +00:00
William E. Kempf
831d054d24 Added exceptions.cpp.
[SVN r11502]
2001-11-01 16:19:44 +00:00
William E. Kempf
f3af804ddb Removed semaphores. Fixed some reported bugs. Switched to CRITICAL_SECTION implementations.
[SVN r11501]
2001-11-01 16:18:57 +00:00
John Maddock
1f35149ef0 Added code to normalise timespec structures.
[SVN r11500]
2001-11-01 12:56:57 +00:00
William E. Kempf
554a18842f Switched to void* for HANDLE types. Changed boost::once_init to the macro BOOST_ONCE_INIT.
[SVN r11475]
2001-10-30 22:12:37 +00:00
William E. Kempf
869243b6d1 Updated Jamfiles for PTW32, removed _atomic.cpp and added Win32 conditional compilation blocks for threadmon files.
[SVN r11468]
2001-10-29 22:20:50 +00:00
William E. Kempf
c0da02326a Fixed reported documentation bugs.
[SVN r11462]
2001-10-29 16:58:17 +00:00
William E. Kempf
9b5f666fc5 Removed tabs and trailing white space.
[SVN r11403]
2001-10-18 19:56:32 +00:00
William E. Kempf
1ce93426a4 Fixed Jamfile.
[SVN r11396]
2001-10-16 22:10:45 +00:00
William E. Kempf
6dacf3478b Fixed sprintf bugs in once.cpp.
[SVN r11395]
2001-10-16 19:32:20 +00:00
William E. Kempf
dff91699c3 Fixed more warnings and errors found when compiling with gcc.
[SVN r11388]
2001-10-15 21:28:11 +00:00
William E. Kempf
9f83e8c1fc Modified Jamfile to allow for building using pthreads-win32 (code is commented out).
[SVN r11387]
2001-10-15 18:34:01 +00:00
William E. Kempf
7b07cb0759 Fixed errors and warnings for gcc. Still some outstanding issues for gcc on Win32.
[SVN r11386]
2001-10-15 18:32:21 +00:00
William E. Kempf
c2e7091632 Fixed reported warnings. Fixed once bug with void* and function pointer conversion.
[SVN r11385]
2001-10-15 00:48:51 +00:00
Beman Dawes
1ab320042e Minor typo fix and wording improvements
[SVN r11365]
2001-10-08 20:20:07 +00:00
William E. Kempf
b0cd307eaf Ran "tidy" against documentation.
[SVN r11329]
2001-10-02 16:13:25 +00:00
167 changed files with 19387 additions and 9589 deletions

View File

@@ -1,40 +0,0 @@
# (C) Copyright William E. Kempf 2001. Permission to copy, use, modify, sell and
# distribute this software is granted provided this copyright notice appears
# in all copies. This software is provided "as is" without express or implied
# warranty, and with no claim as to its suitability for any purpose.
#
# Boost.Threads build and test Jamfile
#
# Declares the following targets:
# 1. libboost_thread, a static link library.
# 1a. On Win32, a dynamic link library libboost_threadmon,
# which must be used in conjunction with libboost_thread.
# declare the location of this subproject relative to the root
subproject libs/thread/build ;
#######################
#
# Declare the Boost.Threads static link library.
#
# For Win32 we need to build a special DLL, libboost_threadmon, to handle
# TSS destruction.
if $(NT)
{
dll libboost_threadmon : ../src/threadmon.cpp
# requirements
: <threading>multi
: debug release ;
}
# Base names of the source files for libboost_thread
CPP_SOURCES =
condition mutex recursive_mutex semaphore thread tss xtime once ;
lib libboost_thread : ../src/$(CPP_SOURCES).cpp
# requirements
: <include>$(BOOST_ROOT)
<threading>multi
: debug release ;

208
build/Jamfile.v2 Normal file
View File

@@ -0,0 +1,208 @@
# $Id$
# Copyright 2006-2007 Roland Schwarz.
# Copyright 2007 Anthony Williams
# Distributed under the Boost Software License, Version 1.0. (See
# accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#########################################################################
# The boost threading library can be built on top of different API's
# Currently this is the win32 API and the pthreads API.
# Pthread is native on unix variants.
# To get pthread on windows you need the pthread win32 library
# http://sourceware.org/pthreads-win32 which is available under LGPL.
#
# You need to provide the include path and lib path in the variables
# PTW32_INCLUDE and PTW32_LIB respectively. You can specify these
# paths in site-config.jam, user-config.jam or in the environment.
# A new feature is provided to request a specific API:
# <threadapi>win32 and <threadapi)pthread.
#
# The naming of the resulting libraries is mostly the same for the
# variant native to the build platform, i.e.
# boost_thread and the boost specific tagging.
# For the library variant that is not native on the build platform
# an additional tag is applied:
# boost_thread_pthread for the pthread variant on windows, and
# boost_thread_win32 for the win32 variant (likely when built on cygwin).
#
# To request the pthread variant on windows, from boost root you would
# say e.g:
# bjam msvc-8.0 --with-thread install threadapi=pthread
#########################################################################
import os ;
import feature ;
import indirect ;
import path ;
project boost/thread
: source-location ../src
: requirements <threading>multi
<link>static:<define>BOOST_THREAD_BUILD_LIB=1
<link>shared:<define>BOOST_THREAD_BUILD_DLL=1
-<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
<tag>@$(__name__).tag
: default-build <threading>multi
;
local rule default_threadapi ( )
{
local api = pthread ;
if [ os.name ] = "NT" { api = win32 ; }
return $(api) ;
}
feature.feature threadapi : pthread win32 : propagated ;
feature.set-default threadapi : [ default_threadapi ] ;
rule tag ( name : type ? : property-set )
{
local result = $(name) ;
if $(type) in STATIC_LIB SHARED_LIB IMPORT_LIB
{
local api = [ $(property-set).get <threadapi> ] ;
# non native api gets additional tag
if $(api) != [ default_threadapi ] {
result = $(result)_$(api) ;
}
}
# forward to the boost tagging rule
return [ indirect.call $(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
$(result) : $(type) : $(property-set) ] ;
}
rule win32_pthread_paths ( properties * )
{
local result ;
local PTW32_INCLUDE ;
local PTW32_LIB ;
PTW32_INCLUDE = [ modules.peek : PTW32_INCLUDE ] ;
PTW32_LIB = [ modules.peek : PTW32_LIB ] ;
PTW32_INCLUDE ?= [ modules.peek user-config : PTW32_INCLUDE ] ;
PTW32_LIB ?= [ modules.peek user-config : PTW32_LIB ] ;
PTW32_INCLUDE ?= [ modules.peek site-config : PTW32_INCLUDE ] ;
PTW32_LIB ?= [ modules.peek site-config : PTW32_LIB ] ;
if ! ( $(PTW32_INCLUDE) && $(PTW32_LIB) )
{
if ! $(.notified)
{
echo "************************************************************" ;
echo "Trying to build Boost.Thread with pthread support." ;
echo "If you need pthread you should specify the paths." ;
echo "You can specify them in site-config.jam, user-config.jam" ;
echo "or in the environment." ;
echo "For example:" ;
echo "PTW32_INCLUDE=C:\\Program Files\\ptw32\\Pre-built2\\include" ;
echo "PTW32_LIB=C:\\Program Files\\ptw32\\Pre-built2\\lib" ;
echo "************************************************************" ;
.notified = true ;
}
}
else
{
local include_path = [ path.make $(PTW32_INCLUDE) ] ;
local lib_path = [ path.make $(PTW32_LIB) ] ;
local libname = pthread ;
if <toolset>msvc in $(properties)
{
libname = $(libname)VC2.lib ;
}
if <toolset>gcc in $(properties)
{
libname = lib$(libname)GC2.a ;
}
lib_path = [ path.glob $(lib_path) : $(libname) ] ;
if ! $(lib_path)
{
if ! $(.notified)
{
echo "************************************************************" ;
echo "Trying to build Boost.Thread with pthread support." ;
echo "But the library" $(libname) "could not be found in path" ;
echo $(PTW32_LIB) ;
echo "************************************************************" ;
.notified = true ;
}
}
else
{
result += <include>$(include_path) ;
result += <library>$(lib_path) ;
}
}
return $(result) ;
}
rule usage-requirements ( properties * )
{
local result ;
if <threadapi>pthread in $(properties)
{
result += <define>BOOST_THREAD_POSIX ;
if <target-os>windows in $(properties)
{
result += [ win32_pthread_paths $(properties) ] ;
# TODO: What is for static linking? Is the <library> also needed
# in that case?
}
}
return $(result) ;
}
rule requirements ( properties * )
{
local result ;
if <threadapi>pthread in $(properties)
{
result += <define>BOOST_THREAD_POSIX ;
if <target-os>windows in $(properties)
{
local paths = [ win32_pthread_paths $(properties) ] ;
if $(paths)
{
result += $(paths) ;
}
else
{
result = <build>no ;
}
}
}
return $(result) ;
}
alias thread_sources
: ## win32 sources ##
win32/thread.cpp
win32/exceptions.cpp
win32/tss_dll.cpp
win32/tss_pe.cpp
: ## requirements ##
<threadapi>win32
;
alias thread_sources
: ## pthread sources ##
pthread/thread.cpp
pthread/exceptions.cpp
pthread/once.cpp
: ## requirements ##
<threadapi>pthread
;
explicit thread_sources ;
lib boost_thread
: thread_sources
: <conditional>@requirements
:
: <link>shared:<define>BOOST_THREAD_USE_DLL=1
<link>static:<define>BOOST_THREAD_USE_LIB=1
<conditional>@usage-requirements
;

55
doc/Jamfile.v2 Normal file
View File

@@ -0,0 +1,55 @@
# (C) Copyright 2008 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)
path-constant boost-images : ../../../doc/src/images ;
xml thread : thread.qbk ;
boostbook standalone
:
thread
:
# HTML options first:
# Use graphics not text for navigation:
<xsl:param>navig.graphics=1
# How far down we chunk nested sections, basically all of them:
<xsl:param>chunk.section.depth=3
# Don't put the first section on the same page as the TOC:
<xsl:param>chunk.first.sections=1
# How far down sections get TOC's
<xsl:param>toc.section.depth=10
# Max depth in each TOC:
<xsl:param>toc.max.depth=3
# How far down we go with TOC's
<xsl:param>generate.section.toc.level=10
# Path for links to Boost:
<xsl:param>boost.root=../../../..
# Path for libraries index:
<xsl:param>boost.libraries=../../../../libs/libraries.htm
# Use the main Boost stylesheet:
<xsl:param>html.stylesheet=../../../../doc/html/boostbook.css
# PDF Options:
# TOC Generation: this is needed for FOP-0.9 and later:
#<xsl:param>fop1.extensions=1
# Or enable this if you're using XEP:
<xsl:param>xep.extensions=1
# TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9!
<xsl:param>fop.extensions=0
# No indent on body text:
<xsl:param>body.start.indent=0pt
# Margin size:
<xsl:param>page.margin.inner=0.5in
# Margin size:
<xsl:param>page.margin.outer=0.5in
# Yes, we want graphics for admonishments:
<xsl:param>admon.graphics=1
# Set this one for PDF generation *only*:
# default pnd graphics are awful in PDF form,
# better use SVG's instead:
<format>pdf:<xsl:param>admon.graphics.extension=".svg"
<format>pdf:<xsl:param>admon.graphics.path=$(boost-images)/
;

View File

@@ -1,72 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Boost.Threads Acknowledgements</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Acknowledgements</h2>
</td>
</tr>
</table>
<h2>Acknowledgments</h2>
<p><a href="../../../people/william_kempf.htm">William E. Kempf</a> was the
architect, designer, and implementor of <b>Boost.Threads</b>.</p>
<p>Important contributions were also made by Jeremy Siek (lots of input on
the design and on the implementation), Alexander Terekhov (lots of input on
the Win32 implementation, especially in regards to boost::condition, as well
as a lot of explanation of POSIX behavior), Greg Colvin (lots of input on the
design), and Paul Mclachlan, Thomas Matelich and Iain Hanson (for help in
trying to get the build to work on other platforms).</p>
<p>The documentation was written by William E. Kempf. Beman Dawes provided
additional documentation material and editing.</p>
<p>Discussions on the boost.org mailing list were essential in the development
of <b>Boost.Threads</b>. As of August 1, 2001, participants included Alan Griffiths,
Albrecht Fritzsche, Aleksey Gurtovoy, Alexander Terekhov, Andrew Green, Andy Sawyer,
Asger Alstrup Nielsen, Beman Dawes, Bill Klein, Bill Rutiser, Bill Wade, Branko
Èibej, Brent Verner, Craig Henderson, Csaba Szepesvari, Dale Peakall, Damian
Dixon, Dan Nuffer, Darryl Green, Daryle Walker, David Abrahams, David Allan
Finch, Dejan Jelovic, Dietmar Kuehl, Doug Gregor, Douglas Gregor, Duncan Harris,
Ed Brey, Eric Swanson, Eugene Karpachov, Fabrice Truillot, Frank
Gerlach, Gary Powell, Gernot Neppert, Geurt Vos, Ghazi Ramadan, Greg Colvin,
Gregory Seidman, HYS, Iain Hanson, Ian Bruntlett, J Panzer, Jeff Garland, Jeff
Paquette, Jens Maurer, Jeremy Siek, Jesse Jones, Joe Gottman, John (EBo) David,
John Bandela, John Maddock, John Max Skaller, John Panzer, Jon Jagger , Karl
Nelson, Kevlin Henney, KG Chandrasekhar, Levente Farkas, Lie-Quan Lee, Lois
Goldthwaite, Luis Pedro Coelho, Marc Girod, Mark A. Borgerding, Mark Rodgers,
Marshall Clow, Matthew Austern, Matthew Hurd, Michael D. Crawford, Michael H.
Cox , Mike Haller, Miki Jovanovic, Nathan Myers, Paul Moore, Pavel Cisler, Peter
Dimov, Petr Kocmid, Philip Nash, Rainer Deyke, Reid Sweatman, Ross Smith, Scott
McCaskill, Shalom Reich , Steve Cleary, Steven Kirk, Thomas Holenstein, Thomas
Matelich, Trevor Perrin, Valentin Bonnard, Vesa Karvonen, Wayne Miller, and
William Kempf.</p>
<p>Apologies for anyone inadvertently missed.</p>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p>©<i> Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001</i></p>
</body>
</html>

23
doc/acknowledgements.qbk Normal file
View File

@@ -0,0 +1,23 @@
[/
(C) Copyright 2007-8 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).
]
[section:acknowledgements Acknowledgments]
The original implementation of __boost_thread__ was written by William Kempf, with contributions from numerous others. This new
version initially grew out of an attempt to rewrite __boost_thread__ to William Kempf's design with fresh code that could be
released under the Boost Software License. However, as the C++ Standards committee have been actively discussing standardizing a
thread library for C++, this library has evolved to reflect the proposals, whilst retaining as much backwards-compatibility as
possible.
Particular thanks must be given to Roland Schwarz, who contributed a lot of time and code to the original __boost_thread__ library,
and who has been actively involved with the rewrite. The scheme for dividing the platform-specific implementations into separate
directories was devised by Roland, and his input has contributed greatly to improving the quality of the current implementation.
Thanks also must go to Peter Dimov, Howard Hinnant, Alexander Terekhov, Chris Thomasson and others for their comments on the
implementation details of the code.
[endsect]

72
doc/barrier.qbk Normal file
View File

@@ -0,0 +1,72 @@
[/
(C) Copyright 2007-8 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).
]
[section:barriers Barriers]
A barrier is a simple concept. Also known as a ['rendezvous], it is a synchronization point between multiple threads. The barrier is
configured for a particular number of threads (`n`), and as threads reach the barrier they must wait until all `n` threads have
arrived. Once the `n`-th thread has reached the barrier, all the waiting threads can proceed, and the barrier is reset.
[section:barrier Class `barrier`]
#include <boost/thread/barrier.hpp>
class barrier
{
public:
barrier(unsigned int count);
~barrier();
bool wait();
};
Instances of __barrier__ are not copyable or movable.
[heading Constructor]
barrier(unsigned int count);
[variablelist
[[Effects:] [Construct a barrier for `count` threads.]]
[[Throws:] [__thread_resource_error__ if an error occurs.]]
]
[heading Destructor]
~barrier();
[variablelist
[[Precondition:] [No threads are waiting on `*this`.]]
[[Effects:] [Destroys `*this`.]]
[[Throws:] [Nothing.]]
]
[heading Member function `wait`]
bool wait();
[variablelist
[[Effects:] [Block until `count` threads have called `wait` on `*this`. When the `count`-th thread calls `wait`, all waiting threads
are unblocked, and the barrier is reset. ]]
[[Returns:] [`true` for exactly one thread from each batch of waiting threads, `false` otherwise.]]
[[Throws:] [__thread_resource_error__ if an error occurs.]]
]
[endsect]
[endsect]

View File

@@ -1,145 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Boost.Threads Bibliography</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Bibliography</h2>
</td>
</tr>
</table>
<h2>Bibliography</h2>
<table border="0" cellpadding="5" width="777">
<tr>
<td width="102" valign="top" align="left"><b>[<a name="Andrews-83">Andrews
83</a>]</b></td>
<td width="645">
Gregory R. Andrews, Fred B. Schneider, <cite>Concepts and Notations for Concurrent
Programming</cite>, ACM Computing Surveys, Vol. 15, No. 1, March, 1983. <a href="http://www.acm.org/pubs/citations/journals/surveys/1983-15-1/p3-andrews/">http://www.acm.org/pubs/citations/journals/surveys/1983-15-1/p3-andrews/</a>
<p>Good general background reading.&nbsp; Includes descriptions of Path
Expressions, Message Passing, and Remote Procedure Call in addition to the
basics.&nbsp;
</td>
</tr>
<tr>
<td width="102" valign="top" align="left"><b>[<a name="Boost">Boost</a>]</b></td>
<td width="645">
The <cite> Boost</cite> world-wide web site.&nbsp; <a href="http://www.boost.org">http://www.boost.org</a>
<p>Boost.Threads is one of many Boost libraries.&nbsp; The Boost web site
includes a great deal of documentation and general information which applies to
all Boost libraries. Current copies of the libraries including documentation and
test programs may be downloaded from the web site.
</td>
</tr>
<tr>
<td width="102" valign="top" align="left"><b>[<a name="Brinch-Hansen-73">Brinch
Hansen 73</a>]</b></td>
<td width="645">
Per Brinch Hansen, <cite>Concurrent Programming Concepts</cite>, ACM Computing
Surveys, Vol. 5, No. 4, December, 1973. <a href="http://www.acm.org/pubs/articles/journals/surveys/1973-5-4/p223-hansen/p223-hansen.pdf">http://www.acm.org/pubs/articles/journals/surveys/1973-5-4/p223-hansen/</a>
<p>&quot;This paper describes the evolution of language features for
multiprogramming from event queues and semaphores to critical regions and
monitors.&quot; Includes analysis of&nbsp; why <i>events</i> are considered
error-prone. Also noteworthy because of an introductory quotation from
Christopher Alexander; Brinch Hansen was years ahead of others in recognizing
pattern concepts applied to software too.
</td>
</tr>
<tr>
<td width="102" valign="top" align="left"><b>]<a name="Butenhof-97">Butenhof
97</a>]</b></td>
<td width="645">
<p> David R. Butenhof, <cite>Programming with
POSIX Threads</cite>, Addison-Wesley 1997, ISBN 0-201-63392-2&nbsp; <a href="http://cseng.aw.com/book/0,3828,0201633922,00.html">http://cseng.aw.com/book/0,3828,0201633922,00.html</a></p>
<p>This is a very readable explanation of threads and how to use them.&nbsp; Many
of the insights given apply to all multi-threaded programming, not just POSIX
Threads.</p>
</td>
</tr>
<tr>
<td width="102" valign="top" align="left"><b>[<a name="Hoare-74">Hoare 74</a>]</b></td>
<td width="645">
<p>C.A.R Hoare, <cite> Monitors: An Operating System Structuring Concept</cite>,
Communications of the ACM, Vol. 17, No. 10. October
1974, pp. 549-557&nbsp; <a href="http://www.acm.org/classics/feb96/">http://www.acm.org/classics/feb96/ </a></p>
<p>Hoare and Brinch Hansen's work on Monitors is the basis for reliable
multi-threading patterns. This is one of the most often referenced papers in
all of computer science, and with good reason.</p>
</td>
</tr>
<tr>
<td width="102" valign="top" align="left"><b>[<a name="ISO-98">ISO 98</a>]</b></td>
<td width="645">
<p>ISO/IEC 14882:1998(E) <cite> Programming Language C++</cite>&nbsp; <a href="http://www.ansi.org">http://www.ansi.org</a></p>
<p>This is the official C++ Standards
document. Available from the ANSI (American
National Standards Institute) Electronic Standards Store.</p>
</td>
</tr>
<tr>
<td width="102" valign="top" align="left"><b>[<a name="McDowell-89">McDowell
89</a>]</b></td>
<td width="645">
Charles E McDowell, David P. Helmbold, <cite>Debugging Concurrent Programs</cite>,
ACM Computing Surveys, Vol. 21, No. 2, December, 1989. <a href="http://www.acm.org/pubs/citations/journals/surveys/1989-21-4/p593-mcdowell/">http://www.acm.org/pubs/citations/journals/surveys/1989-21-4/p593-mcdowell/</a>
<p>Identifies many of the unique failure modes and debugging difficulties
associated with concurrent programs.
</td>
</tr>
<tr>
<td width="102" valign="top" align="left"> <b>[<a name="Schmidt">Schmidt</a>]&nbsp;</b></td>
<td width="645">
<p> Douglas C. Schmidt and Irfan Pyarali, <cite>Strategies for
Implementing POSIX Condition Variables on Win32</cite>,&nbsp; Department of Computer Science, Washington University, St. Louis, Missouri.&nbsp;
<a href="http://www.cs.wustl.edu/~schmidt/win32-cv-1.html">http://www.cs.wustl.edu/~schmidt/win32-cv-1.html</a></p>
<p>Rationale for understanding Boost.Threads condition variables. Note that Alexander Terekhov found some bugs in
the implementation given in this article, so pthreads-win32 and Boost.Threads
are even more complicated yet.</p>
</td>
</tr>
<tr>
<td width="102" valign="top" align="left"> <b>[<a name="Schmidt-00">Schmidt
00</a>]&nbsp;</b></td>
<td width="645">
<p> Douglas C. Schmidt, Michael Stal, Hans Rohnert and Frank Buschmann, <cite>Pattern-Oriented Software Architecture Volume 2 - Patterns for
Concurrent and Networked Objects</cite>,&nbsp; Wiley 2000, ISBN 0-471-60695-2&nbsp; <a href="http://www.wiley.com/Corporate/Website/Objects/Products/0,9049,104671,00.html">http://www.wiley.com/Corporate/Website/Objects/Products/0,9049,104671,00.html</a></p>
<p>This is a very good explanation of how to apply several patterns useful for concurrent programming.
Among the patterns documented is the Monitor Pattern mentioned frequently in the <b>Boost.Threads</b>
documentation.</p>
</td>
</tr>
<tr>
<td width="102" valign="top" align="left"> <b>[<a name="Stroustrup-00">Stroustrup
00</a>]</b></td>
<td width="645">
Bjarne Stroustrup, <cite> The C++ Programming Language</cite>, Special Edition, Addison-Wesley
2000, ISBN 0-201-70073-5 <a href="http://cseng.aw.com/book/0,3828,0201700735,00.html">http://cseng.aw.com/book/0,3828,0201700735,00.html</a>
<p>The first book a C++ programmer should own.&nbsp; Note that the 3rd edition
(and subsequent editions like the Special Edition) has been rewritten to cover
the ISO standard language and library.
</td>
</tr>
</table>
<p>Note: The URL's above are provided in plain text form so that they will be visible
on printed copies of this document.</p>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %b %Y" startspan -->01 Oct 2001<!--webbot bot="Timestamp" endspan i-checksum="14990" -->
</p>
<p>© Copyright Beman Dawes, 2001</p>
</body>
</html>

View File

@@ -1,128 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, Boost.Threads, thread library, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost.Threads, call_once</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">call_once</h2>
</td>
</tr>
</table>
<hr>
<p><A href="#Introduction">Introduction</A><br>
<A href="#Header">Header</A><br>
<A href="#Synopsis">Synopsis</A><br>
<A href="#Members">Members</A><br>
<A href="#Example">Example</A></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <code>call_once</code> routine and <code>once_flag</code> type can be used to
run a routine exactly once. This can be used to initialize data in a
<a href="definitions.html#Thread-safe">thread-safe</a> manner.</p>
<h2><a name="Header">Header</a></h2>
<pre>
#include <a href="../../../boost/thread/once.hpp">&lt;boost/thread/once.hpp&gt;</a>
</pre>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>
namespace boost {
typedef <i>[implementation defined]</i> once_flag;
const once_flag once_init = <i>[implementation defined]</i>;
void call_once(void (*func)(), once_flag&amp; flag);
} // namespace boost
</pre>
<h2><a name="Reference">Reference</a></h2>
<hr>
<h3>once_flag</h3>
<p>This implementation defined type is used as a flag to insure a routine is called only once.
Instances of this type should be statically initialized to <code>once_init</code>.</p>
<hr>
<h3>once_init</h3>
<p>This is a constant value used to initialize <code>once_flag</code> instances
to indicate that the logically associated routine has not been run yet.</p>
<hr>
<h3>call_once</h3>
<pre>
void call_once(void (*func)(), once_flag&amp; flag);
</pre>
<p><b>Requires:</b> The function <code>func</code> shall not throw exceptions.</p>
<p><b>Effects:</b> As if (in an atomic fashion)</p>
<code>
&nbsp;&nbsp;&nbsp;if (flag == once_init)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;func();
</code>
<p><b>Postcondition:</b> <code>flag</code> != <code>once_init</code></p>
<hr>
<h2><a name="Example">Example Usage</a></h2>
<pre>
#include <a href="../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
#include <a href="../../../boost/thread/tss.hpp">&lt;boost/thread/once.hpp&gt;</a>
#include &lt;cassert&gt;
int value=0;
boost::once_flag once = boost::once_init;
void init()
{
++value;
}
void thread_proc()
{
boost::call_once(&amp;init, once);
}
int main(int argc, char* argv[])
{
boost::thread_group threads;
for (int i=0; i&lt;5; ++i)
threads.create_thread(&amp;thread_proc);
threads.join_all();
assert(value == 1);
}
</pre>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html>

83
doc/changes.qbk Normal file
View File

@@ -0,0 +1,83 @@
[/
(C) Copyright 2007-8 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).
]
[section:changes Changes since boost 1.35]
The 1.36.0 release of Boost includes a few new features in the thread library:
* New generic __lock_multiple_ref__ and __try_lock_multiple_ref__ functions for locking multiple mutexes at once.
* Rvalue reference support for move semantics where the compilers supports it.
* A few bugs fixed and missing functions added (including the serious win32 condition variable bug).
* `scoped_try_lock` types are now backwards-compatible with Boost 1.34.0 and previous releases.
* Support for passing function arguments to the thread function by supplying additional arguments to the __thread__ constructor.
* Backwards-compatibility overloads added for `timed_lock` and `timed_wait` functions to allow use of `xtime` for timeouts.
[heading Changes since boost 1.34]
Almost every line of code in __boost_thread__ has been changed since the 1.34 release of boost. However, most of the interface
changes have been extensions, so the new code is largely backwards-compatible with the old code. The new features and breaking
changes are described below.
[heading New Features]
* Instances of __thread__ and of the various lock types are now movable.
* Threads can be interrupted at __interruption_points__.
* Condition variables can now be used with any type that implements the __lockable_concept__, through the use of
`boost::condition_variable_any` (`boost::condition` is a `typedef` to `boost::condition_variable_any`, provided for backwards
compatibility). `boost::condition_variable` is provided as an optimization, and will only work with
`boost::unique_lock<boost::mutex>` (`boost::mutex::scoped_lock`).
* Thread IDs are separated from __thread__, so a thread can obtain it's own ID (using `boost::this_thread::get_id()`), and IDs can
be used as keys in associative containers, as they have the full set of comparison operators.
* Timeouts are now implemented using the Boost DateTime library, through a typedef `boost::system_time` for absolute timeouts, and
with support for relative timeouts in many cases. `boost::xtime` is supported for backwards compatibility only.
* Locks are implemented as publicly accessible templates `boost::lock_guard`, `boost::unique_lock`, `boost::shared_lock`, and
`boost::upgrade_lock`, which are templated on the type of the mutex. The __lockable_concept__ has been extended to include publicly
available __lock_ref__ and __unlock_ref__ member functions, which are used by the lock types.
[heading Breaking Changes]
The list below should cover all changes to the public interface which break backwards compatibility.
* __try_mutex__ has been removed, and the functionality subsumed into __mutex__. __try_mutex__ is left as a `typedef`,
but is no longer a separate class.
* __recursive_try_mutex__ has been removed, and the functionality subsumed into
__recursive_mutex__. __recursive_try_mutex__ is left as a `typedef`, but is no longer a separate class.
* `boost::detail::thread::lock_ops` has been removed. Code that relies on the `lock_ops` implementation detail will no longer work,
as this has been removed, as it is no longer necessary now that mutex types now have public __lock_ref__ and __unlock_ref__ member
functions.
* `scoped_lock` constructors with a second parameter of type `bool` are no longer provided. With previous boost releases,
``boost::mutex::scoped_lock some_lock(some_mutex,false);`` could be used to create a lock object that was associated with a mutex,
but did not lock it on construction. This facility has now been replaced with the constructor that takes a
`boost::defer_lock_type` as the second parameter: ``boost::mutex::scoped_lock some_lock(some_mutex,boost::defer_lock);``
* The `locked()` member function of the `scoped_lock` types has been renamed to __owns_lock_ref__.
* You can no longer obtain a __thread__ instance representing the current thread: a default-constructed __thread__ object is not
associated with any thread. The only use for such a thread object was to support the comparison operators: this functionality has
been moved to __thread_id__.
* The broken `boost::read_write_mutex` has been replaced with __shared_mutex__.
* __mutex__ is now never recursive. For Boost releases prior to 1.35 __mutex__ was recursive on Windows and not on POSIX platforms.
* When using a __recursive_mutex__ with a call to [cond_any_wait_link `boost::condition_variable_any::wait()`], the mutex is only
unlocked one level, and not completely. This prior behaviour was not guaranteed and did not feature in the tests.
[endsect]

View File

@@ -1,333 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost.Threads, condition</title>
</head>
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080" text="#000000">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><IMG height=86 alt="C++ Boost" src="../../../c++boost.gif" width=277></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">condition</h2>
</td>
</tr>
</table>
<hr>
<p><A href="#Introduction">Introduction</a><br>
<A href="#Header">Header</a><br>
<A href="#Synopsis">Synopsis</a><br>
<A href="#Members">Members</a><br>
<A href="#Example">Example</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>An object of class <code>condition</code> is a synchronization primitive used to
cause a thread to wait until a particular shared-data condition (or time) is met.
A <code>condition</code> object is always used in conjunction with a mutex
object modeling a <a href="mutex_concept.html">Mutex Concept</a>. The mutex must be locked prior to waiting on the
<code>condition</code>, which is ensured by passing a lock object modeling a <a href="lock_concept.html">Lock
Concept</a> to the <code>condition</code> object's <code>wait</code> functions. While the thread is waiting on the <code>condition</code>
object,
the mutex associated with the lock is unlocked. When the thread returns
from a call to one of the <code>condition</code> object's <code>wait</code> functions,
the mutex is again locked. The tricky lock/unlock/lock sequence is performed
automatically by the <code>condition</code> object's <code>wait</code>
functions.</p>
<p>The <code>condition</code> type is often used to implement the <i>Monitor Object</i>
and other important patterns. See <A href="bibliography.html#Schmidt-00">[Schmidt-00]</a>
and <A href="bibliography.html#Hoare-74">[Hoare 74]</a>. Monitors are one of the most
important patterns for creating reliable multithreaded programs.</p>
<p>See <A href="definitions.html">Formal Definitions</a> for definitions of thread
states <A href="definitions.html#state">blocked</a> and
<A href="definitions.html#state">ready</a>. Note that "waiting" is a synonym
for blocked.</p>
<h2><a name="Header">Header</a></h2>
<pre>
#include <A href="../../../boost/thread/condition.hpp">&lt;boost/thread/condition.hpp&gt;</a>
</pre>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>
namespace boost {
class condition : private <A href="../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
// Class condition meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
{
public:
condition();
~condition();
void notify_one();
void notify_all();
template &lt;typename <a href="scoped_lock.html">ScopedLock</a>&gt;
void wait(<a href="scoped_lock.html">ScopedLock</a>&amp; lock);
template &lt;typename <a href="scoped_lock.html">ScopedLock</a>, typename <A href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</A>&gt;
void wait(<a href="scoped_lock.html">ScopedLock</a>&amp; lock, <A href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</A> pred);
template &lt;typename <a href="scoped_lock.html">ScopedLock</a>&gt;
bool timed_wait(<a href="scoped_lock.html">ScopedLock</a>&amp; lock, const xtime&amp; xt);
template &lt;typename <a href="scoped_lock.html">ScopedLock</a>, typename <A href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</A>&gt;
bool timed_wait(<a href="scoped_lock.html">ScopedLock</a>&amp; lock, const xtime&amp; xt, <A href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</A> pred);
};
} // namespace boost
</pre>
<h2><a name="Members">Members</a></h2>
<hr>
<h3>Constructor</h3>
<pre>
condition();
</pre>
<p><b>Effects:</b> Constructs a <code>condition</code>.</p>
<hr>
<h3>Destructor</h3>
<pre>
~condition();
</pre>
<p><b>Effects:</b> Destroys <code>*this</code>.</p>
<hr>
<h3>notify_one</h3>
<pre>
void notify_one();
</pre>
<p><b>Effects:</b> If there is a thread waiting on <code>*this</code>, change
that thread's state to ready. Otherwise there is no effect.</p>
<p><b>Notes:</b> If more that one thread is waiting on the condition, it is
unspecified which is made ready.</p>
<hr>
<h3>notify_all</h3>
<pre>
void notify_all();
</pre>
<p><b>Effects:</b> Change the state of all threads waiting on <code>*this</code>
to ready. If there are no waiting threads, <code>notify_all()</code> has no effect.</p>
<hr>
<h3>wait</h3>
<pre>
template &lt;typename ScopedLock&gt;
void wait(ScopedLock&amp; lock);
</pre>
<p><b>Requires:</b> ScopedLock meets the
<A href="lock_concept.html#ScopedLock">ScopedLock</a> requirements.</p>
<p><b>Effects:</b> Releases the lock on the <A href="mutex_concept.html">mutex model</a>
associated with <code>lock</code>, blocks the current thread of execution until readied
by a call to <code>this-&gt;notify_one()</code> or <code>this-&gt;notify_all()</code>,
and then reacquires the lock. All effects occur in an atomic fashion.</p>
<p><b>Throws:</b> <code><A href="lock_error.html">lock_error</a></code>
if <code>!lock.locked()</code></p>
<p><b>Danger:</b> This version should always be used within a loop checking that the
state logically associated with the <code>condition</code> has become true. Without
the loop, race conditions can ensue due to possible "spurious wake ups". The second
version encapsulates this loop idiom internally and is generally the preferred method.</p>
<pre>
template &lt;typename ScopedLock, typename Pr&gt;
void wait(ScopedLock&amp; lock, Pr pred);
</pre>
<p><b>Requires:</b> ScopedLock meets the
<A href="lock_concept.html#ScopedLock">ScopedLock</a> requirements, return from
<code>pred()</code> convertible to bool.</p>
<p><b>Effects:</b> As if:</p>
<code>
&nbsp;&nbsp;&nbsp;while (!pred()) wait(lock)
</code>
<p><b>Throws:</b> <code><A href="lock_error.html">lock_error</a></code> if
<code>!lock.locked()</code></p>
<hr>
<h3>timed_wait</h3>
<pre>
template &lt;typename ScopedTimedLock&gt;
bool timed_wait(ScopedTimedLock&amp; lock, const <a href="xtime.html">xtime</a>&amp; xt);
</pre>
<p><b>Requires:</b> ScopedTimeLock meets the
<A href="lock_concept.html#ScopedTimedLock">ScopedTimedLock</a> requirements.</p>
<p><b>Effects:</b> Releases the lock on the <A href="mutex_concept.html">mutex model</a>
associated with the <code>lock</code>, blocks the current thread of execution until
readied by a call to <code>this-&gt;notify_one()</code> or
<code>this-&gt;notify_all()</code>, or until <code>xt</code>, and then reacquires the
lock. All effects occur in an atomic fashion.</p>
<p><b>Throws:</b> <code><A href="lock_error.html">lock_error</a></code> if
<code>!lock.locked()</code></p>
<p><b>Danger:</b> This version should always be used within a loop checking that the
state logically associated with the <code>condition</code> has become true. Without
the loop, race conditions can ensue due to "spurious wake ups". The second version
encapsulates this loop idiom internally and is generally the preferred method.</p>
<p><b>Returns:</b> <code>false</code> if <code>xt</code> is reached, otherwise
<code>true</code>.</p>
<pre>
template &lt;typename ScopedTimedLock, typename Pr&gt;
bool timed_wait(ScopedTimedLock&amp; lock, const <a href="xtime.html">xtime</a>&amp; xt, Pr pred);
</pre>
<p><b>Requires: </b>ScopedTimeLock meets the
<A href="lock_concept.html#ScopedTimedLock">ScopedTimedLock</a> requirements,
return from <code>pred()</code> convertible to bool.</p>
<p><b>Effects: </b>As if:</p>
<code>
&nbsp;&nbsp;&nbsp;while (!pred())<br>
&nbsp;&nbsp;&nbsp;{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!timed_wait(lock, xt))<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;<br>
&nbsp;&nbsp;&nbsp;}
</code>
<p><b>Throws:</b> <code><A href="lock_error.html">lock_error</a></code> if
<code>!lock.locked()</code></p>
<p><b>Returns:</b> <code>false</code> if <code>xt</code> is reached, otherwise
<code>true</code>.</p>
<hr>
<h2><a name="Example">Example Usage</a></h2>
<pre>
#include &lt;iostream&gt;
#include &lt;vector&gt;
#include <A href="../../../boost/utility.hpp">&lt;boost/utility.hpp&gt;</a>
#include <A href="../../../boost/thread/condition.hpp">&lt;boost/thread/condition.hpp&gt;</a>
#include <A href="../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
class bounded_buffer : private boost::noncopyable
{
public:
typedef boost::mutex::scoped_lock lock;
bounded_buffer(int n) : begin(0), end(0), buffered(0), circular_buf(n) { }
void send (int m) {
lock lk(monitor);
while (buffered == circular_buf.size())
buffer_not_full.wait(lk);
circular_buf[end] = m;
end = (end+1) % circular_buf.size();
++buffered;
buffer_not_empty.notify_one();
}
int receive() {
lock lk(monitor);
while (buffered == 0)
buffer_not_empty.wait(lk);
int i = circular_buf[begin];
begin = (begin+1) % circular_buf.size();
--buffered;
buffer_not_full.notify_one();
return i;
}
private:
int begin, end, buffered;
std::vector&lt;int&gt; circular_buf;
boost::condition buffer_not_full, buffer_not_empty;
boost::mutex monitor;
};
bounded_buffer buf(2);
void sender() {
int n = 0;
while (n &lt; 100) {
buf.send(n);
std::cout &lt;&lt; &quot;sent: &quot; &lt;&lt; n &lt;&lt; std::endl;
++n;
}
buf.send(-1);
}
void receiver() {
int n;
do {
n = buf.receive();
std::cout &lt;&lt; &quot;received: &quot; &lt;&lt; n &lt;&lt; std::endl;
} while (n != -1); // -1 indicates end of buffer
}
int main(int, char*[])
{
boost::thread thrd1(&amp;sender);
boost::thread thrd2(&amp;receiver);
thrd1.join();
thrd2.join();
return 0;
}
</pre>
<p>Typical output (dependent on scheduling policies) is:</p>
<pre>
sent: 0
sent: 1
received: 0
received: 1
sent: 2
sent: 3
received: 2
received: 3
sent: 4
received: 4
</pre>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <A href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html>

513
doc/condition_variables.qbk Normal file
View File

@@ -0,0 +1,513 @@
[/
(C) Copyright 2007-8 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).
]
[section:condvar_ref Condition Variables]
[heading Synopsis]
The classes `condition_variable` and `condition_variable_any` provide a
mechanism for one thread to wait for notification from another thread that a
particular condition has become true. The general usage pattern is that one
thread locks a mutex and then calls `wait` on an instance of
`condition_variable` or `condition_variable_any`. When the thread is woken from
the wait, then it checks to see if the appropriate condition is now true, and
continues if so. If the condition is not true, then the thread then calls `wait`
again to resume waiting. In the simplest case, this condition is just a boolean
variable:
boost::condition_variable cond;
boost::mutex mut;
bool data_ready;
void process_data();
void wait_for_data_to_process()
{
boost::unique_lock<boost::mutex> lock(mut);
while(!data_ready)
{
cond.wait(lock);
}
process_data();
}
Notice that the `lock` is passed to `wait`: `wait` will atomically add the
thread to the set of threads waiting on the condition variable, and unlock the
mutex. When the thread is woken, the mutex will be locked again before the call
to `wait` returns. This allows other threads to acquire the mutex in order to
update the shared data, and ensures that the data associated with the condition
is correctly synchronized.
In the mean time, another thread sets the condition to `true`, and then calls
either `notify_one` or `notify_all` on the condition variable to wake one
waiting thread or all the waiting threads respectively.
void retrieve_data();
void prepare_data();
void prepare_data_for_processing()
{
retrieve_data();
prepare_data();
{
boost::lock_guard<boost::mutex> lock(mut);
data_ready=true;
}
cond.notify_one();
}
Note that the same mutex is locked before the shared data is updated, but that
the mutex does not have to be locked across the call to `notify_one`.
This example uses an object of type `condition_variable`, but would work just as
well with an object of type `condition_variable_any`: `condition_variable_any`
is more general, and will work with any kind of lock or mutex, whereas
`condition_variable` requires that the lock passed to `wait` is an instance of
`boost::unique_lock<boost::mutex>`. This enables `condition_variable` to make
optimizations in some cases, based on the knowledge of the mutex type;
`condition_variable_any` typically has a more complex implementation than
`condition_variable`.
[section:condition_variable Class `condition_variable`]
#include <boost/thread/condition_variable.hpp>
namespace boost
{
class condition_variable
{
public:
condition_variable();
~condition_variable();
void notify_one();
void notify_all();
void wait(boost::unique_lock<boost::mutex>& lock);
template<typename predicate_type>
void wait(boost::unique_lock<boost::mutex>& lock,predicate_type predicate);
bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time);
template<typename duration_type>
bool timed_wait(boost::unique_lock<boost::mutex>& lock,duration_type const& rel_time);
template<typename predicate_type>
bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time,predicate_type predicate);
template<typename duration_type,typename predicate_type>
bool timed_wait(boost::unique_lock<boost::mutex>& lock,duration_type const& rel_time,predicate_type predicate);
// backwards compatibility
bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::xtime const& abs_time);
template<typename predicate_type>
bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::xtime const& abs_time,predicate_type predicate);
};
}
[section:constructor `condition_variable()`]
[variablelist
[[Effects:] [Constructs an object of class `condition_variable`.]]
[[Throws:] [__thread_resource_error__ if an error occurs.]]
]
[endsect]
[section:destructor `~condition_variable()`]
[variablelist
[[Precondition:] [All threads waiting on `*this` have been notified by a call to
`notify_one` or `notify_all` (though the respective calls to `wait` or
`timed_wait` need not have returned).]]
[[Effects:] [Destroys the object.]]
[[Throws:] [Nothing.]]
]
[endsect]
[section:notify_one `void notify_one()`]
[variablelist
[[Effects:] [If any threads are currently __blocked__ waiting on `*this` in a call
to `wait` or `timed_wait`, unblocks one of those threads.]]
[[Throws:] [Nothing.]]
]
[endsect]
[section:notify_all `void notify_all()`]
[variablelist
[[Effects:] [If any threads are currently __blocked__ waiting on `*this` in a call
to `wait` or `timed_wait`, unblocks all of those threads.]]
[[Throws:] [Nothing.]]
]
[endsect]
[section:wait `void wait(boost::unique_lock<boost::mutex>& lock)`]
[variablelist
[[Precondition:] [`lock` is locked by the current thread, and either no other
thread is currently waiting on `*this`, or the execution of the `mutex()` member
function on the `lock` objects supplied in the calls to `wait` or `timed_wait`
in all the threads currently waiting on `*this` would return the same value as
`lock->mutex()` for this call to `wait`.]]
[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
thread will unblock when notified by a call to `this->notify_one()` or
`this->notify_all()`, or spuriously. When the thread is unblocked (for whatever
reason), the lock is reacquired by invoking `lock.lock()` before the call to
`wait` returns. The lock is also reacquired by invoking `lock.lock()` if the
function exits with an exception.]]
[[Postcondition:] [`lock` is locked by the current thread.]]
[[Throws:] [__thread_resource_error__ if an error
occurs. __thread_interrupted__ if the wait was interrupted by a call to
__interrupt__ on the __thread__ object associated with the current thread of execution.]]
]
[endsect]
[section:wait_predicate `template<typename predicate_type> void wait(boost::unique_lock<boost::mutex>& lock, predicate_type pred)`]
[variablelist
[[Effects:] [As-if ``
while(!pred())
{
wait(lock);
}
``]]
]
[endsect]
[section:timed_wait `bool timed_wait(boost::unique_lock<boost::mutex>& lock,boost::system_time const& abs_time)`]
[variablelist
[[Precondition:] [`lock` is locked by the current thread, and either no other
thread is currently waiting on `*this`, or the execution of the `mutex()` member
function on the `lock` objects supplied in the calls to `wait` or `timed_wait`
in all the threads currently waiting on `*this` would return the same value as
`lock->mutex()` for this call to `wait`.]]
[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
thread will unblock when notified by a call to `this->notify_one()` or
`this->notify_all()`, when the time as reported by `boost::get_system_time()`
would be equal to or later than the specified `abs_time`, or spuriously. When
the thread is unblocked (for whatever reason), the lock is reacquired by
invoking `lock.lock()` before the call to `wait` returns. The lock is also
reacquired by invoking `lock.lock()` if the function exits with an exception.]]
[[Returns:] [`false` if the call is returning because the time specified by
`abs_time` was reached, `true` otherwise.]]
[[Postcondition:] [`lock` is locked by the current thread.]]
[[Throws:] [__thread_resource_error__ if an error
occurs. __thread_interrupted__ if the wait was interrupted by a call to
__interrupt__ on the __thread__ object associated with the current thread of execution.]]
]
[endsect]
[section:timed_wait_rel `template<typename duration_type> bool timed_wait(boost::unique_lock<boost::mutex>& lock,duration_type const& rel_time)`]
[variablelist
[[Precondition:] [`lock` is locked by the current thread, and either no other
thread is currently waiting on `*this`, or the execution of the `mutex()` member
function on the `lock` objects supplied in the calls to `wait` or `timed_wait`
in all the threads currently waiting on `*this` would return the same value as
`lock->mutex()` for this call to `wait`.]]
[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
thread will unblock when notified by a call to `this->notify_one()` or
`this->notify_all()`, after the period of time indicated by the `rel_time`
argument has elapsed, or spuriously. When the thread is unblocked (for whatever
reason), the lock is reacquired by invoking `lock.lock()` before the call to
`wait` returns. The lock is also reacquired by invoking `lock.lock()` if the
function exits with an exception.]]
[[Returns:] [`false` if the call is returning because the time period specified
by `rel_time` has elapsed, `true` otherwise.]]
[[Postcondition:] [`lock` is locked by the current thread.]]
[[Throws:] [__thread_resource_error__ if an error
occurs. __thread_interrupted__ if the wait was interrupted by a call to
__interrupt__ on the __thread__ object associated with the current thread of execution.]]
]
[note The duration overload of timed_wait is difficult to use correctly. The overload taking a predicate should be preferred in most cases.]
[endsect]
[section:timed_wait_predicate `template<typename predicate_type> bool timed_wait(boost::unique_lock<boost::mutex>& lock, boost::system_time const& abs_time, predicate_type pred)`]
[variablelist
[[Effects:] [As-if ``
while(!pred())
{
if(!timed_wait(lock,abs_time))
{
return pred();
}
}
return true;
``]]
]
[endsect]
[endsect]
[section:condition_variable_any Class `condition_variable_any`]
#include <boost/thread/condition_variable.hpp>
namespace boost
{
class condition_variable_any
{
public:
condition_variable_any();
~condition_variable_any();
void notify_one();
void notify_all();
template<typename lock_type>
void wait(lock_type& lock);
template<typename lock_type,typename predicate_type>
void wait(lock_type& lock,predicate_type predicate);
template<typename lock_type>
bool timed_wait(lock_type& lock,boost::system_time const& abs_time);
template<typename lock_type,typename duration_type>
bool timed_wait(lock_type& lock,duration_type const& rel_time);
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& lock,boost::system_time const& abs_time,predicate_type predicate);
template<typename lock_type,typename duration_type,typename predicate_type>
bool timed_wait(lock_type& lock,duration_type const& rel_time,predicate_type predicate);
// backwards compatibility
template<typename lock_type>
bool timed_wait(lock_type>& lock,boost::xtime const& abs_time);
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& lock,boost::xtime const& abs_time,predicate_type predicate);
};
}
[section:constructor `condition_variable_any()`]
[variablelist
[[Effects:] [Constructs an object of class `condition_variable_any`.]]
[[Throws:] [__thread_resource_error__ if an error occurs.]]
]
[endsect]
[section:destructor `~condition_variable_any()`]
[variablelist
[[Precondition:] [All threads waiting on `*this` have been notified by a call to
`notify_one` or `notify_all` (though the respective calls to `wait` or
`timed_wait` need not have returned).]]
[[Effects:] [Destroys the object.]]
[[Throws:] [Nothing.]]
]
[endsect]
[section:notify_one `void notify_one()`]
[variablelist
[[Effects:] [If any threads are currently __blocked__ waiting on `*this` in a call
to `wait` or `timed_wait`, unblocks one of those threads.]]
[[Throws:] [Nothing.]]
]
[endsect]
[section:notify_all `void notify_all()`]
[variablelist
[[Effects:] [If any threads are currently __blocked__ waiting on `*this` in a call
to `wait` or `timed_wait`, unblocks all of those threads.]]
[[Throws:] [Nothing.]]
]
[endsect]
[section:wait `template<typename lock_type> void wait(lock_type& lock)`]
[variablelist
[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
thread will unblock when notified by a call to `this->notify_one()` or
`this->notify_all()`, or spuriously. When the thread is unblocked (for whatever
reason), the lock is reacquired by invoking `lock.lock()` before the call to
`wait` returns. The lock is also reacquired by invoking `lock.lock()` if the
function exits with an exception.]]
[[Postcondition:] [`lock` is locked by the current thread.]]
[[Throws:] [__thread_resource_error__ if an error
occurs. __thread_interrupted__ if the wait was interrupted by a call to
__interrupt__ on the __thread__ object associated with the current thread of execution.]]
]
[endsect]
[section:wait_predicate `template<typename lock_type,typename predicate_type> void wait(lock_type& lock, predicate_type pred)`]
[variablelist
[[Effects:] [As-if ``
while(!pred())
{
wait(lock);
}
``]]
]
[endsect]
[section:timed_wait `template<typename lock_type> bool timed_wait(lock_type& lock,boost::system_time const& abs_time)`]
[variablelist
[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
thread will unblock when notified by a call to `this->notify_one()` or
`this->notify_all()`, when the time as reported by `boost::get_system_time()`
would be equal to or later than the specified `abs_time`, or spuriously. When
the thread is unblocked (for whatever reason), the lock is reacquired by
invoking `lock.lock()` before the call to `wait` returns. The lock is also
reacquired by invoking `lock.lock()` if the function exits with an exception.]]
[[Returns:] [`false` if the call is returning because the time specified by
`abs_time` was reached, `true` otherwise.]]
[[Postcondition:] [`lock` is locked by the current thread.]]
[[Throws:] [__thread_resource_error__ if an error
occurs. __thread_interrupted__ if the wait was interrupted by a call to
__interrupt__ on the __thread__ object associated with the current thread of execution.]]
]
[endsect]
[section:timed_wait_rel `template<typename lock_type,typename duration_type> bool timed_wait(lock_type& lock,duration_type const& rel_time)`]
[variablelist
[[Effects:] [Atomically call `lock.unlock()` and blocks the current thread. The
thread will unblock when notified by a call to `this->notify_one()` or
`this->notify_all()`, after the period of time indicated by the `rel_time`
argument has elapsed, or spuriously. When the thread is unblocked (for whatever
reason), the lock is reacquired by invoking `lock.lock()` before the call to
`wait` returns. The lock is also reacquired by invoking `lock.lock()` if the
function exits with an exception.]]
[[Returns:] [`false` if the call is returning because the time period specified
by `rel_time` has elapsed, `true` otherwise.]]
[[Postcondition:] [`lock` is locked by the current thread.]]
[[Throws:] [__thread_resource_error__ if an error
occurs. __thread_interrupted__ if the wait was interrupted by a call to
__interrupt__ on the __thread__ object associated with the current thread of execution.]]
]
[note The duration overload of timed_wait is difficult to use correctly. The overload taking a predicate should be preferred in most cases.]
[endsect]
[section:timed_wait_predicate `template<typename lock_type,typename predicate_type> bool timed_wait(lock_type& lock, boost::system_time const& abs_time, predicate_type pred)`]
[variablelist
[[Effects:] [As-if ``
while(!pred())
{
if(!timed_wait(lock,abs_time))
{
return pred();
}
}
return true;
``]]
]
[endsect]
[endsect]
[section:condition Typedef `condition`]
#include <boost/thread/condition.hpp>
typedef condition_variable_any condition;
The typedef `condition` is provided for backwards compatibility with previous boost releases.
[endsect]
[endsect]

View File

@@ -1,103 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<title>Boost.Threads, Configuration Information</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Configuration Information</h2>
</td>
</tr>
</table>
<hr>
<p><b>Boost.Threads</b> uses several configuration macros in <a href="../../config/config.htm"> &lt;boost/config.hpp&gt;</a>.
These macros are documented here. Most of the macros are
of interest only to developers attempting to provide new implementations of <b>Boost.Threads</b>.
The one exception to this is BOOST_HAS_THREADS.</p>
<table cellspacing="10" width="100%">
<tr>
<td valign="top">
<b>Macro</b>
</td>
<td valign="top">
<b>Meaning</b>
</td>
</tr>
<tr>
<td valign="top">
BOOST_HAS_THREADS
</td>
<td valign="top">
Indicates that threading support is available. This means both that there is a
platform specific implementation for <b>Boost.Threads</b> and that threading
support has been enabled in a platform specific manner. For instance, on the
Win32 platform there's an implementation for <b>Boost.Threads</b> but unless
the program is compiled against one of the multi-threading runtimes
(often determined by the
compiler predefining the macro _MT) the
BOOST_HAS_THREADS macro remains undefined.
</td>
</tr>
<tr>
<td valign="top">
BOOST_HAS_WINTHREADS
</td>
<td valign="top">
Indicates that the platform has the Microsoft Win32 threading libraries,
and that they should be used
to implement <b>Boost.Threads</b>.
</td>
</tr>
<tr>
<td valign="top">
BOOST_HAS_PTHREADS
</td>
<td valign="top">
Indicates that the platform has the POSIX pthreads libraries, and that
they should be used
to implement <b>Boost.Threads</b>.
</td>
</tr>
<tr>
<td valign="top">
BOOST_HAS_FTIME
</td>
<td valign="top">
Indicates that the implementation should use GetSystemTimeAsFileTime() and
the FILETIME type to calculate the current time. This is an implementation
detail used by boost::detail::getcurtime().
</td>
</tr>
<tr>
<td valign="top">
BOOST_HAS_GETTTIMEOFDAY
</td>
<td valign="top">
Indicates that the implementation should use gettimeofday() to calculate the
current time. This is an implementation detail used by boost::detail::getcurtime().
</td>
</tr>
</table>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,244 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Boost.Threads Definitions</title>
</head>
<body bgcolor="#FFFFFF">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center"> Definitions</h2>
</td>
</tr>
</table>
<h2>Introduction</h2>
<p>The definitions are given in terms of the <a href="bibliography.html#ISO-98"> C++ Standard</a>.&nbsp; References to the standard
are in the form [1.2.3/4], which
represents the section number, with the paragraph number following the &quot;/&quot;.</p>
<p>Because the definitions are written in something akin to
&quot;standardese&quot;, they can be difficult to understand.&nbsp; The intent
isn't to confuse, but rather to clarify the additional requirements
Boost.Threads places on a C++ implementation as defined by the C++ Standard.</p>
<h2>Definitions</h2>
<h3>Thread</h3>
<p>Thread is short for &quot;thread of execution&quot;. A thread of execution is an execution environment [1.9/7] within the execution environment
of a C++ program [1.9]. The main() function [3.6.1] of the program is the
initial function of the initial thread. A program in a multi-threading
environment always has an initial thread even if the program explicitly creates
no additional threads.</p>
<p>Unless otherwise specified, each thread shares all aspects of its execution environment with
other threads in the program. Shared aspects of the execution environment
include, but are not limited to, the following:</p>
<ul>
<li>Static storage duration (static, extern) objects [3.7.1].</li>
</ul>
<ul>
<li>Dynamic storage duration (heap) objects [3.7.3].&nbsp; Thus each memory
allocation will return a unique addresses, regardless of the thread making
the allocation request.</li>
</ul>
<ul>
<li>Automatic storage duration (stack) objects [3.7.2] accessed via pointer or
reference from another thread.</li>
</ul>
<ul>
<li>Resources provided by the operating
system.&nbsp; For example, files.</li>
</ul>
<ul>
<li>The program itself.&nbsp; In other words, each thread is executing some
function of the same program, not a totally different program.</li>
</ul>
<p>Each thread has its own:</p>
<ul>
<li>Registers and current execution sequence (program counter) [1.9/5].</li>
</ul>
<ul>
<li>Automatic storage duration (stack) objects [3.7.2].</li>
</ul>
<h3><a name="Thread-safe">Thread-safe</a></h3>
<p>A program is thread-safe if it has no <a href="#Race condition">race
conditions</a>, does not <a href="#Deadlock">deadlock</a>, and has no <a href="#Priority failure">priority
failures</a>.</p>
<p>Note that thread-safety does not necessarily imply efficiency, and than while
some thread-safety violations can be determined statically at compile time, many
thread-safety errors can only only be detected at runtime.</p>
<h3>Thread <a name="State">State</a></h3>
<p>During the lifetime of a thread, it shall be in one of the following
states:</p>
<table border="1" cellpadding="5">
<tr>
<td><b>State</b></td>
<td><b>Description</b></td>
</tr>
<tr>
<td>Ready</td>
<td>Ready to run, but waiting for a processor.</td>
</tr>
<tr>
<td>Running</td>
<td>Currently executing on a processor. Zero or more threads may be running
at any time, with a maximum equal to the number of processors.&nbsp;</td>
</tr>
<tr>
<td>Blocked</td>
<td>Waiting for some resource other than a processor which is not currently
available, or for the completion of calls to library functions [1.9/6].
The term &quot;waiting&quot; is synonymous for &quot;blocked&quot;</td>
</tr>
<tr>
<td>Terminated</td>
<td>Finished execution but not yet detached or joined.</td>
</tr>
</table>
<p>Thread state transitions shall occur only as specified:</p>
<table border="1" cellpadding="5">
<tr>
<td><b>From</b></td>
<td><b>To</b></td>
<td><b>Cause</b></td>
</tr>
<tr>
<td>
<p align="left">[none]</td>
<td>Ready</td>
<td>Thread is created by a call to a library function.&nbsp; In the case of
the initial thread, creation is implicit and occurs during the startup of
the main() function [3.6.1].</td>
</tr>
<tr>
<td>Ready</td>
<td>Running</td>
<td>Processor becomes available.</td>
</tr>
<tr>
<td>Running</td>
<td>Ready</td>
<td>Thread preempted.</td>
</tr>
<tr>
<td>Running</td>
<td>Blocked</td>
<td>Thread calls a library function which waits for a resource or for the
completion of I/O.</td>
</tr>
<tr>
<td>Running</td>
<td>Terminated</td>
<td>Thread returns from its initial function, calls a thread termination
library function, or is cancelled by some other thread calling a thread
termination library function.</td>
</tr>
<tr>
<td>Blocked</td>
<td>Ready</td>
<td>The resource being waited for becomes available, or the blocking library
function completes.</td>
</tr>
<tr>
<td>Terminated</td>
<td>[none]</td>
<td>Thread is detached or joined by some other thread calling the
appropriate library function, or by program termination [3.6.3].</td>
</tr>
</table>
<p>[Note: if a suspend() function is added to the threading library, additional
transitions to the blocked state will have to be added to the above table.]</p>
<h3><a name="Race condition">Race condition</a></h3>
<p>A race condition is what occurs when multiple threads read and
write to the same memory without proper synchronization, resulting in an
incorrect value being read or written.&nbsp; The result of a race condition may
be a bit pattern which isn't even a valid value for the data type. A race
condition results in undefined behavior [1.3.12].</p>
<p>Race conditions can be prevented by serializing memory access
using the tools provided by Boost.Threads.&nbsp;</p>
<h3><a name="Deadlock">Deadlock</a></h3>
<p>Deadlock is an execution state where for some set of threads, each thread in
the set is blocked waiting for some action by one of the other threads in the
set. Since each is waiting on the others, none will ever become ready again.</p>
<h3><a name="Priority failure">Priority failure</a></h3>
<p>A priority failure (such as priority inversion or infinite overtaking) occurs
when threads executed in such a sequence that required work is not performed in
time to be useful.</p>
<h2>Memory visibility between threads</h2>
<p>An address [1.7] shall always point to the same memory byte, regardless of the
thread or processor dereferencing the address.</p>
<p>An object [1.8, 1.9] is accessible from multiple threads if it is of
static storage duration (static, extern) [3.7.1], or if a pointer or reference to
it is explicitly or
implicitly dereferenced in multiple threads.</p>
<p>For an object accessible from multiple threads, the value of the object
accessed from one thread may be indeterminate or different than the value
accessed from another thread, except under the conditions specified in the following
table.&nbsp;&nbsp; For the same row of the table, the value of an object
accessible at the indicated sequence point in thread A will be determinate and the
same if accessed at or after the indicated sequence point in thread B, provided
the object is not otherwise modified. In the table, the
&quot;sequence point at a call&quot; is the sequence point after the evaluation
of all function arguments [1.9/17], while the &quot;sequence point after a
call&quot; is the sequence point after the copying of the returned
value...&quot; [1.9/17].</p>
<table border="1" cellpadding="5">
<tr>
<td align="center"><b>Thread A</b></td>
<td align="center"><b>Thread B</b></td>
</tr>
<tr>
<td>The sequence point at a call to a library thread-creation
function.&nbsp;</td>
<td>The first sequence point of the initial function in the new thread
created by the Thread A call.</td>
</tr>
<tr>
<td>The sequence point at a call to a library function which locks a mutex,
directly or by waiting for a condition variable.</td>
<td>The sequence point after a call to a library function which unlocks the
same mutex.</td>
</tr>
<tr>
<td>The last sequence point before thread termination.</td>
<td>The sequence point after a call to a library function which joins the
terminated thread.</td>
</tr>
<tr>
<td>The sequence point at a call to a library function which signals or
broadcasts a condition variable.</td>
<td>The sequence point after the call to the library function which was
waiting on that same condition variable or signal.</td>
</tr>
</table>
<p>The architecture of the execution environment and the observable behavior of
the abstract machine [1.9] shall be the same on all processors.</p>
<p>The latitude granted by the C++ standard for an implementation to alter the
definition of observable behavior of the abstract machine to include additional library I/O
functions [1.9/6] is extended to include threading library functions.</p>
<p>When an exception is thrown and there is no matching exception handler in the
same thread, behavior is undefined.&nbsp; The preferred behavior is the same as when there is no matching exception handler
in a program [15.3/9].&nbsp; That is, terminate() is called, and it is implementation defined
whether or not the stack is unwound.</p>
<h2><a name="Acknowledgements">Acknowledgements</a></h2>
<p>This document has been much improved by the incorporation of comments from
William Kempf.</p>
<p>The visibility rules are based on <a href="bibliography.html#Butenhof-97">[Butenhof
97]</a>.&nbsp;</p>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %b %Y" startspan -->01 Oct 2001<!--webbot bot="Timestamp" endspan i-checksum="14990" -->
</p>
<p>© Copyright Beman Dawes, 2001</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
</body>
</html>

View File

@@ -1,174 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost.Threads, FAQ</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Frequently Asked Questions</h2>
</td>
</tr>
</table>
<hr>
<h2>1. Are lock objects <a href="definitions.html#Thread-safe">thread-safe</a>?</h2>
<p><b>No!</b> Lock objects are not meant to be shared between threads. They are meant to
be short lived objects created on automatic storage within a code block. Any other usage
is just likely to lead to errors and won't really be of actual benefit any way. Share
<a href="mutex_concept.html">mutexes</a>, not locks. For more information see the
<a href="rationale.html#lock_objects">rationale</a> behind the design for lock objects.</p>
<h2>2a. Why was Boost.Threads modeled after (specific library name)?</h2>
<p>It wasn't. Boost.Threads was designed from scratch. Extensive design
discussions involved numerous people representing a wide range of experience across
many platforms. To ensure portability, the initial implements were done in
parallel using POSIX Threads and theWin32 threading API. But the Boost.Threads
design is very much in the spirit of C++, and thus doesn't model such C based
APIs.</p>
<h2>2b. Why wasn't Boost.Threads modeled after (specific library name)?</h2>
<p>Existing C++ libraries either seemed dangerous (often failing to take
advantage of prior art to reduce errors) or had excessive dependencies on
library components unrelated to threading. Existing C libraries couldn't meet
our C++ requirements, and were also missing certain features. For
instance, POSIX threads doesn't support a maximum value for semaphores.
The WIN32 thread API lacks condition variables, even though these are critical
for the important Monitor pattern <a href="bibliography.html#Schmidt-00">[Schmidt
00]</a>.</p>
<h2>3. Why do <a href="mutex_concept.html"> Mutexes</a> have noncopyable semantics?</h2>
<p>To ensure that <a href="definitions.html#Deadlock"> deadlocks</a> don't occur. The only logical form of copy would be to
use some sort of shallow copy semantics in which multiple mutex objects could refer
to the same mutex state. This means that if ObjA has a mutex object as part of its state
and ObjB is copy constructed from it, then when ObjB::foo() locks the mutex it has effectively
locked ObjA as well. This behavior can result in deadlock. Other
copy semantics result in similar problems (if you think you can prove this to
be wrong then supply us with an alternative and we'll reconsider).</p>
<h2>4. How can you prevent <a href="definitions.html#Deadlock"> deadlock</a> from occurring when a thread must lock multiple
mutexes?</h2>
<p>Always lock them in the same order. One easy way of doing this is to use
each mutex's address to determine the order in which they are locked. A future
Boost.Threads concept may wrap this pattern up in a reusable class.</p>
<h2>5. Don't noncopyable <a href="mutex_concept.html"> mutex</a> semantics mean that a
class with a mutex member will be noncopyable as well?</h2>
<p>No, but what it does mean is that the compiler can't generate a copy constructor
and assignment operator, so they will have to be coded explicitly. This is a
<b>good thing</b>, however, since the compiler generated operations would not
be <a href="definitions.html#Thread-safe">thread-safe</a>. The following is a
simple example of a class with copyable semantics and internal synchronization through
a mutex member.</p>
<pre>
class counter
{
public:
// Doesn't need synchronization since there can be no references to *this
// until after it's constructed!
explicit counter(int initial_value)
: m_value(initial_value)
{
}
// We only need to syncronize other for the same reason we don't have to
// synchronize on construction!
counter(const counter&amp; other)
{
boost::mutex::scoped_lock scoped_lock(other.m_mutex);
m_value = other.m_value;
}
// For assignment we need to synchronize both objects!
const counter&amp; operator=(const counter&amp; other)
{
if (this == &amp;other)
return *this;
boost::mutex::scoped_lock lock1(&amp;m_mutex &lt; &amp;other.m_mutex ? m_mutex : other.m_mutex);
boost::mutex::scoped_lock lock2(&amp;m_mutex &gt; &amp;other.m_mutex ? m_mutex : other.m_mutex);
m_value = other.m_value;
return *this;
}
int value() const
{
boost::mutex::scoped_lock scoped_lock(m_mutex);
return m_value;
}
int increment()
{
boost::mutex::scoped_lock scoped_lock(m_mutex);
return ++m_value;
}
private:
mutable boost::mutex m_mutex;
int m_value;
};
</pre>
<h2>6. How can you lock a <a href="mutex_concept.html"> mutex</a> member in a const member function, in order to
implement the Monitor Pattern?</h2>
<p>The Monitor Pattern mutex <a href="bibliography.html#Schmidt-00">[Schmidt
00]</a> should simply be declared as mutable. See the example code above. The internal state of mutex
types could have been made mutable, with all lock calls made via const
functions, but
this does a poor job of documenting the actual semantics. Declaring a mutex member
as mutable clearly documentations the intended semantics.</p>
<h2>7. Why supply <a href="condition.html">condition variables</a> rather than <a href="rationale.html#Events">
event variables</a>?</h2>
<p>Condition variables result in user code much less prone to <a href="definitions.html#Race condition">race
conditions</a> than event variables. See <a href="rationale.html#Events">Rationale</a>
for analysis. Also see <a href="bibliography.html#Hoare-74">[Hoare74]</a>
and <a href="bibliography.html#Schmidt-00">[Schmidt
00]</a>.</p>
<h2>8. Why isn't thread cancellation or termination provided?</h2>
<p>There's a valid need for thread termination, so at some point Boost.Threads
probably will include it, but only after we can find a truly safe (and portable)
mechanism for this concept.</p>
<h2>9. Is it safe for threads to share automatic storage duration (stack)
objects via pointers or references?</h2>
<p>Only if you can guarantee that the lifetime of the stack object will not end
while other threads might still access the object. Thus the safest practice is
to avoid sharing stack objects, particularly in designs where threads are
created and destroyed dynamically. Restrict sharing of stack objects to simple
designs with very clear and unchanging function and thread lifetimes. (Suggested
by Darryl Green).</p>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,87 +1,12 @@
<!-- Copyright (c) 2002-2003 Beman Dawes, William E. Kempf.
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<title>Boost.Threads, Index</title>
<meta http-equiv="refresh" content="0; URL=../../../doc/html/thread.html">
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Documentation Map</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<ul>
<li><a href="overview.html">Overview</a></li>
<li>Class <a href="semaphore.html">semaphore</a></li>
<li><a href="mutex_concept.html">Mutex Concepts</a></li>
<ul>
<li><a href="mutex_concept.html#Mutex">Mutex</a></li>
<li><a href="mutex_concept.html#TryMutex">TryMutex</a></li>
<li><a href="mutex_concept.html#TimedMutex">TimedMutex</a></li>
</ul>
<li>Mutex Classes</li>
<ul>
<li><a href="mutex.html">mutex / try_mutex / timed_mutex</a></li>
<li><a href="recursive_mutex.html">recursive_mutex / recursive_try_mutex / recursive_timed_mutex</a></li>
</ul>
<li><a href="lock_concept.html">Lock Concepts</a></li>
<ul>
<li><a href="lock_concept.html#Lock">Lock</a></li>
<li><a href="lock_concept.html#ScopedLock">ScopedLock</a></li>
<li><a href="lock_concept.html#ScopedTryLock">ScopedTryLock</a></li>
<li><a href="lock_concept.html#ScopedTimedLock">ScopedTimedLock</a></li>
</ul>
<li>Lock Classes</li>
<ul>
<li><a href="scoped_lock.html">scoped_lock</a></li>
<li><a href="scoped_try_lock.html">scoped_try_lock</a></li>
<li><a href="scoped_timed_lock.html">scoped_timed_lock</a></li>
</ul>
<li>Class <a href="condition.html">condition</a></li>
<li>Class <a href="thread_specific_ptr.html">thread_specific_ptr</a></li>
<li>Class <a href="thread.html">thread</a></li>
<li>Class <a href="thread_group.html">thread_group</a></li>
<li>Class <a href="xtime.html">xtime</a></li>
<li>Class <a href="lock_error.html">lock_error</a></li>
<li>Class <a href="thread_resource_error.html">thread_resource_error</a></li>
<li>Routine <a href="call_once.html">call_once</a></li>
<li><a href="config.html">Configuration Information</a></li>
<li><a href="introduction.html">Introduction to design</a></li>
<li><a href="rationale.html">Rationale for design decisions</a></li>
<li><a href="definitions.html">Definitions</a></li>
<li><a href="faq.html">Frequently Asked Questions</a></li>
<li><a href="bibliography.html">Bibliography</a></li>
<li><a href="acknowledgements.html">Acknowledgements</a></li>
</ul>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p>©<i> Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001</i></p>
<p>Permission to use, copy, modify, distribute and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear
in supporting documentation. William E. Kempf makes no representations
about the suitability of this software for any purpose.
It is provided &quot;as is&quot; without express or implied warranty.</p>
<body>
Automatic redirection failed, please go to <a href="../../../doc/html/thread.html">../../../doc/html/thread.html</a>
</body>
</html>

View File

@@ -1,151 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<title>Boost.Threads, Introduction</title>
</head>
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><IMG height=86 alt="C++ Boost" src="../../../c++boost.gif" width=277></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Introduction</h2>
</td>
</tr>
</table>
<hr>
<h3>Motivation</h3>
<p>With client/server and three-tier architectures becoming common place in today's
world, it's becoming increasingly important for programs to be able to handle parallel
processing. Modern day operating systems usually provide some support for this
through native thread APIs. Unfortunately, writing portable code that makes use
of parallel processing in C++ is made very difficult by a lack of a standard interface
for these native APIs. Further, these APIs are almost universally C APIs and fail to
take advantage of C++'s strengths, or to address C++'s issues.</p>
<p>The <b>Boost.Threads</b> library is an attempt to define a portable interface for writing
parallel processes in C++.</p>
<h3>Goals</h3>
<p>The <b>Boost.Threads</b> library has several goals that should help to set it apart from
other solutions. These goals are listed in order of precedence with full descriptions
below.<p>
<ul>
<li><b>Portability</b>
<p><b>Boost.Threads</b> was designed to be highly portable. The goal is for the
interface to be easily implemented on any platform that supports threads,
and possibly even on platforms without native thread support.</p>
<li><b>Safety</b>
<p><b>Boost.Threads</b> was designed to be as safe as possible. Writing
<a href="definitions.html#Thread-safe">thread-safe</a>
code is very difficult and successful libraries must strive to insulate
the programmer from dangerous constructs as much as possible. This is accomplished
in several ways:</p>
<ul>
<li><p align="left">C++ language features are used make correct usage easy (if possible,
the default) and error-prone impossible or at least more difficult.
For example, see the <a href="mutex_concept.html">Mutex</a> and <a href="lock_concept.html">Lock</a>
designs, and how note how they interact.</p></li>
<li>
<p align="left">Certain traditional concurrent programming features
are considered so error-prone that they are not provided at all. For
example, see the <a href="rationale.html#Events">Events Not Provided</a>
rationale.</p>
</li>
<li>
<p align="left">Dangerous features, or features which may be misused,
are identified as such in the documentation to make users aware of
potential pitfalls. For example, see <a href="semaphore.html#Danger">Semaphore</a>.</p>
</li>
</ul>
<li><b>Flexibility</b>
<p><b>Boost.Threads</b> was designed to be flexible. This goal is often at odds
with <i>safety</i>. When functionality might be compromised by the desire
to keep the interface safe, <b>Boost.Threads</b> has been designed to provide
the functionality, but to make it's use prohibitive for general use.</p>
<li><b>Efficiency</b>
<p><b>Boost.Threads</b> was designed to be as efficient as possible. When building
a library on top of another library there is always a danger that the result
will be so much slower than the "native" API that programmers are inclined
to ignore the higher level API. <b>Boost.Threads</b> was designed to minimize the
chances of this occurring. The interfaces have been crafted to allow an
implementation the greatest chance of being as efficient as possible. This
goal is often at odds with the goal for <i>safety</i>. Every effort was made to
ensure efficient implementations, but when in conflict <i>safety</i> has always taken
precedence.</p>
</li>
</ul>
<h3>Iterative Phases</h3>
<p>Another goal of <b>Boost.Threads</b> was to take a dynamic, iterative
approach in its development. The computing industry is still exploring the concepts of parallel programming.
Most thread libraries supply only simple primitive concepts for thread synchronization.
These concepts are very simple, but they are very difficult to use safely or to provide
formal proofs for constructs built on top of them. Until recently, these primitives
were "state of the art" and the only concepts available to programmers. Recently
there has been a lot of research in other concepts, such as in "Communicating Sequential
Processes." <b>Boost.Threads</b> was designed in iterative steps, providing the building
blocks necessary for the next step, and giving the researcher the tools necessary to
explore new concepts in a portable manner.</p>
<p>Given the goal of following a dynamic, iterative approach <b>Boost.Threads</b> shall go through
several growth cycles. Each phase in its development shall be roughly documented here.</p>
<h4>Phase 1, Synchronization Primitives</h4>
<p>Boost is all about providing high quality libraries with implementations for many platforms.
Unfortunately, there's a big problem faced by developers wishing to supply such high quality
libraries, namely thread-safety. The C++ standard doesn't address threads at all, but real
world programs often make use of native threading support. A portable library that doesn't
address the issue of thread-safety is there for not much help to a programmer who wants to
use the library in his multi-threaded application. So there's a very great need for portable
primitives that will allow the library developer to create <a href="definitions.html#Thread-safe">thread-safe</a>
implementations. This
need far out weighs the need for portable methods to create and manage threads.</p>
<p>Because of this need, the first phase of <b>Boost.Threads</b> focuses solely on providing
portable primitive concepts for thread synchronization. Types provided in this phase include
the <A href="semaphore.html">semaphore</a>, <A href="mutex.html">mutex/try_mutex/timed_mutex</a>,
<A href="recursive_mutex.html">recursive_mutex/recursive_try_mutex/recursive_timed_mutex</a>,
<A href="scoped_lock.html">scoped_lock</a>, <A href="scoped_try_lock.html">scoped_try_lock</a>,
<A href="scoped_timed_lock.html">scoped_timed_lock</a> and <A href="lock_error.html">lock_error</a>.
These are considered the "core" synchronization primitives, though there are others that will
be added in later phases.</p>
<h4>Phase 2, Thread Management and Thread Specific Storage</h4>
<p>This phase addresses the creation and management of threads and provides a mechanism for
thread specific storage (data associated with a thread instance). Thread management is a tricky
issue in C++, so this phase addresses only the basic needs of multi-threaded program. Later
phases are likely to add additional functionality in this area. This phase of <b>Boost.Threads</b>
adds the <A href="thread.html">thread</a> and
<A href="thread_specific_ptr.html">thread_specific_ptr</a> types. With these additions
the <b>Boost.Threads</b> library can be considered minimal but complete.</p>
<h4>The Next Phase</h4>
<p>The next phase will address more advanced synchronization concepts, such as read/write mutexes
and barriers.</p>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <A href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,242 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<title>Boost.Threads, Lock Concept</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Lock Concepts</h2>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br>
<a href="#Requirements">Concept Requirements</a><br>
<a href="#Lock">Lock Concept</a><br>
<a href="#ScopedLock">ScopedLock Concept</a><br>
<a href="#ScopedTryLock">ScopedTryLock Concept</a><br>
<a href="#ScopedTimedLock">ScopedTimedLock Concept</a><br>
<a href="#Models">Models</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The lock concepts provide exception safe means for locking and unlocking a
<a href="mutex_concept.html">mutex model</a>. In other words they are an
implementation of the <i>Scoped Locking</i>
<a href="bibliography.html#Schmidt 00">[Schmidt 00]</a> pattern. The
<a href="#ScopedLock">ScopedLock</a> concept, with
<a href="#ScopedTryLock">ScopedTryLock</a> and
<a href="#ScopedTimedLock">ScopedTimedLock</a> refinements, formalize the
requirements.</p>
<p>Lock models are constructed with a reference to a
<a href="mutex_concept.html">mutex model</a> and typically acquire ownership of the
<a href="mutex_concept.html">mutex model</a> by setting its state to locked. They also
ensure ownership is relinquished in the destructor. Lock models also expose functions
to query the lock status and to manually lock and unlock the
<a href="mutex_concept.html">mutex model</a>.</p>
<p>Instances of lock models are meant to be short lived, expected to be used at block
scope only. The lock models are not
<a href="definitions.html#Thread-safe">thread-safe</a>. Lock models must maintain state
to indicate whether or not they've been locked and this state is not protected by any
synchronization concepts. For this reason an instance of a lock model should never be
shared between multiple threads.</p>
<h2>Concept <a name="Requirements">Requirements</a></h2>
<p>[For documentation purposes, portions of the concept requirements are
repeated in the documentation for specific lock classes. Those copies need
to be kept in sync with the requirements here.]</p>
<h3><a name="Lock">Lock</a> Concept</h3>
<p>For a <a href="#ScopedLock"> ScopedLock</a>,
<a href="#ScopedTryLock">ScopedTryLock</a>, or
<a href="#ScopedTimedLock">ScopedTimedLock</a> type <code>L</code> and an object
<code>lk</code> and const object <code>clk</code> of that type, the following expressions
must be well-formed and have the indicated effects.</p>
<p>The Lock concept is used as a base for the <a href="#ScopedLock">ScopedLock</a>,
<a href="#ScopedTryLock">ScopedTryLock</a>, and
<a href="#ScopedTimedLock">ScopedTimedLock</a> refinements. The associated mutex type
is as specified for each of those refinements respectively.</p>
<table border="1" cellpadding="5">
<tr>
<td><b>Expression</b></td>
<td><b>Effects</b></td>
</tr>
<tr>
<td valign="top"><code>(&amp;lk)-&gt;~L();</code></td>
<td><code>if (locked()) unlock();</code></td>
</tr>
<tr>
<td valign="top"><code>(&amp;clk)-&gt;operator const void*()</code></td>
<td>Returns type void*, non-zero if if the associated mutex has been locked
by <code>clk</code>, otherwise 0.</td>
</tr>
<tr>
<td valign="top"><code>clk.locked()</code></td>
<td>Returns a <code>bool</code>, <code>(&amp;clk)-&gt;operator const void*() != 0</code></td>
</tr>
<tr>
<td valign="top"><code>lk.lock()</code></td>
<td>Throws lock_error if locked(). If the associated mutex is already locked by some other
thread, places the current thread in the
<a href="definitions.html#State">Blocked</a> state until the associated mutex is
unlocked, after which the current thread is placed in the
<a href="definitions.html#State">Ready</a> state, eventually to be returned to the
<a href="definitions.html#State">Running</a> state.<br>
Postcondition: locked()</td>
</tr>
<tr>
<td valign="top"><code>lk.unlock()</code></td>
<td>If !locked(), throws lock_error, otherwise unlocks the associated mutex.<br>
Postcondition: !locked()</td>
</tr>
</table>
<h3><a name="ScopedLock">ScopedLock</a> Concept</h3>
<p>A ScopedLock must meet the <a href="#Lock">Lock</a> requirements. For a ScopedLock
type <code>L</code> and an object <code>lk</code> of that type,
and an object <code>m</code> of a type meeting the
<a href="mutex_concept.html#Mutex">Mutex</a> requirements, and an object <code>b</code>
of type <code>bool</code>, the following expressions must be well-formed and have the
indicated effects.</p>
<table border="1" cellpadding="5">
<tr>
<td><b>Expression</b></td>
<td><b>Effects</b></td>
</tr>
<tr>
<td valign="top"><code>L lk(m);</code></td>
<td>Constructs an object <code>lk</code>, and associates mutex <code>m</code> with
it, then calls <code>lock()</code></td>
</tr>
<tr>
<td valign="top"><code>L lk(m,b);</code></td>
<td>Constructs an object <code>lk</code>, and associates mutex <code>m</code> with
it, then if <code>b</code>, calls <code>lock()</code></td>
</tr>
</table>
<h3><a name="ScopedTryLock">ScopedTryLock</a> Concept</h3>
<p>A ScopedTryLock must meet the <a href="#Lock">Lock</a> requirements. For a
ScopedTryLock type <code>L</code> and an object <code>lk</code> of that type,
and an object <code>m</code> of a type meeting the
<a href="mutex_concept.html#TryMutex">TryMutex</a> requirements, and an object
<code>b</code> of type <code>bool</code>, the following expressions must be well-formed
and have the indicated effects.</p>
<table border="1" cellpadding="5">
<tr>
<td><b>Expression</b></td>
<td><b>Effects</b></td>
</tr>
<tr>
<td valign="top"><code>L lk(m);</code></td>
<td>Constructs an object <code>lk</code>, and associates mutex <code>m</code> with
it, then calls <code>try_lock()</code></td>
</tr>
<tr>
<td valign="top"><code>L lk(m,b);</code></td>
<td>Constructs an object <code>lk</code>, and associates mutex <code>m</code> with
it, then if <code>b</code>, calls <code>lock()</code></td>
</tr>
<tr>
<td valign="top"><code>lk.try_lock()</code></td>
<td>If locked(), throws <code>lock_error</code>. Makes a non-blocking attempt to
lock the associated mutex, returning <code>true</code> if the lock attempt is
successful, otherwise <code>false</code>.</td>
</tr>
</table>
<h3><a name="ScopedTimedLock">ScopedTimedLock</a> Concept</h3>
<p>A ScopedTimedLock must meet the <a href="#Lock">Lock</a> requirements. For a
ScopedTimedLock type <code>L</code> and an object <code>lk</code> of that type,
and an object <code>m</code> of a type meeting the
<a href="mutex_concept.html#TimedMutex">TimedMutex</a> requirements, and an object
<code>b</code> of type <code>bool</code>, and an object <code>t</code> of type
<code><a href="xtime.html">xtime</a></code>, the following expressions must be well-formed and have the indicated
effects.</p>
<table border="1" cellpadding="5">
<tr>
<td><b>Expression</b></td>
<td><b>Effects</b></td>
</tr>
<tr>
<td valign="top"><code>L lk(m,t);</code></td>
<td>Constructs an object <code>lk</code>, and associates mutex <code>m</code> with
it, then calls <code>timed_lock(t)</code></td>
</tr>
<tr>
<td valign="top"><code>L lk(m,b);</code></td>
<td>Constructs an object <code>lk</code>, and associates mutex <code>m</code> with
it, then if <code>b</code>, calls <code>lock()</code></td>
</tr>
<tr>
<td valign="top"><code>lk.timed_lock(t)</code></td>
<td>If locked(), throws lock_error. Makes a blocking attempt to lock the
associated mutex, and returns <code>true</code> if successful within the specified
time <code>t</code>, otherwise <code>false</code>.</td>
</tr>
</table>
<h2><a name="Models">Models</a></h2>
<p><b>Boost.Threads</b> currently supplies three classes which model lock concepts.</p>
<p>These classes are normally accessed via typedefs of the same name supplied by
a <a href="mutex_concept.html">mutex model</a>.</p>
<table border="1" cellpadding="5">
<tr>
<td><b>Concept</b></td>
<td><b>Refines</b></td>
<td><b>Classes Modeling the Concept</b></td>
</tr>
<tr>
<td><a href="#ScopedLock">ScopedLock</a></td>
<td>&nbsp;</td>
<td><a href="scoped_lock.html">scoped_lock</a></td>
</tr>
<tr>
<td><a href="#ScopedTryLock">ScopedTryLock</a></td>
<td><a href="#ScopedLock">ScopedLock</a></td>
<td><a href="scoped_try_lock.html">scoped_try_lock</a> </td>
</tr>
<tr>
<td><a href="#ScopedTimedLock">ScopedTimedLock</a></td>
<td><a href="#ScopedLock">ScopedLock</a></td>
<td><a href="scoped_timed_lock.html">scoped_timed_lock</a></td>
</tr>
</table>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,111 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost.Threads, lock_error</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">lock_error</h2>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br>
<a href="#Header">Header</a><br>
<a href="#Synopsis">Synopsis</a><br>
<a href="#Members">Members</a><br>
<a href="#Example">Example</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <tt>lock_error</tt> class defines an exception type thrown to indicate a
locking related error has been detected. Examples of such errors include a lock
operation which can be determined to result in a deadlock, or unlock operations
attempted by a thread that does not own the lock.</p>
<h2><a name="Header">Header</a></h2>
<pre>
#include <a href="../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
</pre>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>
namespace boost
class lock_error : public std::runtime_error
{
public:
lock_error();
};
}
</pre>
<h2><a name="Members">Members</a></h2>
<hr>
<h3>Constructor</h3>
<pre>
lock_error();
</pre>
<p>Constructs a <tt>lock_error</tt> object.</p>
<hr>
<h2><a name="Example">Example</a> Usage</h2>
<pre>
#include <a href="../../../boost/thread/mutex.hpp">&lt;boost/thread/mutex.hpp&gt;</a>
#include <a href="../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
#include &lt;iostream&gt;
int main(int, char*[])
{
boost::mutex mutex;
boost::mutex::scoped_lock scoped_lock(mutex);
try
{
boost::mutex::scoped_lock deadlock(mutex);
std::cout &lt;&lt; &quot;lock succeeded&quot; &lt;&lt; std::endl;
}
catch (boost::lock_error&amp; err)
{
std::cout &lt;&lt; err.what() &lt;&lt; &quot; - deadlock occurred.&quot; &lt;&lt; std::endl;
}
return 0;
}
</pre>
<p>The output is:</p>
<pre>
thread lock error - deadlock occurred.
</pre>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,319 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost.Threads, mutex</title>
</head>
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><IMG alt="C++ Boost" src="../../../c++boost.gif" width="277" height="86"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">mutex<br>
try_mutex<br>
timed_mutex</h2>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br>
<a href="#Header">Header</a><br>
<a href="#mutex Synopsis">Class mutex Synopsis</a><br>
<a href="#mutex Members">Class mutex Members</a><br>
<a href="#try_mutex Synopsis">Class try_mutex Synopsis</a><br>
<a href="#try_mutex Members">Class try_mutex Members</a><br>
<a href="#timed_mutex Synopsis">Class timed_mutex Synopsis</a><br>
<a href="#timed_mutex Members">Class timed_mutex Members</a><br>
<a href="#Example">Example</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <tt><a href="#mutex Synopsis">mutex</a></tt>, <tt><a href="#try_mutex Synopsis">try_mutex</a></tt> and <tt><a href="#timed_mutex Synopsis">timed_mutex</a></tt> classes define full featured
models of the <a href="mutex_concept.html#Mutex">Mutex</a>, <a href="mutex_concept.html#TryMutex">TryMutex</a>,
and <a href="mutex_concept.html#TimedMutex">TimedMutex</a> concepts. These types should be used to
non-recursively synchronize access to
shared resources. For recursive locking mechanics, see <a href="recursive_mutex.html">recursive
mutexes</a>.</p>
<p>Each class supplies one or more typedefs for lock types which model matching
lock concepts. For the best possible performance you should use the mutex class that supports
the minimum set of lock
types that you need.</p>
<table border="1" cellpadding="5">
<tr>
<td><b>Mutex Class</b></td>
<td><b>Lock name</b></td>
<td><b>Implementation defined Lock Type</b></td>
<td><b>&nbsp;Lock Concept</b></td>
</tr>
<tr>
<td valign="top"><a href="#mutex Synopsis"><code>mutex</code></a></td>
<td valign="middle"><code>scoped_lock</code></td>
<td valign="middle"><code><a href="scoped_lock.html">boost::</a></code><a href="scoped_lock.html"><code>detail::thread::scoped_lock&lt;mutex&gt;</code></a></td>
<td valign="middle"><a href="lock_concept.html#ScopedLock">ScopedLock</a></td>
</tr>
<tr>
<td valign="top"><tt><a href="#try_mutex Synopsis">try_mutex</a></tt> </td>
<td valign="middle"><code>scoped_lock<br>
scoped_try_lock</code></td>
<td valign="middle"><code><a href="scoped_lock.html">boost::</a></code><a href="scoped_lock.html"><code>detail::thread::scoped_lock&lt;try_mutex&gt;<br>
</code></a><code><a href="scoped_try_lock.html">boost::detail::thread::scoped_try_lock&lt;try_mutex&gt;</a></code></td>
<td valign="middle"><a href="lock_concept.html#ScopedLock">ScopedLock</a><br>
<a href="lock_concept.html#ScopedTryLock">ScopedTryLock</a></td>
</tr>
<tr>
<td valign="top"><code><a href="#timed_mutex Synopsis">timed_mutex</a></code> </td>
<td valign="middle"><code>scoped_lock<br>
scoped_try_lock<br>
scoped_timed_lock</code></td>
<td valign="middle"><code><a href="scoped_lock.html">boost::</a></code><a href="scoped_lock.html"><code>detail::thread::scoped_lock&lt;timed_mutex&gt;</code></a><br>
<code><a href="scoped_try_lock.html">boost::</a></code><a href="scoped_try_lock.html"><code>detail::thread::scoped_try_lock&lt;timed_mutex&gt;</code></a><br>
<code><a href="scoped_timed_lock.html">boost::</a></code><a href="scoped_timed_lock.html"><code>detail::thread::scoped_timed_lock&lt;timed_mutex&gt;</code></a></td>
<td valign="middle"><a href="lock_concept.html#ScopedLock">ScopedLock</a><br>
<a href="lock_concept.html#ScopedTryLock">ScopedTryLock</a><br>
<a href="lock_concept.html#ScopedTimedLock">ScopedTimedLock</a></td>
</tr>
</table>
<p>The <tt>mutex</tt>, <tt>try_mutex</tt> and <tt>timed_mutex</tt> classes use an <tt>Unspecified</tt>
<A href="mutex_concept.html#LockingStrategies">locking strategy</a>, so attempts to recursively lock
them or attempts to unlock them by threads that don't own a lock on them result in <b>undefined behavior</b>.
This strategy allows implementations to be as efficient as possible on any given platform. It is, however,
recommended that implementations include debugging support to detect misuse when <tt>NDEBUG</tt> is
not defined.</p>
<p>Like all the <b>Boost.Threads</b> <A href="mutex_concept.html">mutex models</a>, the <tt>mutex</tt>,
<tt>try_mutex</tt> and <tt>timed_mutex</tt> leave the
<A href="mutex_concept.html#SchedulingPolicies">scheduling policy</a> as <tt>Unspecified</tt>.
Programmers should assume that threads waiting for a lock on objects of these types
acquire
the lock in a random order, even though the specific behavior for a given platform may be different.</p>
<h2><a name="Header">Header</a></h2>
<pre>
#include <a href="../../../boost/thread/mutex.hpp">&lt;boost/thread/mutex.hpp&gt;</a>
</pre>
<h2>Class <a name="mutex Synopsis"> mutex Synopsis</a></h2>
<pre>
namespace boost
{
class mutex : private <a href="../../utility/utility.htm">boost::noncopyable</a> // Exposition only.
// Class mutex meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
{
public:
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_lock;
mutex();
~mutex();
};
}
</pre>
<h2>
Class <a name="mutex Members">mutex Members</a>
</h2>
<hr>
<h3>Constructor</h3>
<pre>
mutex();
</pre>
<p><b>Postconditions: </b><code>*this</code> is in the unlocked state.</p>
<hr>
<h3>Destructor</h3>
<pre>
~mutex();
</pre>
<p><b>Requires:</b> <code>*this</code> is in the unlocked state.</p>
<p><b>Effects:</b> Destroys <code>*this</code>.</p>
<p><b>Dangers:</b> Destruction of a locked mutex is a serious programming error
resulting in undefined behavior such as a program crash.</p>
<hr>
<h2>
Class <a name="try_mutex Synopsis">try_mutex Synopsis</a>
</h2>
<pre>
namespace boost
{
class try_mutex : private boost::noncopyable // Exposition only.
// Class try_mutex meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
{
public:
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_lock;
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_try_lock;
try_mutex();
~try_mutex();
};
}
</pre>
<h2>Class <a name="try_mutex Members">try_mutex Members</a></h2>
<hr>
<h3>Constructor</h3>
<pre>
try_mutex();
</pre>
<p><b>Postconditions: </b><code>*this</code> is in the unlocked state.</p>
<hr>
<h3>Destructor</h3>
<pre>
~try_mutex();
</pre>
<p><b>Requires:</b> <code>*this</code> is in the unlocked state.</p>
<p><b>Effects:</b> Destroys <code>*this</code>.</p>
<p><b>Dangers:</b> Destruction of a locked mutex is a serious programming error
resulting in undefined behavior such as a program crash.</p>
<hr>
<h2>
Class <a name="timed_mutex Synopsis">timed_mutex Synopsis</a>
</h2>
<pre>
namespace boost
{
class timed_mutex : private boost::noncopyable // Exposition only.
// Class timed_mutex meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
{
public:
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_lock;
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_try_lock;
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_timed_lock;
timed_mutex();
~timed_mutex();
};
}
</pre>
<h2>Class <a name="timed_mutex Members">timed_mutex Members</a></h2>
<hr>
<h3>Constructor</h3>
<pre>
timed_mutex();
</pre>
<p><b>Postconditions: </b><code>*this</code> is in the unlocked state.</p>
<hr>
<h3>Destructor</h3>
<pre>
~timed_mutex();
</pre>
<p><b>Requires:</b> <code>*this</code> is in the unlocked state.</p>
<p><b>Effects:</b> Destroys <code>*this</code>.</p>
<p><b>Dangers:</b> Destruction of a locked mutex is a serious programming error
resulting in undefined behavior such as a program crash.</p>
<hr>
<h2><a name="Example">Example</a> Usage</h2>
<pre>
#include <a href="../../../boost/thread/mutex.hpp">&lt;boost/thread/mutex.hpp&gt;</a>
#include <a href="../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
#include &lt;iostream&gt;
boost::mutex io_mutex; // The iostreams are not guaranteed to be <a href="definitions.html#Thread-safe">thread-safe</a>!
class counter
{
public:
counter() : count(0) { }
int increment() {
boost::mutex::scoped_lock scoped_lock(mutex);
return ++count;
}
private:
boost::mutex mutex;
int count;
};
counter c;
void change_count(void*)
{
int i = c.increment();
boost::mutex::scoped_lock scoped_lock(io_mutex);
std::cout &lt;&lt; &quot;count == &quot; &lt;&lt; i &lt;&lt; std::endl;
}
int main(int, char*[])
{
const int num_threads = 4;
boost::thread_group thrds;
for (int i=0; i &lt; num_threads; ++i)
thrds.create_thread(&amp;change_count, 0);
thrds.join_all();
return 0;
}
</pre>
<p>The output is:</p>
<pre>
count == 1
count == 2
count == 3
count == 4
</pre>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <A href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,275 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<title>Boost.Threads, Mutex Concept</title>
</head>
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><IMG height=86 alt="C++ Boost" src="../../../c++boost.gif" width=277></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Mutex Concepts</h2>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br>
<a href="#LockingStrategies">Locking Strategies</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Recursive">Recursive</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#CheckedStrategy">Checked</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#UncheckedStrategy">Unchecked</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#UnspecifiedStrategy">Unspecified</a><br>
<a href="#SchedulingPolicies">Scheduling Policies</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#FIFO">FIFO</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Priority Driven">Priority Driven</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#UndefinedScheduling">Undefined</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#UnspecifiedScheduling">Unspecified</a><br>
<a href="#Requirements">Concept Requirements</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Mutex">Mutex Concept</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#TryMutex">TryMutex Concept</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#TimedMutex">TimedMutex Concept</a><br>
<a href="#Models">Models</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>A mutex (short for mutual-exclusion) concept serializes access to
a resource shared between multiple threads. The <a href="#Mutex">Mutex</a>
concept, with <a href="#TryMutex">TryMutex</a> and <a href="#TimedMutex">TimedMutex</a>
refinements, formalize the requirements. A model that implements Mutex and its
refinements has two states: <b> locked</b> and <b>unlocked</b>. Before using a
shared resource, a thread locks a Boost.Threads mutex model object,
insuring <a href="definitions.html#Thread-safe">thread-safe</a> access to the shared
resource. When use of the shared resource is complete, the thread unlocks the mutex
model object, allowing another thread to acquire the lock and use the shared resource.</p>
<p>Traditional C thread APIs, like Pthreads or the Windows thread APIs, expose
functions to lock and unlock a mutex model. This is dangerous since it's easy to forget
to unlock a locked mutex. When the flow of control is complex, with multiple return
points, the likelihood of forgetting to unlock a mutex model would become even greater.
When exceptions are thrown, it becomes nearly impossible to ensure that the mutex is
unlocked properly when using these traditional API's. The result is
<a href="definitions.html#Deadlock">deadlock</a>.</p>
<p>Many C++ threading libraries use a pattern known as <i>Scoped Locking</i>
<a href="bibliography.html#Schmidt 00">[Schmidt 00]</a> to free the programmer from the
need to explicitly lock and unlock mutexes. With this pattern, a
<A href="lock_concept.html">lock concept</A> is employed where the lock model's
constructor locks the associated mutex model and the destructor automatically does the
unlocking. The <b>Boost.Threads</b> library takes this pattern to the extreme in that
lock concepts are the only way to lock and unlock a mutex model: lock and unlock
functions are not exposed by any <b>Boost.Threads </b>mutex models. This helps to
ensure safe usage patterns, especially when code throws exceptions.</p>
<h2><a name="LockingStrategies">Locking Strategies</a></h2>
<p>Every mutex model follows one of several locking strategies. These strategies
define the semantics for the locking operation when the calling thread already
owns a lock on the mutex model.</p>
<h3><a name="Recursive">Recursive</a></h3>
<p>With a recursive locking strategy when a thread attempts to acquire a lock on
the mutex model for which it already owns a lock, the operation is successful.
Note the distinction between a thread, which may have multiple locks outstanding
on a recursive mutex, and a lock object, which even for a recursive mutex cannot
have its lock() function called multiple times without first calling unlock().</p>
<p>Internally a lock count is maintained and the owning thread must unlock the
mutex model the same number of times that it's locked it before the mutex model's
state returns to unlocked. Since mutex models in <b>Boost.Threads</b> expose
locking functionality only through lock concepts, a thread will always unlock a mutex
model the same number of times that it locked it. This helps to eliminate a whole set
of errors typically found in traditional C style thread APIs.</p>
<p>Classes <A href="recursive_mutex.html">recursive_mutex</A>,
<A href="recursive_mutex.html">recursive_try_mutex</A> and
<A href="recursive_mutex.html">recursive_timed_mutex</A> use this locking strategy.</p>
<h3><a name="CheckedStrategy">Checked</a></h3>
<p>With a checked locking strategy when a thread attempts to acquire a lock on
the mutex model for which the thread already owns a lock, the operation will fail with
some sort of error indication. Further, attempts by a thread to unlock a mutex
that was not locked by the thread will also return some sort of error indication.
In <b>Boost.Threads</b>, an exception of type <A href="lock_error.html">lock_error</A>
would be thrown in these cases.</p>
<p><b>Boost.Threads</b> does not currently provide any mutex models that use this
strategy.</p>
<h3><a name="UncheckedStrategy">Unchecked</a></h3>
<p>With an unchecked locking strategy when a thread attempts to acquire a lock
on the mutex model for which the thread already owns a lock the operation will
<a href="definitions.html#Deadlock">deadlock</a>. In general this locking strategy is
less safe than a checked or recursive strategy, but it's also a faster strategy and so
is employed by many libraries.</p>
<p><b>Boost.Threads</b> does not currently provide any mutex models that use this
strategy.</p>
<h3><a name="UnspecifiedStrategy">Unspecified</a></h3>
<p>With an unspecified locking strategy, when a thread attempts to acquire a lock
on a mutex model for which the thread already owns a lock the operation results in
<b>undefined behavior</b>. When a mutex model has an unspecified locking strategy the
programmer must assume that the mutex model instead uses an unchecked strategy.</p>
<p>In general a mutex model with an unspecified locking strategy is unsafe, and it
requires programmer discipline to use the mutex model properly. However, this strategy
allows an implementation to be as fast as possible with no restrictions on its
implementation. This is especially true for portable implementations that wrap the
native threading support of a platform. For this reason, the classes
<A href="mutex.html">mutex</A>, <A href="mutex.html">try_mutex</A> and
<A href="mutex.html">timed_mutex</A> use this locking strategy despite the lack of
safety.</p>
<h2><a name="SchedulingPolicies">Scheduling Policies</a></h2>
<p>Every mutex model follows one of several scheduling policies. These policies
define the semantics when the mutex model is unlocked and there is more than one
thread waiting to acquire a lock. In other words, the policy defines which waiting
thread shall acquire the lock.</p>
<h3><a name="FIFO">FIFO</a></h3>
<p>With a FIFO scheduling policy, threads waiting for the lock will acquire it in
a first come first serve order (or First In First Out). This can help prevent a
high priority thread from starving lower priority threads that are also waiting
on the mutex lock.</p>
<h3><a name="Priority Driven">Priority Driven</a></h3>
<p>With a Priority Driven scheduling policy, the thread with the highest priority
acquires the lock. Note that this means that low-priority threads may never acquire
the lock if the mutex model has high contention and there is always at least one
high-priority thread waiting. This is known as thread starvation. When multiple threads
of the same priority are waiting on the mutex lock one of the other scheduling
priorities will determine which thread shall acquire the lock.</p>
<h3><a name="UndefinedScheduling">Undefined</a></h3>
<p>Threads acquire the lock in no particular order. Users should assume that
low-priority threads may wait indefinitely, and that threads of the same
priority acquire the lock in essentially random order.</p>
<h3><a name="UnspecifiedScheduling">Unspecified</a></h3>
<p>The mutex model does not specify which scheduling policy is used. The programmer
must assume that an undefined scheduling policy is used. In order to ensure portability,
all <b>Boost.Threads</b> mutex models use an unspecified scheduling policy.</p>
<h2>Concept <a name="Requirements">Requirements</a></h2>
<h3><a name="Mutex">Mutex</a> Concept</h3>
<p>A Mutex object has two states: locked and unlocked. Mutex object state can only be
determined by an object meeting the <a href="lock_concept.html#ScopedLock">ScopedLock</a>
requirements and constructed for the Mutex object.</p>
<p>A Mutex is <a href="../../utility/utility.htm#Class noncopyable">noncopyable</a>.</p>
<p>For a Mutex type M and an object m of that type, the following expressions must be
well-formed and have the indicated effects.</p>
<table border="1" cellpadding="5">
<tr>
<td><b>Expression</b></td>
<td><b>Effects</b></td>
</tr>
<tr>
<td><code>M m;</code></td>
<td>Constructs a mutex object m. Post-condition: m is unlocked.</td>
</tr>
<tr>
<td><code>(&amp;m)-&gt;~M();</code></td>
<td>Precondition: m is unlocked. Destroys a mutex object m.</td>
</tr>
<tr>
<td><code>M::scoped_lock</code></td>
<td>A type meeting the <a href="lock_concept.html#ScopedLock">ScopedLock</a>
requirements.</td>
</tr>
</table>
<h3><a name="TryMutex">TryMutex</a> Concept</h3>
<p>A TryMutex must meet the <a href="#Mutex"> Mutex</a> requirements. In addition, for a
TryMutex type M and an object m of that type, the following expressions must be
well-formed and have the indicated effects.</p>
<table border="1" cellpadding="5">
<tr>
<td><b>Expression</b></td>
<td><b>Effects</b></td>
</tr>
<tr>
<td><code>M::scoped_try_lock</code></td>
<td>A type meeting the <a href="lock_concept.html#ScopedTryLock">ScopedTryLock</a>
requirements.</td>
</tr>
</table>
<h3><a name="TimedMutex">TimedMutex</a> Concept</h3>
<p>A TimedMutex must meet the <a href="#TryMutex"> TryMutex</a> requirements. In addition, for a
TimedMutex type M and an object m of that type, the following
expressions must be well-formed and have the indicated effects.</p>
<table border="1" cellpadding="5">
<tr>
<td><b>Expression</b></td>
<td><b>Effects</b></td>
</tr>
<tr>
<td><code>M::scoped_timed_lock</code></td>
<td>A type meeting the <a href="lock_concept.html#ScopedTimedLock">ScopedTimedLock</a>
requirements.</td>
</tr>
</table>
<h2><a name="Models">Models</a></h2>
<p> <b>Boost.Threads</b> currently supplies six classes which model mutex
concepts.</p>
<table border="1" cellpadding="5">
<tr>
<td><b>Concept</b></td>
<td><b>Refines</b></td>
<td><b>Classes Modeling the Concept</b></td>
</tr>
<tr>
<td valign="top"><a href="#Mutex">Mutex</a></td>
<td valign="top">&nbsp;</td>
<td><A href="mutex.html">mutex</A><br>
<A href="recursive_mutex.html">recursive_mutex</A></td>
</tr>
<tr>
<td valign="top"><a href="#TryMutex">TryMutex</a></td>
<td valign="top"><a href="#Mutex">Mutex</a></td>
<td><A href="mutex.html">try_mutex<br>
</A><A href="recursive_mutex.html">recursive_try_mutex</A> </td>
</tr>
<tr>
<td valign="top"><a href="#TimedMutex">TimedMutex</a></td>
<td valign="top"><a href="#TryMutex">TryMutex</a></td>
<td><A href="mutex.html">timed_mutex<br>
</A><A href="recursive_mutex.html">recursive_timed_mutex</A></td>
</tr>
</table>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <A href="mailto:williamkempf@hotmail.com">William E. Kempf</A>
2001 all rights reserved.</i></p>
</body>
</html>

1119
doc/mutex_concepts.qbk Normal file

File diff suppressed because it is too large Load Diff

224
doc/mutexes.qbk Normal file
View File

@@ -0,0 +1,224 @@
[/
(C) Copyright 2007-8 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).
]
[section:mutex_types Mutex Types]
[section:mutex Class `mutex`]
#include <boost/thread/mutex.hpp>
class mutex:
boost::noncopyable
{
public:
mutex();
~mutex();
void lock();
bool try_lock();
void unlock();
typedef platform-specific-type native_handle_type;
native_handle_type native_handle();
typedef unique_lock<mutex> scoped_lock;
typedef unspecified-type scoped_try_lock;
};
__mutex__ implements the __lockable_concept__ to provide an exclusive-ownership mutex. At most one thread can own the lock on a given
instance of __mutex__ at any time. Multiple concurrent calls to __lock_ref__, __try_lock_ref__ and __unlock_ref__ shall be permitted.
[section:nativehandle Member function `native_handle()`]
typedef platform-specific-type native_handle_type;
native_handle_type native_handle();
[variablelist
[[Effects:] [Returns an instance of `native_handle_type` that can be used with platform-specific APIs to manipulate the underlying
implementation. If no such instance exists, `native_handle()` and `native_handle_type` are not present.]]
[[Throws:] [Nothing.]]
]
[endsect]
[endsect]
[section:try_mutex Typedef `try_mutex`]
#include <boost/thread/mutex.hpp>
typedef mutex try_mutex;
__try_mutex__ is a `typedef` to __mutex__, provided for backwards compatibility with previous releases of boost.
[endsect]
[section:timed_mutex Class `timed_mutex`]
#include <boost/thread/mutex.hpp>
class timed_mutex:
boost::noncopyable
{
public:
timed_mutex();
~timed_mutex();
void lock();
void unlock();
bool try_lock();
bool timed_lock(system_time const & abs_time);
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time);
typedef platform-specific-type native_handle_type;
native_handle_type native_handle();
typedef unique_lock<timed_mutex> scoped_timed_lock;
typedef unspecified-type scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
};
__timed_mutex__ implements the __timed_lockable_concept__ to provide an exclusive-ownership mutex. At most one thread can own the
lock on a given instance of __timed_mutex__ at any time. Multiple concurrent calls to __lock_ref__, __try_lock_ref__,
__timed_lock_ref__, __timed_lock_duration_ref__ and __unlock_ref__ shall be permitted.
[section:nativehandle Member function `native_handle()`]
typedef platform-specific-type native_handle_type;
native_handle_type native_handle();
[variablelist
[[Effects:] [Returns an instance of `native_handle_type` that can be used with platform-specific APIs to manipulate the underlying
implementation. If no such instance exists, `native_handle()` and `native_handle_type` are not present.]]
[[Throws:] [Nothing.]]
]
[endsect]
[endsect]
[section:recursive_mutex Class `recursive_mutex`]
#include <boost/thread/recursive_mutex.hpp>
class recursive_mutex:
boost::noncopyable
{
public:
recursive_mutex();
~recursive_mutex();
void lock();
bool try_lock();
void unlock();
typedef platform-specific-type native_handle_type;
native_handle_type native_handle();
typedef unique_lock<recursive_mutex> scoped_lock;
typedef unspecified-type scoped_try_lock;
};
__recursive_mutex__ implements the __lockable_concept__ to provide an exclusive-ownership recursive mutex. At most one thread can
own the lock on a given instance of __recursive_mutex__ at any time. Multiple concurrent calls to __lock_ref__, __try_lock_ref__ and
__unlock_ref__ shall be permitted. A thread that already has exclusive ownership of a given __recursive_mutex__ instance can call
__lock_ref__ or __try_lock_ref__ to acquire an additional level of ownership of the mutex. __unlock_ref__ must be called once for
each level of ownership acquired by a single thread before ownership can be acquired by another thread.
[section:nativehandle Member function `native_handle()`]
typedef platform-specific-type native_handle_type;
native_handle_type native_handle();
[variablelist
[[Effects:] [Returns an instance of `native_handle_type` that can be used with platform-specific APIs to manipulate the underlying
implementation. If no such instance exists, `native_handle()` and `native_handle_type` are not present.]]
[[Throws:] [Nothing.]]
]
[endsect]
[endsect]
[section:recursive_try_mutex Typedef `recursive_try_mutex`]
#include <boost/thread/recursive_mutex.hpp>
typedef recursive_mutex recursive_try_mutex;
__recursive_try_mutex__ is a `typedef` to __recursive_mutex__, provided for backwards compatibility with previous releases of boost.
[endsect]
[section:recursive_timed_mutex Class `recursive_timed_mutex`]
#include <boost/thread/recursive_mutex.hpp>
class recursive_timed_mutex:
boost::noncopyable
{
public:
recursive_timed_mutex();
~recursive_timed_mutex();
void lock();
bool try_lock();
void unlock();
bool timed_lock(system_time const & abs_time);
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time);
typedef platform-specific-type native_handle_type;
native_handle_type native_handle();
typedef unique_lock<recursive_timed_mutex> scoped_lock;
typedef unspecified-type scoped_try_lock;
typedef scoped_lock scoped_timed_lock;
};
__recursive_timed_mutex__ implements the __timed_lockable_concept__ to provide an exclusive-ownership recursive mutex. At most one
thread can own the lock on a given instance of __recursive_timed_mutex__ at any time. Multiple concurrent calls to __lock_ref__,
__try_lock_ref__, __timed_lock_ref__, __timed_lock_duration_ref__ and __unlock_ref__ shall be permitted. A thread that already has
exclusive ownership of a given __recursive_timed_mutex__ instance can call __lock_ref__, __timed_lock_ref__,
__timed_lock_duration_ref__ or __try_lock_ref__ to acquire an additional level of ownership of the mutex. __unlock_ref__ must be
called once for each level of ownership acquired by a single thread before ownership can be acquired by another thread.
[section:nativehandle Member function `native_handle()`]
typedef platform-specific-type native_handle_type;
native_handle_type native_handle();
[variablelist
[[Effects:] [Returns an instance of `native_handle_type` that can be used with platform-specific APIs to manipulate the underlying
implementation. If no such instance exists, `native_handle()` and `native_handle_type` are not present.]]
[[Throws:] [Nothing.]]
]
[endsect]
[endsect]
[include shared_mutex_ref.qbk]
[endsect]

56
doc/once.qbk Normal file
View File

@@ -0,0 +1,56 @@
[/
(C) Copyright 2007-8 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).
]
[section:once One-time Initialization]
`boost::call_once` provides a mechanism for ensuring that an initialization routine is run exactly once without data races or deadlocks.
[section:once_flag Typedef `once_flag`]
#include <boost/thread/once.hpp>
typedef platform-specific-type once_flag;
#define BOOST_ONCE_INIT platform-specific-initializer
Objects of type `boost::once_flag` shall be initialized with `BOOST_ONCE_INIT`:
boost::once_flag f=BOOST_ONCE_INIT;
[endsect]
[section:call_once Non-member function `call_once`]
#include <boost/thread/once.hpp>
template<typename Callable>
void call_once(once_flag& flag,Callable func);
[variablelist
[[Requires:] [`Callable` is `CopyConstructible`. Copying `func` shall have no side effects, and the effect of calling the copy shall
be equivalent to calling the original. ]]
[[Effects:] [Calls to `call_once` on the same `once_flag` object are serialized. If there has been no prior effective `call_once` on
the same `once_flag` object, the argument `func` (or a copy thereof) is called as-if by invoking `func()`, and the invocation of
`call_once` is effective if and only if `func()` returns without exception. If an exception is thrown, the exception is
propagated to the caller. If there has been a prior effective `call_once` on the same `once_flag` object, the `call_once` returns
without invoking `func`. ]]
[[Synchronization:] [The completion of an effective `call_once` invocation on a `once_flag` object, synchronizes with
all subsequent `call_once` invocations on the same `once_flag` object. ]]
[[Throws:] [`thread_resource_error` when the effects cannot be achieved. or any exception propagated from `func`.]]
]
void call_once(void (*func)(),once_flag& flag);
This second overload is provided for backwards compatibility. The effects of `call_once(func,flag)` shall be the same as those of
`call_once(flag,func)`.
[endsect]
[endsect]

View File

@@ -1,156 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Boost.Threads Overview</title>
</head>
<body>
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><IMG height=86 alt="C++ Boost" src="../../../c++boost.gif" width=277></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Overview</h2>
</td>
</tr>
</table>
<p><a href="#Introduction">Introduction</a><br>
<a href="#Dangers">Dangers</a><br>
<a href="#Library">C++ Standard Library usage</a><br>
<a href="#Common">Common requirements</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>Boost.Threads allows C++ programs to execute as multiple, asynchronous,
independent, threads-of-execution. Each thread has its own machine state
including program instruction counter and registers. Programs which execute as
multiple threads are call multi-threaded programs to distinguish them from
traditional single-threaded programs. <a href="definitions.html">Definitions</a>
gives a more complete description of the multi-threading execution environment.</p>
<p>Multi-threading provides several advantages:</p>
<ul>
<li>Programs which would otherwise block waiting for some external event can
continue to respond if the blocking operation is placed in a separate
thread.&nbsp; Multi-threading is usually an absolute requirement for these
programs.</li>
</ul>
<ul>
<li>Well-designed multi-threaded programs may execute faster than single-threaded
programs, particularly on multi-processor hardware.&nbsp;
Note, however, that poorly-designed multi-threaded programs are often slower
that single-threaded programs.</li>
</ul>
<ul>
<li>Some program designs may be easier to formulate using a multi-threaded
approach.
After all, the real world is asynchronous!&nbsp;</li>
</ul>
<h2><a name="Dangers">Dangers</a></h2>
<p>Beyond the errors which can occur in single-threaded programs, multi-threaded
programs are subject to additional errors:</p>
<ul>
<li><a href="definitions.html#Race condition">Race conditions</a>.
<li><a href="definitions.html#Deadlock">Deadlock</a> (sometimes called
&quot;deadly embrace&quot;)
<li><a href="definitions.html#Priority failure">Priority failures</a>
(priority inversion, infinite overtaking, starvation, etc.)</li>
</ul>
<p>Every multi-threaded program must be designed carefully to avoid race
conditions and deadlock.&nbsp; These aren't rare or exotic failures - they are
virtually guaranteed to occur unless multi-threaded code is designed to avoid
them.&nbsp; Priority failures are somewhat less common, but are none-the-less
serious.</p>
<p>The <a href="introduction.html">Boost.Threads design</a> attempts to minimize
these errors, but they will still occur unless the programmer proactively
designs to avoid them.</p>
<h3>Testing and debugging considerations</h3>
<p>Multi-threaded programs are non-deterministic. In other words, the same
program with the same input data may follow different execution paths each time
it is invoked.&nbsp; That can make testing and debugging a nightmare:</p>
<ul>
<li>Failures are often not repeatable.
<li>Probe effect causes debuggers to produce very different results from
non-debug uses.
<li>Debuggers require special support to show thread state.
<li>Tests on a single processor system may give no indication of serious
errors which would appear on multiprocessor systems, and visa versa. Thus test
cases should include a varying number of processors.&nbsp;</li>
<li>For programs which create a varying number of threads according to
workload, tests which don't span the full range of possibilities may miss
serious errors.</li>
</ul>
<h3>Getting a head start</h3>
<p>Although it might appear that multi-threaded programs are inherently
unreliable, many reliable multi-threaded programs do exist. Multi-threading
techniques are known which lead to reliable programs.</p>
<p>Design patterns for reliable multi-threaded programs, including the important
<i>monitor</i> pattern, are presented in <cite>Pattern-Oriented Software Architecture Volume 2 - Patterns for
Concurrent and Networked Objects</cite> [<a href="bibliography.html#Schmidt-00">Schmidt
00</a>].&nbsp; Many important multi-threading programming considerations
(independent of threading library) are discussed in <cite>Programming with
POSIX Threads</cite> [<a href="bibliography.html#Butenhof-97">Butenhof 97</a>].</p>
<p>Reading and study first yields a head start toward designing reliable
multi-threaded programs.</p>
<h2><a name="Library">C++ Standard Library usage in multi-threaded programs</a></h2>
<h3>Runtime libraries</h3>
<p><b>Warning:</b> Multi-threaded programs such as those using <b>Boost.Threads</b> must link to
<a href="definitions.html#Thread-safe">thread-safe</a> versions of all runtime
libraries used by the program, including the runtime library for the C++
Standard Library. Otherwise <a href="definitions.html#Race condition">race
conditions</a> will occur when multiple threads simultaneously execute runtime
library functions for <i>new</i>, <i>delete</i>, or other language features
which imply shared state.&nbsp;&nbsp;</p>
<h3>Potentially non-thread-safe functions</h3>
<p>Certain C++ Standard Library functions inherited from C are particular
problems because they hold internal state between calls:</p>
<ul>
<li>rand</li>
<li>strtok</li>
<li>asctime</li>
<li>ctime&nbsp;</li>
<li>gmtime</li>
<li>localtime</li>
</ul>
<p>It is possible to write thread-safe implementations of these by using <a href="thread_specific_ptr.html">thread-specific
storage</a>, and several C++ compiler vendors do just that.&nbsp; The technique
is well-know and is explained in [<a href="bibliography.html#Butenhof-97">Buttenhof-97</a>].</p>
<p>But at least one vendor (HP-UX) does not provide thread-safe implementations
of the above functions in their otherwise thread-safe runtime library.&nbsp;
Instead they provide replacement functions with different names and arguments.</p>
<p><b>Recommendation:</b> For the most portable, yet thread-safe code, use Boost
replacements for the problem functions.&nbsp; See the <a href="../../random/index.html">Boost
Random Number Library</a> and <a href="../../tokenizer/index.htm">Boost
Tokenizer Library</a>.</p>
<h2><a name="Common">Common</a> requirements for all Boost.Threads components</h2>
<h3>Exceptions</h3>
<p> <b>Boost.Threads</b> destructors never throw exceptions. Unless otherwise
specified, other <b>Boost.Threads</b>
functions that do not have an exception-specification may throw implementation-defined exceptions.</p>
<p>In particular, <b>Boost.Threads</b> reports failure to allocate storage by throwing an exception of type
std::bad_alloc, or a class derived from std::bad_alloc, failure to obtain
thread resources other than memory by throwing an exception of type <a href="thread_resource_error.html">boost::thread_resource_error</a>,
and certain lock related failures by throwing an exception of type <a href="lock_error.html">boost::lock_error</a></p>
<p><b>Rationale: </b>Follows the C++ Standard Library practice of allowing all
functions except destructors or other specified functions to throw exceptions on
errors.</p>
<h3><a name="NonCopyable">NonCopyable</a> requirement</h3>
<p><b>Boost.Threads</b> classes documented as meeting the NonCopyable requirement disallow copy
construction and copy assignment. For the sake of exposition, the synopsis of
such classes show private derivation from <a href="../../utility/utility.htm">boost::noncopyable</a>.
Users should not depend on this derivation, however, as implementations are free
to meet the NonCopyable requirement in other ways.</p>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p>© Copyright 2001 Beman Dawes</p>
</body>
</html>

30
doc/overview.qbk Normal file
View File

@@ -0,0 +1,30 @@
[/
(C) Copyright 2007-8 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).
]
[section:overview Overview]
__boost_thread__ enables the use of multiple threads of execution with shared data in portable C++ code. It provides classes and
functions for managing the threads themselves, along with others for synchronizing data between the threads or providing separate
copies of data specific to individual threads.
The __boost_thread__ library was originally written and designed by William E. Kempf. This version is a major rewrite designed to
closely follow the proposals presented to the C++ Standards Committee, in particular
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2497.html N2497],
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2320.html N2320],
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2184.html N2184],
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2139.html N2139], and
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2094.html N2094]
In order to use the classes and functions described here, you can
either include the specific headers specified by the descriptions of
each class or function, or include the master thread library header:
#include <boost/thread.hpp>
which includes all the other headers in turn.
[endsect]

View File

@@ -1,431 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<title>Boost.Threads, rationale</title>
</head>
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><IMG height=86 alt="C++ Boost" src="../../../c++boost.gif" width=277></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Rationale</h2>
</td>
</tr>
</table>
<hr>
<p>This page explains the rationale behind various design decisions in the <b> Boost.Threads</b>
library. Having the rationale documented here should explain how we arrived at the current
design as well as prevent future rehashing of discussions and thought processes that have
already occurred. It can also give users a lot of insight into the design process required
for this library.</p>
<h2><a name="library">Rationale for the Creation of Boost.Threads</a></h2>
<p>Processes often have a degree of "potential parallelism" and it can often be more intuitive
to design systems with this in mind. Further, these parallel processes can result in more responsive
programs. The benefits for multi-threaded programming are quite well known to most modern programmers,
yet the C++ language doesn't directly support this concept.</p>
<p>Many platforms support multi-threaded programming despite the fact that the language doesn't support
it. They do this through external libraries, which are, unfortunately, platform specific. POSIX has
tried to address this problem through the standardization of a "pthread" library. However, this
is a standard only on POSIX platforms, so its portability is limited.</p>
<p>Another problem with POSIX and other platform specific thread libraries is that they are
almost universally C based libraries. This leaves several C++ specific issues unresolved, such
as what happens when an exception is thrown in a thread. Further, there are some C++ concepts,
such as destructors, that can make usage much easier than what's available in a C library.</p>
<p>What's truly needed is C++ language support for threads. However, the C++ standards committee needs
existing practice or a good proposal as a starting point for adding this to the standard.</p>
<p>The Boost.Threads library was developed to provide a C++ developer with a portable interface
for writing multi-threaded programs on numerous platforms. There's a hope that the library can
be the basis for a more detailed proposal for the C++ standards committee to consider for inclusion
in the next C++ standard.</p>
<h2><a name="primitives">Rationale for the Low Level Primitives Supported in Boost.Threads</a></h2>
<p>The Boost.Threads library supplies a set of low level primitives for writing multi-threaded
programs, such as semaphores, mutexes and condition variables. In fact, the first release of
Boost.Threads supports only these low level primitives. However, computer
science research has shown
that use of these primitives is difficult since there's no way to mathematically prove that a
usage pattern is correct, meaning it doesn't result in race conditions or deadlocks. There
are several algebras (such as CSP, CCS and Join calculus) that have been developed to help write
provably correct parallel processes. In order to prove the correctness these processes must
be coded using higher level abstractions. So why does Boost.Threads support the lower level
concepts?</p>
<p>The reason is simple: the higher level concepts need to be implemented using at least some
of the lower level concepts. So having portable lower level concepts makes it easier to develop
the higher level concepts and will allow researchers to experiment with various techniques.</p>
<p>Beyond this theoretical application of higher level concepts, however, the fact remains that
many multi-threaded programs are written using only the lower level concepts, so they are
useful in and of themselves, even if it's hard to prove that their usage is correct. Since
many users will be familiar with these lower level concepts but be unfamiliar with any of the
higher level concepts there's also an argument for accessibility.</p>
<h2><a name="lock_objects">Rationale for the Lock Design</a></h2>
<p>Programmers who are used to multi-threaded programming issues will quickly note that the
Boost.Thread's design for mutex lock concepts is not <a href="definitions.html#Thread-safe">thread-safe</a>
(this is clearly documented
as well). At first this may seem like a serious design flaw. Why have a multi-threading primitive
that's not thread-safe itself?</p>
<p>A lock object is not a synchronization primitive. A lock object's sole responsibility is
to ensure that a mutex is both locked and unlocked in a manner that won't result in the common
error of locking a mutex and then forgetting to unlock it. This means that instances of a
lock object are only going to be created, at least in theory, within block scope and won't
be shared between threads. Only the mutex objects will be created outside of block scope and/or
shared between threads. Though it's possible to create a lock object outside of block scope and
to share it between threads to do so would not be a typical usage. Nor are there any cases when
such usage would be required.</p>
<p>Lock objects must maintain some state information. In order to allow a program to determine
if a try_lock or timed_lock was successful the lock object must retain state indicating
the success or failure of the call made in its constructor. If a lock object were to have
such state and remain thread-safe it would need to synchronize access to the state information
which would result in roughly doubling the time of most operations. Worse, since checking
the state can occur only by a call after construction we'd have a race condition if the lock
object were shared between threads.</p>
<p>So, to avoid the overhead of synchronizing access to the state information and to avoid
the race condition the Boost.Threads library simply does nothing to make lock objects thread-safe. Instead, sharing a lock object between threads results in undefined behavior. Since the
only proper usage of lock objects is within block scope this isn't a problem, and so long
as the lock object is properly used there's no danger of any multi-threading issues.</p>
<h2><a name="thread">Rationale for Non-copyable Thread Type</a></h2>
<p>Programmers who are used to C libraries for multi-threaded programming are likely to
wonder why Boost.Threads uses a non-copyable design for <a href="thread.html">boost::thread</a>. After all, the C
thread types are copyable, and you often have a need for copying them within user code.
However, careful comparison of C designs to C++ designs shows a flaw in this logic.</p>
<p>All C types are copyable. It is, in fact, not possible to make a non-copyable type in
C. For this reason types that represent system resources in C are often designed to behave
very similarly to a pointer to dynamic memory. There's an API for acquiring the resource
and an API for releasing the resources. For memory we have pointers as the type and
alloc/free for the acquisition and release APIs. For files we have FILE* as the type
and fopen/fclose for the acquisition and release APIs. You can freely copy instances of the
types but must manually manage the lifetime of the actual resource through the acquisition
and release APIs.</p>
<p>C++ designs recognize that the acquisition and release APIs are error prone and try
to eliminate possible errors by acquiring the resource in the constructor and releasing it
in the destructor. The best example of such a design is the std::iostream set of classes
which can represent the same resource as the FILE* type in C. A file is opened in the
std::fstream's constructor and closed in its destructor. However, if an iostream were
copyable it could lead to a file being closed twice, an obvious error, so the std::iostream
types are noncopyable by design. This is the same design used by boost::thread, which
is a simple and easy to understand design that's consistent with other C++ standard types.</p>
<p>During the design of boost::thread it was pointed out that it would be possible to allow
it to be a copyable type if some form of "reference management" were used, such as ref-counting
or ref-lists, and many argued for a boost::thread_ref design instead. The reasoning was
that copying "thread" objects was a typical need in the C libraries, and so presumably would
be in the C++ libraries as well. It was also thought that implementations could provide
more efficient reference management then wrappers (such as boost::shared_ptr) around a noncopyable
thread concept. Analysis of whether or not these arguments would hold true don't appear to
bear them out. To illustrate the analysis we'll first provide pseudo-code illustrating the six
typical usage patterns of a thread object.</p>
<h3>1. Simple creation of a thread.</h3>
<pre>
void foo()
{
create_thread(&amp;bar);
}
</pre>
<h3>2. Creation of a thread that's later joined.</h3>
<pre>
void foo()
{
thread = create_thread(&amp;bar);
join(thread);
}
</pre>
<h3>3. Simple creation of several threads in a loop.</h3>
<pre>
void foo()
{
for (int i=0; i&lt;NUM_THREADS; ++i)
create_thread(&amp;bar);
}
</pre>
<h3>4. Creation of several threads in a loop which are later joined.</h3>
<pre>
void foo()
{
for (int i=0; i&lt;NUM_THREADS; ++i)
threads[i] = create_thread(&amp;bar);
for (int i=0; i&lt;NUM_THREADS; ++i)
threads[i].join();
}
</pre>
<h3>5. Creation of a thread whose ownership is passed to another object/method.</h3>
<pre>
void foo()
{
thread = create_thread(&amp;bar);
manager.owns(thread);
}
</pre>
<h3>6. Creation of a thread whose ownership is shared between multiple objects.</h3>
<pre>
void foo()
{
thread = create_thread(&amp;bar);
manager1.add(thread);
manager2.add(thread);
}
</pre>
<p>Of these usage patterns there's only one that requires reference management (number 6).
Hopefully it's fairly obvious that this usage pattern simply won't occur as often as the
other usage patterns. So there really isn't a "typical need" for a thread concept, though
there is some need.</p>
<p>Since the need isn't typical we must use different criteria for deciding on either a
thread_ref or thread design. Possible criteria include ease of use and performance. So let's
analyze both of these carefully.</p>
<p>With ease of use we can look at existing experience. The standard C++ objects that
represent a system resource, such as std::iostream, are noncopyable, so we know that C++
programmers must at least be experienced with this design. Most C++ developers are also
used to smart pointers such as boost::shared_ptr, so we know they can at least adapt to
a thread_ref concept with little effort. So existing experience isn't going to lead us
to a choice.</p>
<p>The other thing we can look at is how difficult it is to use both types for the six usage
patterns above. If we find it overly difficult to use a concept for any of the usage patterns
there would be a good argument for choosing the other design. So we'll code all six usage
patterns using both designs.</p>
<h3>1.</h3>
<pre>
void foo()
{
thread thrd(&amp;bar);
}
void foo()
{
thread_ref thrd = create_thread(&amp;bar);
}
</pre>
<h3>2.</h3>
<pre>
void foo()
{
thread thrd(&amp;bar);
thrd.join();
}
void foo()
{
thread_ref thrd =
create_thread(&amp;bar);thrd-&gt;join();
}
</pre>
<h3>3.</h3>
<pre>
void foo()
{
for (int i=0; i&lt;NUM_THREADS; ++i)
thread thrd(&amp;bar);
}
void foo()
{
for (int i=0; i&lt;NUM_THREADS; ++i)
thread_ref thrd = create_thread(&amp;bar);
}
</pre>
<h3>4.</h3>
<pre>
void foo()
{
std::auto_ptr&lt;thread&gt; threads[NUM_THREADS];
for (int i=0; i&lt;NUM_THREADS; ++i)
threads[i] = std::auto_ptr&lt;thread&gt;(new thread(&amp;bar));
for (int i= 0; i&lt;NUM_THREADS;
++i)threads[i]-&gt;join();
}
void foo()
{
thread_ref threads[NUM_THREADS];
for (int i=0; i&lt;NUM_THREADS; ++i)
threads[i] = create_thread(&amp;bar);
for (int i= 0; i&lt;NUM_THREADS;
++i)threads[i]-&gt;join();
}
</pre>
<h3>5.</h3>
<pre>
void foo()
{
thread thrd* = new thread(&amp;bar);
manager.owns(thread);
}
void foo()
{
thread_ref thrd = create_thread(&amp;bar);
manager.owns(thrd);
}
</pre>
<h3>6.</h3>
<pre>
void foo()
{
boost::shared_ptr&lt;thread&gt; thrd(new thread(&amp;bar));
manager1.add(thrd);
manager2.add(thrd);
}
void foo()
{
thread_ref thrd = create_thread(&amp;bar);
manager1.add(thrd);
manager2.add(thrd);
}
</pre>
<p>This shows the usage patterns being nearly identical in complexity for both designs.
The only actual added complexity occurs because of the use of operator new in (4), (5)
and (6) and the use of std::auto_ptr and boost::shared_ptr in (4) and (6) respectively.
However, that's not really much added complexity, and C++ programmers are used to using
these idioms any way. Some may dislike the presence of operator new in user code,
but this can be eliminated by proper design of higher level concepts, such as the
boost::thread_group class that simplifies example (4) down to:</p>
<pre>
void foo()
{
thread_group threads;
for (int i=0; i&lt;NUM_THREADS; ++i)
threads.create_thread(&amp;bar);
threads.join_all();
}
</pre>
<p>So ease of use is really a wash and not much help in picking a design.</p>
<p>So what about performance? If you look at the above code examples we can analyze
the theoretical impact to performance that both designs have. For (1) we can see that
platforms that don't have a ref-counted native thread type (POSIX, for instance) will
be impacted by a thread_ref design. Even if the native thread type is ref-counted there
may be an impact if more state information has to be maintained for concepts foreign
to the native API, such as clean up stacks for Win32 implementations. For (2) the
performance impact will be identical to (1). The same for (3). For (4) things get a
little more interesting and we find that theoretically at least the thread_ref may
perform faster since the thread design requires dynamic memory allocation/deallocation.
However, in practice there may be dynamic allocation for the thread_ref design as well,
it will just be hidden from the user. As long as the implementation has to do dynamic
allocations the thread_ref loses again because of the reference management. For (5)
we see the same impact as we do for (4). For (6) we still have a possible impact
to the thread design because of dynamic allocation but thread_ref no longer suffers
because of it's reference management, and in fact, theoretically at least, the thread_ref
may do a better job of managing the references. All of this indicates that thread wins
for (1), (2) and (3), with (4) and (5) the winner depends on the implementation and the platform
but the thread design probably has a better chance, and with (6) it will again
depend on the implementation and platform but this time we favor thread_ref slightly.
Given all of this it's a narrow margin, but the thread design prevails.</p>
<p>Given this analysis, and the fact that noncopyable objects for system resources are
the normal designs that C++ programmers are used to dealing with, the Boost.Threads
library has gone with a noncopyable design.</p>
<h2>Rationale for not providing <i><a name="Events">Event</a> Variables</i></h2>
<p><i>Event variables </i>are simply far too error-prone.&nbsp; <a href="condition.html">Condition
variables</a> are a much safer alternative.</p>
<p>[Note that Graphical User Interface <i>events</i> are a different concept,
and are not what is being discussed here.]</p>
<p>Event variables were one of the first synchronization primitives. They are
still used today, for example, in the native Windows multithreading API.</p>
<p>Yet both respected computer science researchers and experienced
multithreading practitioners believe event variables are so inherently
error-prone that they should never be used, and thus should not be part of a
multithreading library.</p>
<p>Per Brinch Hansen <a href="bibliography.html#Brinch-Hansen-73">[Brinch Hansen
73]</a> analyzed event variables in some detail, pointing out [emphasis his]
that &quot;<i>event operations force the programmer to be aware of the relative
speeds of the sending and receiving processes</i>&quot;. His summary:</p>
<blockquote>
<p>We must therefore conclude that event variables of the previous type are
impractical for system design. <i>The effect of an interaction between two
processes must be independent of the speed at which it is carried out.</i></p>
</blockquote>
<p>Experienced programmers using the Windows platform today
report that event variables are a continuing source of errors, even after previous
bad experiences caused them to be very careful in their use of event
variables.&nbsp; Overt problems can be avoided, for example, by teaming the
event variable with a mutex, but that may just convert a <a href="definitions.html#Race condition">race
condition</a> into another problem, such as excessive resource use. One of the most
distressing aspects of the experience reports is the claim that many defects are
latent.&nbsp; That is, the programs appear to work correctly, but contain
hidden timing dependencies which will cause them to fail when environmental
factors or usage patterns change, altering relative thread timings.</p>
<p>The decision to exclude event variables from Boost.Threads has been
surprising to some Windows programmers.&nbsp; They have written programs which
work using event variables, and wonder what the problem is.&nbsp; It seems
similar to the &quot;goto considered harmful&quot; controversy of 30 years ago.
It isn't that events, like gotos, can't be made to work, but rather that
virtually all programs using alternatives will be easier to write, debug,
read, maintain, and be less likely to contain latent defects.</p>
<p>[Rationale provided by Beman Dawes]</p>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <A href="mailto:williamkempf@hotmail.com">William E. Kempf</A>
2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,327 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost.Threads, recursive_mutex</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">recursive_mutex<br>
recursive_try_mutex<br>
recursive_timed_mutex</h2>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br>
<a href="#Header">Header</a><br>
<a href="#recursive_mutex Synopsis">Class recursive_mutex Synopsis</a><br>
<a href="#recursive_mutex Members">Class recursive_mutex Members</a><br>
<a href="#recursive_try_mutex Synopsis">Class recursive_try_mutex Synopsis</a><br>
<a href="#recursive_try_mutex Members">Class recursive_try_mutex Members</a><br>
<a href="#recursive_timed_mutex Synopsis">Class recursive_timed_mutex Synopsis</a><br>
<a href="#recursive_timed_mutex Members">Class recursive_timed_mutex Members</a><br>
<a href="#Example">Example</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <code>recursive_mutex</code>, <code>recursive_try_mutex</code> and
<code>recursive_timed_mutex</code> classes define full featured models of the
<a href="mutex_concept.html#Mutex">Mutex</a>,
<a href="mutex_concept.html#TryMutex">TryMutex</a> and
<a href="mutex_concept.html#TimedMutex">TimedMutex</a> concepts with recursive locking
semantics. These types should be used to synchronize access to shared resources
when recursive locking by a single thread is likely to occur. A good example for this
is when a class supplies "internal synchronization" to ensure
<a href="definitions.html#Thread-safe">thread-safety</a> and a function of the class
may have to call other functions of the class which also attempt to lock the mutex.
For recursive locking mechanics, see <a href="mutex.html">mutexes</a>.
<p>Each class supplies one or more typedefs for lock types which model matching
lock concepts. For the best possible performance you should use the mutex class that
supports the minimum set of lock types that you need.</p>
<table border="1" cellpadding="5">
<tr>
<td><b>Mutex Class</b></td>
<td><b>Lock name</b></td>
<td><b>Implementation defined Lock Type</b></td>
<td><b>Lock Concept</b></td>
</tr>
<tr>
<td valign="top"><a href="#recursive_mutex Synopsis"><code>recursive_mutex</code></a></td>
<td valign="middle"><code>scoped_lock</code></td>
<td valign="middle"><a href="scoped_lock.html"><code>detail::thread::scoped_lock&lt;recursive_mutex&gt;</code></a></td>
<td valign="middle"><a href="lock_concept.html#ScopedLock">ScopedLock</a></td>
</tr>
<tr>
<td valign="top"><code><a href="#recursive_try_mutex Synopsis">recursive_try_mutex</a></code></td>
<td valign="middle"><code>scoped_lock<br>
scoped_try_lock</code></td>
<td valign="middle"><a href="scoped_lock.html"><code>detail::thread::scoped_lock&lt;recursive_try_mutex&gt;<br>
</code></a><code><a href="scoped_try_lock.html">detail::thread::scoped_try_lock&lt;recursive_try_mutex&gt;</a></code></td>
<td valign="middle"><a href="lock_concept.html#ScopedLock">ScopedLock</a><br>
<a href="lock_concept.html#ScopedTryLock">ScopedTryLock</a></td>
</tr>
<tr>
<td valign="top"><code><a href="#recursive_timed_mutex Synopsis">recursive_timed_mutex</a></code> </td>
<td valign="middle"><code>scoped_lock<br>
scoped_try_lock<br>
scoped_timed_lock</code></td>
<td valign="middle"><a href="scoped_lock.html"><code>detail::thread::scoped_lock&lt;recursive_timed_mutex&gt;</code></a><br>
<a href="scoped_try_lock.html"><code>detail::thread::scoped_try_lock&lt;recursive_timed_mutex&gt;</code></a><br>
<a href="scoped_timed_lock.html"><code>detail::thread::scoped_timed_lock&lt;recursive_timed_mutex&gt;</code></a></td>
<td valign="middle"><a href="lock_concept.html#ScopedLock">ScopedLock</a><br>
<a href="lock_concept.html#ScopedTryLock">ScopedTryLock</a><br>
<a href="lock_concept.html#ScopedTimedLock">ScopedTimedLock</a></td>
</tr>
</table>
<p>The <code>recursive_mutex</code>, <code>recursive_try_mutex</code> and
<code>recursive_timed_mutex</code> employ a <code>Recursive</code>
<a href="mutex_concept.html#LockingStrategies">locking strategy</a>, so attempts to
recursively lock them succeed and an internal "lock count" is maintained. Attempts
to unlock them by a thread that does not own a lock on them will result in a
<a href="lock_error.html">lock_error</a> exception being thrown.</p>
<p>The <code>recursive_mutex</code>, <code>recursive_try_mutex</code> and
<code>recursive_timed_mutex</code> leave the
<a href="mutex_concept.html#SchedulingPolicies">scheduling policy</a> as
<code>Unspecified</code>. Programmers should assume that threads waiting for a lock on
objects of these types acquire the lock in a random order, even though the specific
behavior for a given platform may be different.</p>
<h2><a name="Header">Header</a></h2>
<pre>
#include <a href="../../../boost/thread/recursive_mutex.hpp">&lt;boost/thread/recursive_mutex.hpp&gt;</a>
</pre>
<h2>Class <a name="recursive_mutex Synopsis"> recursive_mutex Synopsis</a></h2>
<hr>
<pre>
namespace boost
{
class recursive_mutex : private <a href="../../utility/utility.htm">boost::noncopyable</a> // Exposition only.
// Class recursive_mutex meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
{
public:
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_lock;
recursive_mutex();
~recursive_mutex();
};
}
</pre>
<h2>Class <a name="recursive_mutex Members">recursive_mutex Members</a></h2>
<hr>
<h3>Constructor</h3>
<pre>
recursive_mutex();
</pre>
<p><b>Postconditions: </b><code>*this</code> is in the unlocked state.</p>
<hr>
<h3>Destructor</h3>
<pre>
~recursive_mutex();
</pre>
<p><b>Requires:</b> <code>*this</code> is in the unlocked state.</p>
<p><b>Effects:</b> Destroys <code>*this</code>.</p>
<p><b>Dangers:</b> Destruction of a locked mutex is a serious programming error
resulting in undefined behavior such as a program crash..</p>
<hr>
<h2>
Class <a name="recursive_try_mutex Synopsis">recursive_try_mutex Synopsis</a>
</h2>
<pre>
namespace boost
{
class recursive_try_mutex : private boost::noncopyable // Exposition only.
// Class recursive_try_mutex meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
{
public:
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_lock;
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_try_lock;
recursive_try_mutex();
~recursive_try_mutex();
};
}
</pre>
<h2>Class <a name="recursive_try_mutex Members">recursive_try_mutex Members</a></h2>
<hr>
<h3>Constructor</h3>
<pre>
recursive_try_mutex();
</pre>
<p><b>Postconditions: </b><code>*this</code> is in the unlocked state.</p>
<hr>
<h3>Destructor</h3>
<pre>
~recursive_try_mutex();
</pre>
<p><b>Requires:</b> <code>*this</code> is in the unlocked state.</p>
<p><b>Effects:</b> Destroys <code>*this</code>.</p>
<p><b>Dangers:</b> Destruction of a locked mutex is a serious programming error
resulting in undefined behavior such as a program crash..</p>
<hr>
<h2>
Class <a name="recursive_timed_mutex Synopsis">recursive_timed_mutex Synopsis</a>
</h2>
<pre>
namespace boost
{
class recursive_timed_mutex : private boost::noncopyable // Exposition only.
// Class recursive_timed_mutex meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
{
public:
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_lock;
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_try_lock;
typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_timed_lock;
recursive_timed_mutex();
~recursive_timed_mutex();
};
}
</pre>
<h2>
Class <a name="recursive_timed_mutex Members">recursive_timed_mutex Members</a>
</h2>
<hr>
<h3>Constructor</h3>
<pre>
recursive_timed_mutex();
</pre>
<p><b>Postconditions: </b><code>*this</code> is in the unlocked state.</p>
<hr>
<h3>Destructor</h3>
<pre>
~recursive_timed_mutex();
</pre>
<p><b>Requires:</b> <code>*this</code> is in the unlocked state.</p>
<p><b>Effects:</b> Destroys <code>*this</code>.</p>
<p><b>Dangers:</b> Destruction of a locked mutex is a serious programming error
resulting in undefined behavior such as a program crash..</p>
<hr>
<h2><a name="Example">Example</a> Usage</h2>
<pre>
#include <a href="../../../boost/thread/recursive_mutex.hpp">&lt;boost/thread/recursive_mutex.hpp&gt;</a>
#include <a href="../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
#include &lt;iostream&gt;
class counter
{
public:
counter() : count(0) { }
int add(int val) {
boost::recursive_mutex::scoped_lock scoped_lock(mutex);
count += val;
return count;
}
int increment() {
boost::recursive_mutex::scoped_lock scoped_lock(mutex);
return add(1);
}
private:
boost::recursive_mutex mutex;
int count;
};
counter c;
void change_count(void*)
{
std::cout &lt;&lt; &quot;count == &quot; &lt;&lt; c.increment() &lt;&lt; std::endl;
}
int main(int, char*[])
{
const int num_threads=4;
boost::thread_group threads;
for (int i=0; i &lt; num_threads; ++i)
threads.create_thread(&amp;change_count, 0);
threads.join_all();
return 0;
}
</pre>
<p>The output is:</p>
<pre>
count == 1
count == 2
count == 3
count == 4
</pre>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,134 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<title>Boost.Threads, atomic_t</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">atomic_t</h2>
</td>
</tr>
</table>
<hr>
<h2>Header</h2>
<p>The <tt>atomic_t</tt> class defines an "atomic integer" type. This class should be used
to perform thread safe operations on an integral type with out the overhead of locks. Only
a limited set of integer operations are available with an <tt>atomic_t</tt> instance.</p>
<pre>
#include &lt;boost/thread/atomic.hpp&gt;
</pre>
<h2>Public Interface</h2>
<pre>
class atomic_t
{
public:
typedef <b>implementation defined</b> value_type;
explicit atomic_t(value_type val=0);
};
atomic_t::value_type read(const atomic_t&amp; x);
atomic_t::value_type increment(atomic_t&amp; x);
atomic_t::value_type decrement(atomic_t&amp; x);
atomic_t::value_type swap(atomic_t&amp; x, atomic_t::value_type y);
atomic_t::value_type compare_swap(atomic_t&amp; x, atomic_t::value_type y, atomic_t::value_type z);
</pre>
<h3>Constructor</h3>
<pre>
atomic_t(atomic_t::value_type val=0);
</pre>
<p>Constructs an <tt>atomic_t</tt> and sets its value to <tt>val</tt>.</p>
<h3>read</h3>
<pre>
atomic_t::value_type read(const atomic_t&amp; x);
</pre>
<p>Gets the current value of <tt>x</tt>.</p>
<h3>increment</h3>
<pre>
atomic_t::value_type increment(atomic_t&amp; x);
</pre>
<p>Increments <tt>x</tt> and returns a value <tt>&lt; 0</tt> if the result is less than 0,
<tt>&gt; 0</tt> if the result is greater than 0 and <tt>== 0</tt> if the result is equal to
0.</p>
<h3>decrement</h3>
<pre>
atomic_t::value_type decrement(atomic_t&amp; x);
</pre>
<p>Decrements <tt>x</tt> and returns a value <tt>&lt; 0</tt> if the result is less than 0,
<tt>&gt; 0</tt> if the result is greater than 0 and <tt>== 0</tt> if the result is equal to
0.</p>
<h3>swap</h3>
<pre>
atomic_t::value_type swap(atomic_t&amp; x, atomic_t::value_type y);
</pre>
<p>Assigns the value of <tt>y</tt> to <tt>x</tt> and returns the value of <tt>x</tt> prior
to the swap.</p>
<h3>compare_swap</h3>
<pre>
atomic_t::value_type compare_swap(atomic_t&amp; x, atomic_t::value_type y, atomic_t::value_type z);
</pre>
<p>Compares the value of <tt>z</tt> to the value of <tt>x</tt> and if equal sets the value of
<tt>x</tt> to the value of <tt>y</tt> and returns the value of <tt>x</tt> prior to the swap.</p>
<h2>Example Usage</h2>
<pre>
#include &lt;boost/thread/atomic.hpp&gt;
#include &lt;boost/test/test_tools.hpp&gt;
int test_main(int, char*[])
{
boost::atomic_t a;
BOOST_TEST_VERIFY(boost::read(a) == 0);
BOOST_TEST_VERIFY(boost::increment(a) &gt; 0);
BOOST_TEST_VERIFY(boost::decrement(a) == 0);
BOOST_TEST_VERIFY(boost::swap(a, 1) == 0);
BOOST_TEST_VERIFY(boost::swap(a, 2, 0) == 1);
BOOST_TEST_VERIFY(boost::read(a) == 1);
}
</pre>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,213 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost.Threads, scoped_lock</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">scoped_lock</h2>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br>
<a href="#Header">Header</a><br>
<a href="#Synopsis">Synopsis</a><br>
<a href="#Members">Members</a><br>
<a href="#Example">Example</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>This class template defines a generic lock type which meets the
<a href="lock_concept.html#ScopedLock">ScopedLock</a> requirements. The
<a href="mutex.html">mutex</a>, <a href="mutex.html">try_mutex</a>,
<a href="mutex.html">timed_mutex</a>, <a href="recursive_mutex.html">recursive_mutex</a>,
<a href="recursive_mutex.html">recursive_try_mutex</a> and
<a href="recursive_mutex.html">recursive_timed_mutex</a> classes all use this template
to define their <code>scoped_lock</code> types.</p>
<p>Like all the <b>Boost.Threads</b> <a href="lock_concept.html">lock models</a>,
<code>scoped_lock</code> objects are meant to be short-lived. Objects of the class
are not <a href="definitions.html#thread-safe">thread-safe</a>, and so should not be
shared between threads.</p>
<p>Class <code> scoped_lock</code> follows the &quot;resource acquisition is
initialization&quot; idiom <a href="bibliography.html#Stroustrup-00">[Stroustrup
00 14.4.1]</a> and is a realization of the &quot;Scoped Locking Pattern&quot;
<a href="bibliography.html#Schmidt-00">[Schmidt-00]</a>. Thus the usage is to let the
constructor do the locking, and then let the destructor do the unlocking automatically at
the end of the enclosing scope. The lock() and unlock() members are usually not
explicitly called, but are provided to allow for complex overlapping locks of multiple
mutexes.</p>
<p>The type used to instantiate the class must meet the
<a href="mutex_concept.html#Mutex">Mutex</a> requirements.</p>
<p>Although this class is an implementation detail, it is publicly documented here because
of its importance.</p>
<h2><a name="Header">Header</a></h2>
<pre>
#include <a href="../../../boost/thread/detail/lock.hpp">&lt;boost/thread/detail/lock.hpp&gt;</a>
<i>This header is usually not included directly by programmers
because it is supplied by <a href="../../../boost/thread/mutex.hpp">&lt;boost/thread/mutex.hpp&gt;</a> or
<a href="../../../boost/thread/recursive_mutex.hpp">&lt;boost/thread/recursive_mutex.hpp&gt;</a></i>
</pre>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>
namespace boost { namespace detail { namespace thread {
template &lt;typename Mutex&gt;
class scoped_lock : private <a href="../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
// Class scoped_lock meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
{
public:
typedef Mutex mutex_type;
explicit scoped_lock(Mutex&amp; mx, bool initially_locked=true);
~scoped_lock();
void lock();
void unlock();
operator const void*() const;
bool locked() const;
};
} // namespace thread
} // namespace detail
} // namespace boost
</pre>
<h2><a name="Members">Members</a></h2>
<hr>
<h3>Constructor</h3>
<pre>
explicit scoped_lock(Mutex&amp; mx, bool initially_locked=true);
</pre>
<p><b>Effects:</b> Associates mutex <code>mx</code> with <code>*this</code>.
If <code>initially_locked</code> is <code>true,</code> calls <code>lock()</code>.</p>
<hr>
<h3>Destructor</h3>
<pre>
~scoped_lock();
</pre>
<p><b>Effects:</b> If <code> locked()</code>, calls <code>unlock()</code>. Destroys
<code>*this</code>.</p>
<hr>
<h3>lock</h3>
<pre>
void lock();
</pre>
<p><b>Effects:</b> If the associated mutex is already locked by another lock in the
current thread, the effects depend on the locking strategy of the associated mutex, as
shown in the following table:</p>
<table border="1" cellpadding="5">
<tr>
<td><i><a href="mutex_concept.html#LockingStrategies">Locking Strategy</a><br>
of associated mutex</i></td>
<td><i>Effect if associated mutex is already locked by the current thread</i></td>
</tr>
<tr>
<td>Recursive</td>
<td>As if an additional lock were added to the mutex.</td>
</tr>
<tr>
<td>Checked</td>
<td>Throws <a href="lock_error.html">lock_error</a>.</td>
</tr>
<tr>
<td>Unchecked</td>
<td>Undefined behavior [<a href="bibliography.html#ISO">ISO</a> 1.3.12] (but
typically, <a href="definitions.html#Deadlock">deadlock</a>.)</td>
</tr>
</table>
<p>If the associated mutex is already locked by some other thread, places the
current thread in the <a href="definitions.html#State">Blocked</a> state until
the associated mutex is unlocked, after which the current thread is placed in
the <a href="definitions.html#State">Ready</a> state, eventually to be returned
to the <a href="definitions.html#State">Running</a> state.
<p><b>Postcondition:</b> locked()
<p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>locked()</code> or
as indicated in <b>Effects</b>.</p>
<hr>
<h3>unlock</h3>
<pre>
void unlock();
</pre>
<p><b>Effects: </b>Unlocks the associated mutex.</p>
<p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>!locked()</code>.</p>
<hr>
<h3>const void* Conversion</h3>
<pre>
operator const void*() const;
</pre>
<p><b>Returns:</b> If the associated mutex is currently locked, a value convertible to
<code>true</code>, else a value convertible to <code>false</code>.</p>
<p><b>Rationale:</b> A <code>const void*</code> conversion is considered safer than a
conversion to <code>bool</code>.</p>
<hr>
<h3>locked</h3>
<pre>
bool locked() const;
</pre>
<p><b>Returns:</b> <code>this-&gt;operator const void*() != 0</code>.</p>
<hr>
<h2><a name="Example">Example</a> Usage</h2>
<p>See the example given in the documentation for the <a href="mutex.html">mutex</a>
class.</p>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,261 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost.Threads, scoped_timed_lock</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">scoped_timed_lock</h2>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br>
<a href="#Header">Header</a><br>
<a href="#Synopsis">Synopsis</a><br>
<a href="#Members">Members</a><br>
<a href="#Example">Example</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>This class template defines a generic lock type which meets the
<a href="lock_concept.html#ScopedTimedLock">ScopedTimedLock</a> requirements. The
<a href="mutex.html">timed_mutex</a> and
<a href="recursive_mutex.html">recursive_timed_mutex</a> classes use this template to
define their <code>scoped_timed_lock</code> types.</p>
<p>Like all the <b>Boost.Threads</b> <a href="lock_concept.html">lock models</a>,
<code>scoped_timed_lock</code> objects are meant to be short-lived. Objects of the
class are not <a href="definitions.html#thread-safe">thread-safe</a>, and so should
not be shared between threads.</p>
<p>Class <code>scoped_timed_lock</code> follows the &quot;resource acquisition is
initialization&quot; idiom <a href="bibliography.html#Stroustrup-00">[Stroustrup
00 14.4.1]</a> and is a realization of the &quot;Scoped Locking Pattern&quot;
<a href="bibliography.html#Schmidt-00">[Schmidt-00]</a>. Thus the usage is to let the
constructor do the locking, and then let the destructor do the unlocking automatically
at the end of the enclosing scope. The lock() and unlock() members are usually not
explicitly called, but are provided to allow for complex overlapping locks of multiple
mutexes.</p>
<p>The type used to instantiate the class must meet the
<a href="mutex_concept.html#TimedMutex">TimedMutex</a> requirements.</p>
<p>Although this class is an implementation detail, it is publicly documented here because
of its importance.</p>
<h2><a name="Header">Header</a></h2>
<pre>
#include <a href="../../../boost/thread/detail/lock.hpp">&lt;boost/thread/detail/lock.hpp&gt;</a>
<i>This header is usually not included directly by programmers
because it is supplied by <a href="../../../boost/thread/mutex.hpp">&lt;boost/thread/mutex.hpp&gt;</a> or
<a href="../../../boost/thread/recursive_mutex.hpp">&lt;boost/thread/recursive_mutex.hpp&gt;</a></i>
</pre>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>
namespace boost { namespace detail { namespace thread {
template &lt;typename TimedMutex&gt;
class scoped_timed_lock : private <a href="../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
// Class scoped_timed_lock meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
{
public:
typedef TimedMutex mutex_type;
scoped_timed_lock(TimedMutex&amp; mx, const boost::xtime&amp; xt);
scoped_timed_lock(TimedMutex&amp; mx, bool initially_locked);
~scoped_timed_lock();
void lock();
bool timed_lock(const xtime&amp; xt);
void unlock();
operator const void*() const;
};
} // namespace thread
} // namesapce detail
} // namespace boost
</pre>
<h2><a name="Members">Members</a></h2>
<hr>
<h3>Constructor</h3>
<pre>
scoped_timed_lock(TimedMutex&amp; mx, const <a href="xtime.html">xtime</a>&amp; xt);
</pre>
<p><b>Effects:</b> Associates mutex <code>mx</code> with <code>*this</code>.
Calls <code>timed_lock</code>( <code>xt</code>)</p>
<hr>
<pre>
scoped_timed_lock(TimedMutex&amp; mx, bool initially_locked);
</pre>
<p><b>Effects:</b> Associates mutex <code>mx</code> with <code>*this</code>.
If <code>initially_locked</code> is <code>true</code>, calls <code>lock()</code>.</p>
<hr>
<h3>Destructor</h3>
<pre>
~scoped_timed_lock();
</pre>
<p><b>Effects:</b> If <code> locked()</code>, calls <code>unlock()</code>. Destroys
<code>*this</code>.</p>
<hr>
<h3>lock</h3>
<pre>
void lock();
</pre>
<p><b>Effects:</b> If the associated mutex is already locked by another lock in the
current thread, the effects depend on the locking strategy of the associated mutex, as
shown in the following table:</p>
<table border="1" cellpadding="5">
<tr>
<td><i><a href="mutex_concept.html#LockingStrategies">Locking Strategy</a><br>
of associated mutex</i></td>
<td><i>Effect if associated mutex is already locked by the current thread</i></td>
</tr>
<tr>
<td>Recursive</td>
<td>As if an additional lock were added to the mutex.</td>
</tr>
<tr>
<td>Checked</td>
<td>Throws <a href="lock_error.html">lock_error</a>.</td>
</tr>
<tr>
<td>Unchecked</td>
<td>Undefined behavior [<a href="bibliography.html#ISO">ISO</a> 1.3.12] (but
typically, <a href="definitions.html#Deadlock">deadlock</a>.)</td>
</tr>
</table>
<p>If the associated mutex is already locked by some other thread, places the
current thread in the <a href="definitions.html#State">Blocked</a> state until
the associated mutex is unlocked, after which the current thread is placed in
the <a href="definitions.html#State">Ready</a> state, eventually to be returned
to the <a href="definitions.html#State">Running</a> state. Places the associated
mutex in the locked state.
<p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>locked()</code> or
as indicated in <b>Effects</b>.</p>
<hr>
<h3>timed_lock</h3>
<pre>
bool timed_lock(const <a href="xtime.html">xtime</a>&amp; xt);
</pre>
<p><b>Effects:</b> Same as <code>lock()</code>, except that if xt is reached,
places the current thread in the <a href="definitions.html#State">Ready</a>
state without further ado.</p>
<p><b>Returns:</b> <code>locked()</code>.</p>
<p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>locked()</code> or
as indicated in <b>Effects</b>.</p>
<hr>
<h3>unlock</h3>
<pre>
void unlock();
</pre>
<p><b>Effects: </b>Unlocks the associated mutex.</p>
<p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>!locked()</code>.</p>
<hr>
<h3>const void* Conversion</h3>
<pre>
operator const void*() const;
</pre>
<p><b>Returns:</b> If the associated mutex is currently locked, a value convertible to
<code>true</code>, else a value convertible to <code>false</code>.</p>
<p><b>Rationale:</b> A <code>const void*</code> conversion is considered safer than a
conversion to <code>bool</code>.</p>
<hr>
<h3>locked</h3>
<pre>
bool locked() const;
</pre>
<p><b>Returns:</b> <code>this-&gt;operator const void*() != 0</code>.</p>
<hr>
<h2><a name="Example">Example</a> Usage</h2>
<pre>
#include &lt;boost/thread/mutex.hpp&gt;
#include &lt;iostream&gt;
int main(int, char*[])
{
boost::timed_mutex mutex;
boost::xtime xt;
boost::get_xtime(&amp;xt, boost::TIME_UTC);
xt.sec += 1;
boost::mutex::scoped_timed_lock scope_timed_lock(mutex, xt);
if (scope_timed_lock.locked())
std::cout &lt;&lt; &quot;locked&quot; &lt;&lt; std::endl;
else
std::cout &lt;&lt; &quot;unlocked&quot; &lt;&lt; std::endl;
return 0;
}
</pre>
<p>The output is:</p>
<pre>
locked
</pre>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%B %d, %Y" startspan -->October 01, 2001<!--webbot bot="Timestamp" endspan i-checksum="30079" -->
</p>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,282 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost.Threads, scoped_try_lock</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">scoped_try_lock</h2>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br>
<a href="#Header">Header</a><br>
<a href="#Synopsis">Synopsis</a><br>
<a href="#Members">Members</a><br>
<a href="#Example">Example</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>This class template defines a generic lock type which meets the
<a href="lock_concept.html#ScopedTryLock">ScopedTryLock</a> requirements. The
<a href="mutex.html">try_mutex</a>, <a href="mutex.html">timed_mutex</a>,
<a href="recursive_mutex.html">recursive_try_mutex</a> and
<a href="recursive_mutex.html">recursive_timed_mutex</a> classes use this template
to define their <code>scoped_try_lock</code> types.</p>
<p>Like all the <b>Boost.Threads</b> <a href="lock_concept.html">lock models</a>,
<code>scoped_try_lock</code> objects are meant to be short-lived. Objects of the
class are not <a href="definitions.html#thread-safe">thread-safe</a>, and
so should not be shared between threads.</p>
<p>Class <code> scoped_try_lock</code> follows the &quot;resource acquisition is
initialization&quot; idiom <a href="bibliography.html#Stroustrup-00">[Stroustrup
00 14.4.1]</a> and is a realization of the &quot;Scoped Locking Pattern&quot;
<a href="bibliography.html#Schmidt-00">[Schmidt-00]</a>. Thus the usage is to let the
constructor do the locking, and then let the destructor do the unlocking automatically at
the end of the enclosing scope. The lock() and unlock() members are usually not
explicitly called, but are provided to allow for complex overlapping locks of multiple
mutexes.</p>
<p>Although this class is an implementation detail, it is publicly documented here because
of its importance.</p>
<p>The type used to instantiate the class must meet the <a href="mutex_concept.html#TryMutex">TryMutex</a> requirements.</p>
<h2><a name="Header">Header</a></h2>
<pre>
#include <a href="../../../boost/thread/detail/lock.hpp">&lt;boost/thread/detail/lock.hpp&gt;</a>
<i>This header is usually not included directly by programmers
because it is supplied by <a href="../../../boost/thread/mutex.hpp">&lt;boost/thread/mutex.hpp&gt;</a> or
<a href="../../../boost/thread/recursive_mutex.hpp">&lt;boost/thread/recursive_mutex.hpp&gt;</a></i>
</pre>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>
namespace boost { namespace detail { namespace thread {
template &lt;typename TryMutex&gt;
class scoped_try_lock : private <a href="../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
// Class scoped_try_lock meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
{
public:
typedef TryMutex mutex_type;
explicit scoped_try_lock(TryMutex&amp; mx);
scoped_try_lock(TryMutex&amp; mx, bool initially_locked);
~scoped_try_lock();
void lock();
bool try_lock();
void unlock();
operator const void*() const;
};
} // namespace thread
} // namespace detail
} // namespace boost
</pre>
<h2><a name="Members">Members</a></h2>
<hr>
<h3>Constructors</h3>
<pre>
explicit scoped_try_lock(TryMutex&amp; mx);
</pre>
<p><b>Effects:</b> Associates mutex <code>mx</code> with <code>*this</code>.
Calls <code>try_lock()</code>.</p>
<hr>
<pre>
scoped_try_lock(TryMutex&amp; mx, bool initially_locked);
</pre>
<p><b>Effects:</b> Associates mutex <code>mx</code> with <code>*this</code>.
If <code>initially_locked</code> is <code>true,</code> calls <code>lock()</code>.</p>
<hr>
<h3>Destructor</h3>
<pre>
~scoped_try_lock();
</pre>
<p><b>Effects:</b> If <code>locked()</code>, calls <code>unlock()</code>. Destroys
<code>*this</code>.</p>
<hr>
<h3>lock</h3>
<pre>
void lock();
</pre>
<p><b>Effects:</b> If the associated mutex is already locked by another lock in the
current thread, the effects depend on the locking strategy of the associated mutex, as
shown in the following table:</p>
<table border="1" cellpadding="5" height="147">
<tr>
<td height="34"><i><a href="mutex_concept.html#LockingStrategies">Locking Strategy</a><br>
of associated mutex</i></td>
<td height="34"><i>Effect if associated mutex is already locked by the
current thread</i></td>
</tr>
<tr>
<td height="19">Recursive</td>
<td height="19">As if an additional lock were added to the mutex.</td>
</tr>
<tr>
<td height="19">Checked</td>
<td height="19">Throws <a href="lock_error.html">lock_error</a>.</td>
</tr>
<tr>
<td height="19">Unchecked</td>
<td height="19">Undefined behavior [<a href="bibliography.html#ISO">ISO</a> 1.3.12] (but
typically, <a href="definitions.html#Deadlock">deadlock</a>.)</td>
</tr>
</table>
<p>If the associated mutex is already locked by some other thread, places the
current thread in the <a href="definitions.html#State">Blocked</a> state until
the associated mutex is unlocked, after which the current thread is placed in
the <a href="definitions.html#State">Ready</a> state, eventually to be returned
to the <a href="definitions.html#State">Running</a> state. Places the associated
mutex in the locked state.</p>
<p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>locked()</code> or
as indicated in <b>Effects</b>.</p>
<hr>
<h3>try_lock</h3>
<pre>
bool try_lock();
</pre>
<p><b>Effects:</b> If the associated mutex is already locked by another lock in the
current thread, the effects depend on the locking strategy of the associated mutex, as
shown in the following table:</p>
<table border="1" cellpadding="5" height="147">
<tr>
<td height="34"><i><a href="mutex_concept.html#LockingStrategies">Locking Strategy</a><br>
of associated mutex</i></td>
<td height="34"><i>Effect if associated mutex is already locked by the
current thread</i></td>
</tr>
<tr>
<td height="19">Recursive</td>
<td height="19">As if an additional lock were added to the mutex.</td>
</tr>
<tr>
<td height="19">Checked</td>
<td height="19">Throws <a href="lock_error.html">lock_error</a>.</td>
</tr>
<tr>
<td height="19">Unspecified</td>
<td height="19">Undefined behavior [<a href="bibliography.html#ISO">ISO</a> 1.3.12] (but
typically, <a href="definitions.html#Deadlock">deadlock</a>.)</td>
</tr>
</table>
<p>If the associated mutex is not already locked by some other thread, locks the
associated mutex and returns true, else returns false.</p>
<p><b>Returns:</b> See effects.</p>
<p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>locked()</code> or
as indicated in <b>Effects</b>.</p>
<hr>
<h3>unlock</h3>
<pre>
void unlock();
</pre>
<p><b>Effects: </b>Unlocks the associated mutex.</p>
<p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>!locked()</code>.</p>
<hr>
<h3>const void* Conversion</h3>
<pre>
operator const void*() const;
</pre>
<p><b>Returns:</b> If the associated mutex is currently locked, a value convertible to
<code>true</code>, else a value convertible to <code>false</code>.</p>
<p><b>Rationale:</b> A <code>const void*</code> conversion is considered safer
than a conversion to <code>bool</code>.</p>
<hr>
<h3>locked</h3>
<pre>
bool locked() const;
</pre>
<p><b>Returns:</b> <code>this-&gt;operator const void*() != 0</code>.</p>
<hr>
<h2><a name="Example">Example</a> Usage</h2>
<pre>
#include <a href="../../../boost/thread/mutex.hpp">&lt;boost/thread/mutex.hpp&gt;</a>
#include &lt;iostream&gt;
int main(int, char*[])
{
boost::mutex mutex;
boost::mutex::try_lock lock(mutex);
if (lock)
std::cout &lt;&lt; &quot;locked&quot; &lt;&lt; std::endl;
else
std::cout &lt;&lt; &quot;unlocked&quot; &lt;&lt; std::endl;
return 0;
}
</pre>
<p>The output is:</p>
<pre>
locked
</pre>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,226 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost.Threads, semaphore</title>
</head>
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><IMG height=86 alt="C++ Boost" src="../../../c++boost.gif" width=277></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">semaphore</h2>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br>
<a href="#Header">Header</a><br>
<a href="#Synopsis">Synopsis</a><br>
<a href="#Members">Members</a><br>
<a href="#Example">Example</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <tt>semaphore</tt> class defines a classic synchronization primitive invented by the
Dutch computer scientist Edsger W. Dijkstra. A semaphore manages an internal counter. This
counter never goes below zero, or above a specified maximum value. When calling
<tt>semaphore::down</tt> the calling thread will block until the value is non-zero and then
decrement the value in a single atomic operation. When calling <tt>semaphore::up</tt> the
calling thread will increment the value in a single atomic operation, failing if the value has
already reached the specified maximum.</p>
<p><b>Rationale:</b> The semaphore is the simplest synchronization primitive available and is generally the
primitive used to build other synchronization concepts at some level of implementation. For this
reason <b>Boost.Threads</b> defines the <tt>semaphore</tt> type in the classic form. This simplifies
usage and implementation, but it means that the interface is not as safe as other <b>Boost.Threads</b>
interfaces.</p>
<p><b><a name="Danger">Danger</a>:</b> Unlike the <A href="mutex_concept.html">mutex models</a> supplied by <b>Boost.Threads,</b>
there is no <A href="lock_concept.html">lock_concept</a> for the semaphore to help ensure proper
usage. Great care must be taken when using a <tt>semaphore</tt> object to ensure
<a href="definitions.html#Deadlock"> deadlock</a> or <a href="definitions.html#Race condition">race conditions</a> do not occur.&nbsp;</p>
<p>The dangers are spelled out by <a href="bibliography.html#Andrews-83">[Andrews-83]</a>
(function names updated, see historical note below):&nbsp;</p>
<blockquote>
<p>Although semaphores can be used to program almost any kind of synchronization,
<b>down()</b> and <b>up()</b> are rather unstructured primitives, and so it is easy to err when using them. Execution of each critical section must begin with a
<b>down()</b> and end with a <b>up()</b> (on the same semaphore). Omitting a <b>down()</b>
or <b>up()</b>, or accidentally coding a <b>down()</b> on one semaphore and a <b>up()</b>
on another can have disastrous effects, since mutually exclusive execution would no longer be ensured. Also, when using semaphores, a programmer can forget to include in critical sections all statements that reference shared objects. This, too, could destroy the mutual exclusion required within critical sections. A second difficulty with using semaphores is that both condition synchronization and mutual exclusion are programmed using the same pair of primitives. This makes it difficult to identify the purpose of a given
<b>down()</b> or <b>up()</b> operation without looking at the other operations on the corresponding semaphore. Since mutual exclusion and condition synchronization are distinct concepts, they should have distinct notations.</p>
</blockquote>
<p><b>Historical note: </b>Dijkstra's original name for <b>down()</b> was <b>P</b>
(short for the Dutch &quot;passeren&quot;, &quot;to pass&quot;), and for <b>up()</b>
was <b>V</b> (short for the Dutch &quot;vrygeven&quot;, &quot;to release&quot;).</p>
<h2><a name="Header">Header</a></h2>
<pre>
#include <a href="../../../boost/thread/semaphore.hpp">&lt;boost/thread/semaphore.hpp&gt;</a>
</pre>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>
namespace boost
{
class semaphore : private <a href="../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
// Class semaphore meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
{
public:
explicit semaphore(unsigned count=0, unsigned max=0);
~semaphore();
bool up(unsigned count=1, unsigned* prev=0);
void down();
bool down(const xtime&amp; xt);
private:
unsigned m_count; <i>exposition only [ISO 17.3.2.3/2]
</i> unsigned m_max; <i>exposition only [ISO 17.3.2.3/2]</i>
};
}
</pre>
<h2><a name="Members">Members</a></h2>
<hr>
<h3>Constructor</h3>
<pre>
explicit semaphore(unsigned count=0, unsigned max=0);
</pre>
<p><b>Effects:</b> As if:</p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp; m_count = count;<br>
&nbsp;&nbsp;&nbsp;&nbsp; m_max = (max == 0 ? std::numeric_limits&lt;unsigned&gt;::max()
? max );</code></p>
<hr>
<h3>Destructor</h3>
<pre>
~semaphore();
</pre>
<p><b>Effects:</b> Destroys <code>*this</code>.</p>
<hr>
<h3>up</h3>
<pre>
bool up(unsigned count=1, unsigned* prev=0);
</pre>
<p><b>Effects:</b> As if:</p>
<p><code>&nbsp;&nbsp;&nbsp; unsigned ct;<br>
&nbsp;&nbsp;&nbsp; bool ret;<br>
&nbsp;&nbsp;&nbsp; { // as a single atomic operation:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ct = m_count;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (m_count == m_max) ret =
false;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret =
true;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++m_count;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; if (prev) *prev = m_count;<br>
&nbsp;&nbsp;&nbsp; return ret;</code></p>
<hr>
<h3>down</h3>
<pre>
void down();
</pre>
<p><b>Effects:</b> If <code>m_count == 0</code>, places the current thread in
the <a href="definitions.html#State">blocked</a> state until <code>m_count != 0</code>.
Finally, <code>--m_count</code>.<code>&nbsp;</code></p>
<hr>
<pre>
bool down(const <a href="xtime.html">xtime</a>&amp; xt);
</pre>
<p><b>Effects:</b> If <code>m_count == 0</code>, places the current thread in
the <a href="definitions.html#State">blocked</a> state until <code>m_count != 0</code>
or <code>xt</code> is reached. Finally, <code>--m_count</code>.<code>&nbsp;</code></p>
<p><b>Returns:</b> If xt was reached, true, else false.</p>
<hr>
<h2><a name="Example">Example</a> Usage</h2>
<pre>
#include <a href="../../../boost/thread/semaphore.hpp">&lt;boost/thread/semaphore.hpp&gt;</a>
#include <a href="../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
#include &lt;iostream&gt;
int global_data = 0;
boost::semaphore global_semaphore(1);
void change_global_data(void*)
{
global_semaphore.down();
++global_data;
std::cout &lt;&lt; &quot;global_data == &quot; &lt;&lt; global_data &lt;&lt; std::endl;
global_semaphore.up();
}
int main(int, char*[])
{
const int num_threads = 4;
boost::thread_group thrds;
for (int i=0; i &lt; num_threads; ++i)
thrds.create_thread(&amp;change_global_data, 0);
thrds.join_all();
return 0;
}
</pre>
<p>The output is:</p>
<pre>
global_data == 1
global_data == 2
global_data == 3
global_data == 4
</pre>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <A href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html>

44
doc/shared_mutex_ref.qbk Normal file
View File

@@ -0,0 +1,44 @@
[/
(C) Copyright 2007-8 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).
]
[section:shared_mutex Class `shared_mutex`]
#include <boost/thread/shared_mutex.hpp>
class shared_mutex
{
public:
shared_mutex();
~shared_mutex();
void lock_shared();
bool try_lock_shared();
bool timed_lock_shared(system_time const& timeout);
void unlock_shared();
void lock();
bool try_lock();
bool timed_lock(system_time const& timeout);
void unlock();
void lock_upgrade();
void unlock_upgrade();
void unlock_upgrade_and_lock();
void unlock_and_lock_upgrade();
void unlock_and_lock_shared();
void unlock_upgrade_and_lock_shared();
};
The class `boost::shared_mutex` provides an implementation of a multiple-reader / single-writer mutex. It implements the
__upgrade_lockable_concept__.
Multiple concurrent calls to __lock_ref__, __try_lock_ref__, __timed_lock_ref__, __lock_shared_ref__, __try_lock_shared_ref__ and
__timed_lock_shared_ref__ shall be permitted.
[endsect]

View File

@@ -1,4 +0,0 @@
PRE
{
BACKGROUND-COLOR: lightcyan
}

View File

@@ -1,254 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, Boost.Threads, thread library, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost.Threads, thread</title>
</head>
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><IMG height=86 alt="C++ Boost" src="../../../c++boost.gif" width=277></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Class thread</h2>
</td>
</tr>
</table>
<hr>
<p><A href="#Introduction">Introduction</A><br>
<A href="#Header">Header</A><br>
<A href="#Synopsis">Synopsis</A><br>
<A href="#Members">Members</A><br>
<A href="#Example">Example</A></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <code>thread</code> class represents threads of execution, and provides
the functionality to create and manage threads within the <b>Boost.Threads</b>
library. See <A href="definitions.html">Definitions</A> for a precise description of
"thread of execution", and for definitions of threading related terms and of thread
states such as "blocked".</p>
<p>A thread of execution has an initial function. For the program's
initial thread, the initial function is <code>main()</code>. For other
threads, the initial function is <code>operator()</code> of the function object
passed to the class <code>thread</code> constructor.</p>
<p>A thread of execution is said to be "finished" or "finished execution" when its
initial function returns or is terminated. This includes completion of all thread
cleanup handlers, and completion of the normal C++ function return behaviors, such
as destruction of automatic storage (stack) objects and releasing any associated
implementation resources.</p>
<p>A thread object has an associated state which is either "joinable" or
"non-joinable".</p>
<p>Except as described below, the policy used by an implementation of
<b>Boost.Threads</b> to schedule transitions between thread states is unspecified.</p>
<p><b>Note: </b>Just as the lifetime of a file may be different from the
lifetime of an iostream object which represents the file, the lifetime of a
thread of execution may be different from the <code>thread</code> object which
represents the thread of execution. In particular, after a call to <code>join()</code>,
the thread of execution will no longer exist even though the <code>thread</code>
object continues to exist until the end of its normal lifetime. The
converse is also possible; if a <code>thread</code> object is destroyed without
<code>join()</code> having first been called, the thread of execution continues until
its initial function completes.</p>
<h2><a name="Header">Header</a></h2>
<pre>
#include <A href="../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</A>
</pre>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>
namespace boost {
class thread : <a href="../../utility/utility.htm#noncopyable">boost::noncopyable</a> // Exposition only.
// Class thread meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
{
public:
thread();
explicit thread(const boost::function0&lt;void&gt;&amp; threadfunc);
~thread();
bool operator==(const thread&amp; rhs) const;
bool operator!=(const thread&amp; rhs) const;
void join();
static void sleep(const xtime&amp; xt);
static void yield();
};
} // namespace boost
</pre>
<h2><a name="Members">Members</a></h2>
<hr>
<h3>Constructors</h3>
<pre>
thread();
</pre>
<p><b>Effects:</b> Constructs a <code>thread</code> object representing the current thread
of execution.</p>
<p><b>Postcondition:</b> <code>*this</code> is non-joinable.</p>
<p><b>Danger:</b> <code>*this</code> is valid only within the current thread.</p>
<pre>
thread(const <A href="../../function/index.html">boost::function0</A>&lt;void&gt;&amp; threadfunc);
</pre>
<p><b>Effects:</b> Starts a new thread of execution and constructs a <code>thread</code> object
representing it. Copies <code>threadfunc</code>
(which in turn copies the function object wrapped by <code>threadfunc</code>) to an
internal location which persists for the lifetime of the new thread of execution. Calls
<code>operator()</code> on the copy of the <code>threadfunc</code> function object in
the new thread of execution.</p>
<p><b>Postcondition:</b> <code>*this</code> is joinable.</p>
<p><b>Throws:</b> <code>boost::thread_resource_error</code> if a new thread of execution
cannot be started.</p>
<hr>
<h3>Destructor</h3>
<pre>
~thread();
</pre>
<p><b>Effects:</b> Destroys <code>*this</code>. The actual thread of execution may
continue to execute after the <code>thread</code> object has been destroyed.</p>
<p><b>Notes:</b> If <code>*this</code> is joinable the actual thread of execution
becomes "detached". Any resources used by the thread will be reclaimed when the
thread of execution completes. To ensure such a thread of execution runs to completion
before the <code>thread</code> object is destroyed, call <code>join()</code>.</p>
<hr>
<h3>Comparison Operators</h3>
<pre>
bool operator==(const thread&amp; rhs);
</pre>
<p><b>Requires:</b> The thread is non-terminated or <code>*this</code> is joinable.</p>
<p><b>Returns:</b> <code>true</code> if <code>*this</code> and <code>rhs</code>
represent the same thread of execution.</p>
<pre>
bool operator!=(const thread&amp; rhs);
</pre>
<p><b>Returns:</b> <code>!(*this==rhs)</code>.</p>
<hr>
<h3>join</h3>
<pre>
void join();
</pre>
<p><b>Requires:</b> <code>*this</code> is joinable.</p>
<p><b>Effects:</b> The current thread of execution blocks until the initial function of
the thread of execution represented by <code>*this</code> finishes and all resources
are reclaimed.</p>
<p><b>Postcondition:</b> <code>*this</code> is non-joinable.</p>
<p><b>Note:</b></p> If <code>*this == thread()</code> the result is implementation defined.
If the implementation doesn't detect this the result will be
<a href="definitions.html#Deadlock">deadlock</a>.</p>
<hr>
<h3>sleep</h3>
<pre>
static void sleep(const <a href="xtime.html">xtime</a>&amp; xt);
</pre>
<p><b>Effects:</b> The current thread of execution blocks until <code>xt</code> is
reached.</p>
<hr>
<h3>yield</h3>
<pre>
static void yield();
</pre>
<p><b>Effects:</b> The current thread of execution is placed in the "ready" state.</p>
<p><b>Notes:</b> Allow the current thread to give up the rest of its time slice
(or other scheduling quota) to another thread. Particularly useful in non-preemptive
implementations.</p>
<hr>
<h2><a name="Example">Example Usage</a></h2>
<pre>
#include &lt;boost/thread/thread.hpp&gt;
#include &lt;iostream&gt;
struct thread_alarm
{
thread_alarm(int secs) : m_secs(secs) { }
void operator()()
{
boost::xtime xt;
boost::xtime_get(&amp;xt, boost::TIME_UTC);
xt.sec += m_secs;
boost::thread::sleep(xt);
std::cout &lt;&lt; &quot;alarm sounded...&quot; &lt;&lt; std::endl;
}
int m_secs;
};
int main(int argc, char* argv[])
{
int secs = 5;
std::cout &lt;&lt; &quot;setting alarm for 5 seconds...&quot; &lt;&lt; std::endl;
boost::thread thrd(thread_alarm(secs));
thrd.join();
}
</pre>
<p>The output is:</p>
<pre>
setting alarm for 5 seconds...
alarm sounded...
</pre>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <A href="mailto:williamkempf@hotmail.com">William E. Kempf</A>
2001 all rights reserved.</i></p>
</body>
</html>

167
doc/thread.qbk Normal file
View File

@@ -0,0 +1,167 @@
[/
(C) Copyright 2007-8 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).
]
[article Thread
[quickbook 1.4]
[authors [Williams, Anthony]]
[copyright 2007-8 Anthony Williams]
[purpose C++ Library for launching threads and synchronizing data between them]
[category text]
[license
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
[@http://www.boost.org/LICENSE_1_0.txt])
]
]
[template lockable_concept_link[link_text] [link thread.synchronization.mutex_concepts.lockable [link_text]]]
[def __lockable_concept__ [lockable_concept_link `Lockable` concept]]
[def __lockable_concept_type__ [lockable_concept_link `Lockable`]]
[template timed_lockable_concept_link[link_text] [link thread.synchronization.mutex_concepts.timed_lockable [link_text]]]
[def __timed_lockable_concept__ [timed_lockable_concept_link `TimedLockable` concept]]
[def __timed_lockable_concept_type__ [timed_lockable_concept_link `TimedLockable`]]
[template shared_lockable_concept_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable [link_text]]]
[def __shared_lockable_concept__ [shared_lockable_concept_link `SharedLockable` concept]]
[def __shared_lockable_concept_type__ [shared_lockable_concept_link `SharedLockable`]]
[template upgrade_lockable_concept_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable [link_text]]]
[def __upgrade_lockable_concept__ [upgrade_lockable_concept_link `UpgradeLockable` concept]]
[def __upgrade_lockable_concept_type__ [upgrade_lockable_concept_link `UpgradeLockable`]]
[template lock_ref_link[link_text] [link thread.synchronization.mutex_concepts.lockable.lock [link_text]]]
[def __lock_ref__ [lock_ref_link `lock()`]]
[template lock_multiple_ref_link[link_text] [link thread.synchronization.lock_functions.lock_multiple [link_text]]]
[def __lock_multiple_ref__ [lock_multiple_ref_link `lock()`]]
[template try_lock_multiple_ref_link[link_text] [link thread.synchronization.lock_functions.try_lock_multiple [link_text]]]
[def __try_lock_multiple_ref__ [try_lock_multiple_ref_link `try_lock()`]]
[template unlock_ref_link[link_text] [link thread.synchronization.mutex_concepts.lockable.unlock [link_text]]]
[def __unlock_ref__ [unlock_ref_link `unlock()`]]
[template try_lock_ref_link[link_text] [link thread.synchronization.mutex_concepts.lockable.try_lock [link_text]]]
[def __try_lock_ref__ [try_lock_ref_link `try_lock()`]]
[template timed_lock_ref_link[link_text] [link thread.synchronization.mutex_concepts.timed_lockable.timed_lock [link_text]]]
[def __timed_lock_ref__ [timed_lock_ref_link `timed_lock()`]]
[template timed_lock_duration_ref_link[link_text] [link thread.synchronization.mutex_concepts.timed_lockable.timed_lock_duration [link_text]]]
[def __timed_lock_duration_ref__ [timed_lock_duration_ref_link `timed_lock()`]]
[template lock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.lock_shared [link_text]]]
[def __lock_shared_ref__ [lock_shared_ref_link `lock_shared()`]]
[template unlock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.unlock_shared [link_text]]]
[def __unlock_shared_ref__ [unlock_shared_ref_link `unlock_shared()`]]
[template try_lock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.try_lock_shared [link_text]]]
[def __try_lock_shared_ref__ [try_lock_shared_ref_link `try_lock_shared()`]]
[template timed_lock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.timed_lock_shared [link_text]]]
[def __timed_lock_shared_ref__ [timed_lock_shared_ref_link `timed_lock_shared()`]]
[template timed_lock_shared_duration_ref_link[link_text] [link thread.synchronization.mutex_concepts.shared_lockable.timed_lock_shared_duration [link_text]]]
[def __timed_lock_shared_duration_ref__ [timed_lock_shared_duration_ref_link `timed_lock_shared()`]]
[template lock_upgrade_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.lock_upgrade [link_text]]]
[def __lock_upgrade_ref__ [lock_upgrade_ref_link `lock_upgrade()`]]
[template unlock_upgrade_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_upgrade [link_text]]]
[def __unlock_upgrade_ref__ [unlock_upgrade_ref_link `unlock_upgrade()`]]
[template unlock_upgrade_and_lock_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_upgrade_and_lock [link_text]]]
[def __unlock_upgrade_and_lock_ref__ [unlock_upgrade_and_lock_ref_link `unlock_upgrade_and_lock()`]]
[template unlock_and_lock_upgrade_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_and_lock_upgrade [link_text]]]
[def __unlock_and_lock_upgrade_ref__ [unlock_and_lock_upgrade_ref_link `unlock_and_lock_upgrade()`]]
[template unlock_upgrade_and_lock_shared_ref_link[link_text] [link thread.synchronization.mutex_concepts.upgrade_lockable.unlock_upgrade_and_lock_shared [link_text]]]
[def __unlock_upgrade_and_lock_shared_ref__ [unlock_upgrade_and_lock_shared_ref_link `unlock_upgrade_and_lock_shared()`]]
[template owns_lock_ref_link[link_text] [link thread.synchronization.locks.unique_lock.owns_lock [link_text]]]
[def __owns_lock_ref__ [owns_lock_ref_link `owns_lock()`]]
[template owns_lock_shared_ref_link[link_text] [link thread.synchronization.locks.shared_lock.owns_lock [link_text]]]
[def __owns_lock_shared_ref__ [owns_lock_shared_ref_link `owns_lock()`]]
[template mutex_func_ref_link[link_text] [link thread.synchronization.locks.unique_lock.mutex [link_text]]]
[def __mutex_func_ref__ [mutex_func_ref_link `mutex()`]]
[def __boost_thread__ [*Boost.Thread]]
[def __not_a_thread__ ['Not-a-Thread]]
[def __interruption_points__ [link interruption_points ['interruption points]]]
[def __mutex__ [link thread.synchronization.mutex_types.mutex `boost::mutex`]]
[def __try_mutex__ [link thread.synchronization.mutex_types.try_mutex `boost::try_mutex`]]
[def __timed_mutex__ [link thread.synchronization.mutex_types.timed_mutex `boost::timed_mutex`]]
[def __recursive_mutex__ [link thread.synchronization.mutex_types.recursive_mutex `boost::recursive_mutex`]]
[def __recursive_try_mutex__ [link thread.synchronization.mutex_types.recursive_try_mutex `boost::recursive_try_mutex`]]
[def __recursive_timed_mutex__ [link thread.synchronization.mutex_types.recursive_timed_mutex `boost::recursive_timed_mutex`]]
[def __shared_mutex__ [link thread.synchronization.mutex_types.shared_mutex `boost::shared_mutex`]]
[template unique_lock_link[link_text] [link thread.synchronization.locks.unique_lock [link_text]]]
[def __lock_guard__ [link thread.synchronization.locks.lock_guard `boost::lock_guard`]]
[def __unique_lock__ [unique_lock_link `boost::unique_lock`]]
[def __shared_lock__ [link thread.synchronization.locks.shared_lock `boost::shared_lock`]]
[def __upgrade_lock__ [link thread.synchronization.locks.upgrade_lock `boost::upgrade_lock`]]
[def __upgrade_to_unique_lock__ [link thread.synchronization.locks.upgrade_to_unique_lock `boost::upgrade_to_unique_lock`]]
[def __thread__ [link thread.thread_management.thread `boost::thread`]]
[def __thread_id__ [link thread.thread_management.thread.id `boost::thread::id`]]
[template join_link[link_text] [link thread.thread_management.thread.join [link_text]]]
[def __join__ [join_link `join()`]]
[template timed_join_link[link_text] [link thread.thread_management.thread.timed_join [link_text]]]
[def __timed_join__ [timed_join_link `timed_join()`]]
[def __detach__ [link thread.thread_management.thread.detach `detach()`]]
[def __interrupt__ [link thread.thread_management.thread.interrupt `interrupt()`]]
[def __sleep__ [link thread.thread_management.this_thread.sleep `boost::this_thread::sleep()`]]
[def __interruption_enabled__ [link thread.thread_management.this_thread.interruption_enabled `boost::this_thread::interruption_enabled()`]]
[def __interruption_requested__ [link thread.thread_management.this_thread.interruption_requested `boost::this_thread::interruption_requested()`]]
[def __interruption_point__ [link thread.thread_management.this_thread.interruption_point `boost::this_thread::interruption_point()`]]
[def __disable_interruption__ [link thread.thread_management.this_thread.disable_interruption `boost::this_thread::disable_interruption`]]
[def __restore_interruption__ [link thread.thread_management.this_thread.restore_interruption `boost::this_thread::restore_interruption`]]
[def __thread_resource_error__ `boost::thread_resource_error`]
[def __thread_interrupted__ `boost::thread_interrupted`]
[def __barrier__ [link thread.synchronization.barriers.barrier `boost::barrier`]]
[template cond_wait_link[link_text] [link thread.synchronization.condvar_ref.condition_variable.wait [link_text]]]
[def __cond_wait__ [cond_wait_link `wait()`]]
[template cond_timed_wait_link[link_text] [link thread.synchronization.condvar_ref.condition_variable.timed_wait [link_text]]]
[def __cond_timed_wait__ [cond_timed_wait_link `timed_wait()`]]
[template cond_any_wait_link[link_text] [link thread.synchronization.condvar_ref.condition_variable_any.wait [link_text]]]
[def __cond_any_wait__ [cond_any_wait_link `wait()`]]
[template cond_any_timed_wait_link[link_text] [link thread.synchronization.condvar_ref.condition_variable_any.timed_wait [link_text]]]
[def __cond_any_timed_wait__ [cond_any_timed_wait_link `timed_wait()`]]
[def __blocked__ ['blocked]]
[include overview.qbk]
[include changes.qbk]
[include thread_ref.qbk]
[section:synchronization Synchronization]
[include mutex_concepts.qbk]
[include mutexes.qbk]
[include condition_variables.qbk]
[include once.qbk]
[include barrier.qbk]
[endsect]
[include tss.qbk]
[include time.qbk]
[include acknowledgements.qbk]

View File

@@ -1,187 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost.Threads, thread_group</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">thread_group</h2>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br>
<a href="#Header">Header</a><br>
<a href="#Synopsis">Synopsis</a><br>
<a href="#Members">Members</a><br>
<a href="#Example">Example</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <tt>thread_group</tt> class provides a container for easy grouping of threads to simplify several
common thread creation and management idioms.</p>
<p>All <tt>thread_group</tt> member functions are <a href="definitions.html#thread-safe">thread-safe</a>,
except destruction.</p>
<h2><a name="Header">Header</a></h2>
<pre>
#include <a href="../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
</pre>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>
namespace boost
{
class thread_group : <a href="../../utility/utility.htm#noncopyable">boost::noncopyable</a>
{
public:
thread_group();
~thread_group();
thread* create_thread(const boost::function0&lt;void&gt;&amp; threadfunc);
void add_thread(thread* thrd);
void remove_thread(thread* thrd);
void join_all();
};
}
</pre>
<h2><a name="Members">Members</a></h2>
<hr>
<h3>Constructor</h3>
<pre>
thread_group();
</pre>
<p><b>Effects:</b> Constructs an empty <tt>thread_group</tt> container.</p>
<hr>
<h3>Destructor</h3>
<pre>
~thread_group();
</pre>
<p><b>Effects:</b> Destroys each contained thread object.&nbsp; Destroys <code>*this</code>.</p>
<p><b>Notes:</b> Behavior is undefined if another thread references *this during
the execution of the destructor.</p>
<hr>
<h3>create_thread</h3>
<pre>
thread* create_thread(const boost::function0&lt;void&gt;&amp; threadfunc);
</pre>
<p><b>Effects:</b> Creates a new <tt>thread</tt> object that executes <tt>threadfunc</tt> and adds it to the
<tt>thread_group</tt> container object's list of managed <tt>thread</tt> objects.</p>
<p><b>Returns:</b> Pointer to the newly created thread.</p>
<hr>
<h3>add_thread</h3>
<pre>
void add_thread(thread* thrd);
</pre>
<p><b>Effects:</b> Adds <tt>thrd</tt> to the <tt>thread_group</tt> object's list of managed <tt>thread</tt>
objects. The <tt>thrd</tt> object must have been allocated via operator new and will
be deleted when the group is destroyed.</p>
<hr>
<h3>remove_thread</h3>
<pre>
void remove_thread(thread* thrd);
</pre>
<p><b>Effects:</b> Removes <code>*this</code>'s list of managed <tt>thread</tt>
objects.</p>
<p><b>Throws: </b>? if <tt>thrd</tt> is not it <code>*this</code>'s list of managed <tt>thread</tt>
objects.</p>
<hr>
<h3>join_all</h3>
<pre>
void join_all();
</pre>
<p><b>Effects:</b> Calls <code> join()</code> on each of the managed <tt>thread</tt> objects.</p>
<hr>
<h2><a name="Example">Example</a> Usage</h2>
<pre>
#include &lt;boost/thread/thread.hpp&gt;
#include &lt;iostream&gt;
int count = 0;
boost::mutex mutex;
void increment_count()
{
boost::mutex::lock lock(mutex);
std::cout &lt;&lt; &quot;count = &quot; &lt;&lt; ++count &lt;&lt; std::endl;
}
int main(int argc, char* argv[])
{
boost::thread_group threads;
for (int i = 0; i &lt; 10; ++i)
threads.create_thread(&amp;increment_count);
threads.join_all();
}
</pre>
<p>The output is:</p>
<pre>
count = 1
count = 2
count = 3
count = 4
count = 5
count = 6
count = 7
count = 8
count = 9
count = 10
</pre>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html>

1064
doc/thread_ref.qbk Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,80 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost.Threads, thread_resource_error</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">thread_resource_error</h2>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br>
<a href="#Header">Header</a><br>
<a href="#Synopsis">Synopsis</a><br>
<a href="#Members">Members</a><br>
<a href="#Example">Example</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <code>thread_resource_error</code> class defines an exception type that is thrown
by constructors in the <b>Boost.Threads</b> library when thread related resources
can not be
acquired. This does not include memory allocation failures which instead throw
std::bad_alloc.</p>
<h2><a name="Header">Header</a></h2>
<pre>
#include <a href="../../../boost/thread/thread.hpp">&lt;boost/thread/exceptions.hpp&gt;</a>
</pre>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>
namespace boost
{
class thread_resource_error : public std::runtime_error
{
public:
thread_resource_error();
};
}
</pre>
<h2><a name="Members">Members</a></h2>
<hr>
<h3>Constructor</h3>
<pre>
thread_resource_error();
</pre>
<p>Constructs a <code>thread_resource_error</code> object.</p>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,214 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, Boost.Threads, thread library, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost.Threads, thread_specific_ptr</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">thread_specific_ptr</h2>
</td>
</tr>
</table>
<hr>
<p><A href="#Introduction">Introduction</A><br>
<A href="#Header">Header</A><br>
<A href="#Synopsis">Synopsis</A><br>
<A href="#Members">Members</A><br>
<A href="#Example">Example</A></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <code>thread_specific_ptr</code> class defines an interface for using thread
specific storage. Thread specific storage is data associated with individual threads
and is often used to make operations
<a href="definitions.html#Thread-safe">thread-safe</a> that rely on global data.</p>
<p>Template <code>thread_specific_ptr</code> stores a pointer to an object obtained via
<code>new</code> on a thread-by-thread basis and calls delete on the contained pointer
when the thread terminates. Each thread initially stores the null pointer in each
<code>thread_specific_ptr</code> instance.</p>
<p>The template <code>thread_specific_ptr</code> is useful in the following cases:</p>
<ul>
<li>An interface was original written assuming a single thread of control and is
being ported to a multi-threaded environment.</li>
<li>Each thread of control invokes sequences of methods that share data that must be
logically accessed through a globally visible access point, but are physically
unique for each thread, instead of being explicitly passed.</li>
</ul>
<h2><a name="Header">Header</a></h2>
<pre>
#include <a href="../../../boost/thread/tss.hpp">&lt;boost/thread/tss.hpp&gt;</a>
</pre>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>
namespace boost {
template &lt;typename T&gt;
class thread_specific_ptr : private boost::noncopyable // Exposition only.
// Class thread_specific_ptr meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
{
public:
thread_specific_ptr();
~thread_specific_ptr();
T* get() const;
T* operator-&gt;() const;
T&amp; operator*() const;
T* release();
void reset(T* p=0);
};
} // namespace boost
</pre>
<h2><a name="Members">Members</a></h2>
<hr>
<h3>Constructor</h3>
<pre>
thread_specific_ptr();
</pre>
<p><b>Postconditions:</b> A thread specific storage has been reserved for use by *this
in all threads, with each thread initially storing a null pointer.</p>
<p><b>Requires:</b> The expression <code>delete get()</code> is well formed.</p>
<p><b>Throws:</b> <code>boost::thread_resource_error</code> if the necessary resources
can not be obtained.</p>
<p><b>Notes:</b> There is an implementation specific limit to the number of thread
specific storage objects that can be created, and this limit may be small.</p>
<hr>
<h3>Destructor</h3>
<pre>
~thread_specific_ptr();
</pre>
<p><b>Notes:</b> Does not destroy any data that may be stored in any thread's thread
specific storage. For this reason you should not destroy a
<code>thread_specific_ptr</code> object until you are certain there are no threads
running that have made use of its thread specific storage.</p>
<hr>
<h3>get</h3>
<pre>
T* get() const;
</pre>
<p><b>Returns:</b> The object stored in thread specific storage for the current thread
for *this.</p>
<p><b>Notes:</b> Each thread initially returns 0.</p>
<hr>
<h3>Smart Pointer Operations</h3>
<pre>
T* operator-&gt;() const;
</pre>
<p><b>Returns:</b> <code>get()</code></p>
<pre>
T&amp; operator*() const;
</pre>
<p><b>Returns:</b> <code>get()</code></p>
<p><b>Requires:</b> <code>get() != 0</code></p>
<hr>
<h3>Release</h3>
<pre>
T* release();
</pre>
<p><b>Returns:</b> <code>get()</code></p>
<p><b>Postcondition:</b> *this holds the null pointer for the current thread.</p>
<hr>
<h3>Reset</h3>
<pre>
void reset(T* p=0);
</pre>
<p><b>Effects:</b> If <code>get()!= p</code> then <code>delete get()</code>.</p>
<p><b>Postconditions:</b> <code>*this</code> holds the pointer <code>p</code> for
the current thread.</p>
<p><b>Notes:</b> The pointer will be deleted when the thread terminates.</p>
<hr>
<h2><a name="Example">Example Usage</a></h2>
<pre>
#include <a href="../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
#include <a href="../../../boost/thread/tss.hpp">&lt;boost/thread/tss.hpp&gt;</a>
#include &lt;cassert&gt;
boost::thread_specific_ptr&lt;int&gt; value;
void increment()
{
int* p = value.get();
++*p;
}
void thread_proc()
{
value.reset(new int(0)); // initialize the thread's storage
for (int i=0; i&lt;10; ++i)
{
increment();
int* p = value.get();
assert(*p == i+1);
}
}
int main(int argc, char* argv[])
{
boost::thread_group threads;
for (int i=0; i&lt;5; ++i)
threads.create_thread(&amp;thread_proc);
threads.join_all();
}
</pre>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html>

75
doc/time.qbk Normal file
View File

@@ -0,0 +1,75 @@
[/
(C) Copyright 2007-8 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).
]
[section:time Date and Time Requirements]
As of Boost 1.35.0, the __boost_thread__ library uses the [link date_time Boost.Date_Time] library for all operations that require a
time out. These include (but are not limited to):
* __sleep__
* __timed_join__
* __cond_timed_wait__
* __timed_lock_ref__
For the overloads that accept an absolute time parameter, an object of type [link thread.time.system_time `boost::system_time`] is
required. Typically, this will be obtained by adding a duration to the current time, obtained with a call to [link
thread.time.get_system_time `boost::get_system_time()`]. e.g.
boost::system_time const timeout=boost::get_system_time() + boost::posix_time::milliseconds(500);
extern bool done;
extern boost::mutex m;
extern boost::condition_variable cond;
boost::unique_lock<boost::mutex> lk(m);
while(!done)
{
if(!cond.timed_wait(lk,timeout))
{
throw "timed out";
}
}
For the overloads that accept a ['TimeDuration] parameter, an object of any type that meets the [link
date_time.posix_time.time_duration Boost.Date_Time Time Duration requirements] can be used, e.g.
boost::this_thread::sleep(boost::posix_time::milliseconds(25));
boost::mutex m;
if(m.timed_lock(boost::posix_time::nanoseconds(100)))
{
// ...
}
[section:system_time Typedef `system_time`]
#include <boost/thread/thread_time.hpp>
typedef boost::posix_time::ptime system_time;
See the documentation for [link date_time.posix_time.ptime_class `boost::posix_time::ptime`] in the Boost.Date_Time library.
[endsect]
[section:get_system_time Non-member function `get_system_time()`]
#include <boost/thread/thread_time.hpp>
system_time get_system_time();
[variablelist
[[Returns:] [The current time.]]
[[Throws:] [Nothing.]]
]
[endsect]
[endsect]

184
doc/tss.qbk Normal file
View File

@@ -0,0 +1,184 @@
[/
(C) Copyright 2007-8 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).
]
[section Thread Local Storage]
[heading Synopsis]
Thread local storage allows multi-threaded applications to have a separate instance of a given data item for each thread. Where a
single-threaded application would use static or global data, this could lead to contention, deadlock or data corruption in a
multi-threaded application. One example is the C `errno` variable, used for storing the error code related to functions from the
Standard C library. It is common practice (and required by POSIX) for compilers that support multi-threaded applications to provide
a separate instance of `errno` for each thread, in order to avoid different threads competing to read or update the value.
Though compilers often provide this facility in the form of extensions to the declaration syntax (such as `__declspec(thread)` or
`__thread` annotations on `static` or namespace-scope variable declarations), such support is non-portable, and is often limited in
some way, such as only supporting POD types.
[heading Portable thread-local storage with `boost::thread_specific_ptr`]
`boost::thread_specific_ptr` provides a portable mechanism for thread-local storage that works on all compilers supported by
__boost_thread__. Each instance of `boost::thread_specific_ptr` represents a pointer to an object (such as `errno`) where each
thread must have a distinct value. The value for the current thread can be obtained using the `get()` member function, or by using
the `*` and `->` pointer deference operators. Initially the pointer has a value of `NULL` in each thread, but the value for the
current thread can be set using the `reset()` member function.
If the value of the pointer for the current thread is changed using `reset()`, then the previous value is destroyed by calling the
cleanup routine. Alternatively, the stored value can be reset to `NULL` and the prior value returned by calling the `release()`
member function, allowing the application to take back responsibility for destroying the object.
[heading Cleanup at thread exit]
When a thread exits, the objects associated with each `boost::thread_specific_ptr` instance are destroyed. By default, the object
pointed to by a pointer `p` is destroyed by invoking `delete p`, but this can be overridden for a specific instance of
`boost::thread_specific_ptr` by providing a cleanup routine to the constructor. In this case, the object is destroyed by invoking
`func(p)` where `func` is the cleanup routine supplied to the constructor. The cleanup functions are called in an unspecified
order. If a cleanup routine sets the value of associated with an instance of `boost::thread_specific_ptr` that has already been
cleaned up, that value is added to the cleanup list. Cleanup finishes when there are no outstanding instances of
`boost::thread_specific_ptr` with values.
[section:thread_specific_ptr Class `thread_specific_ptr`]
#include <boost/thread/tss.hpp>
template <typename T>
class thread_specific_ptr
{
public:
thread_specific_ptr();
explicit thread_specific_ptr(void (*cleanup_function)(T*));
~thread_specific_ptr();
T* get() const;
T* operator->() const;
T& operator*() const;
T* release();
void reset(T* new_value=0);
};
[section:default_constructor `thread_specific_ptr();`]
[variablelist
[[Requires:] [`delete this->get()` is well-formed.]]
[[Effects:] [Construct a `thread_specific_ptr` object for storing a pointer to an object of type `T` specific to each thread. The
default `delete`-based cleanup function will be used to destroy any thread-local objects when `reset()` is called, or the thread
exits.]]
[[Throws:] [`boost::thread_resource_error` if an error occurs.]]
]
[endsect]
[section:constructor_with_custom_cleanup `explicit thread_specific_ptr(void (*cleanup_function)(T*));`]
[variablelist
[[Requires:] [`cleanup_function(this->get())` does not throw any exceptions.]]
[[Effects:] [Construct a `thread_specific_ptr` object for storing a pointer to an object of type `T` specific to each thread. The
supplied `cleanup_function` will be used to destroy any thread-local objects when `reset()` is called, or the thread exits.]]
[[Throws:] [`boost::thread_resource_error` if an error occurs.]]
]
[endsect]
[section:destructor `~thread_specific_ptr();`]
[variablelist
[[Effects:] [Calls `this->reset()` to clean up the associated value for the current thread, and destroys `*this`.]]
[[Throws:] [Nothing.]]
]
[note Care needs to be taken to ensure that any threads still running after an instance of `boost::thread_specific_ptr` has been
destroyed do not call any member functions on that instance.]
[endsect]
[section:get `T* get() const;`]
[variablelist
[[Returns:] [The pointer associated with the current thread.]]
[[Throws:] [Nothing.]]
]
[note The initial value associated with an instance of `boost::thread_specific_ptr` is `NULL` for each thread.]
[endsect]
[section:operator_arrow `T* operator->() const;`]
[variablelist
[[Returns:] [`this->get()`]]
[[Throws:] [Nothing.]]
]
[endsect]
[section:operator_star `T& operator*() const;`]
[variablelist
[[Requires:] [`this->get` is not `NULL`.]]
[[Returns:] [`*(this->get())`]]
[[Throws:] [Nothing.]]
]
[endsect]
[section:reset `void reset(T* new_value=0);`]
[variablelist
[[Effects:] [If `this->get()!=new_value` and `this->get()` is non-`NULL`, invoke `delete this->get()` or
`cleanup_function(this->get())` as appropriate. Store `new_value` as the pointer associated with the current thread.]]
[[Postcondition:] [`this->get()==new_value`]]
[[Throws:] [`boost::thread_resource_error` if an error occurs.]]
]
[endsect]
[section:release `T* release();`]
[variablelist
[[Effects:] [Return `this->get()` and store `NULL` as the pointer associated with the current thread without invoking the cleanup
function.]]
[[Postcondition:] [`this->get()==0`]]
[[Throws:] [Nothing.]]
]
[endsect]
[endsect]
[endsect]

View File

@@ -1,141 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, Boost.Threads, thread library, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost.Threads, xtime</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width="277" height="86"></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">xtime</h2>
</td>
</tr>
</table>
<hr>
<p><A href="#Introduction">Introduction</A><br>
<A href="#Header">Header</A><br>
<A href="#Synopsis">Synopsis</A><br>
<A href="#Reference">Reference</A><br>
<A href="#Example">Example</A></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <code>xtime</code> type is used to represent a point on some time scale or
a duration in time. This type may be proposed for the C standard by Markus Kuhn.
<b>Boost.Threads</b> provides only a very minimal implementation of this proposal
and it's expected that a full implementation will be provided in Boost as a separate
library, at which time <b>Boost.Threads</b> will deprecate its implementation.</p>
<h2><a name="Header">Header</a></h2>
<pre>
#include <a href="../../../boost/thread/xtime.hpp">&lt;boost/thread/xtime.hpp&gt;</a>
</pre>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>
namespace boost {
enum
{
TIME_UTC=1,
};
struct xtime
{
#if defined(BOOST_NO_INT64_T)
int_fast32_t sec;
#else
int_fast64_t sec;
#endif
int_fast32_t nsec;
};
int xtime_get(struct xtime* xtp, int clock_type);
} // namespace boost
</pre>
<h2><a name="Reference">Reference</a></h2>
<hr>
<h3>TIME_UTC</h3>
<p>The clock type for Coordinated Universal Time (UTC). The epoch for this clock type
is 1970-01-01 00:00:00. This is the only clock type supported by <b>Boost.Threads</b>.</p>
<hr>
<h3>xtime</h3>
<pre>
struct xtime
{
#if defined(BOOST_NO_INT64_T)
int_fast32_t sec;
#else
int_fast64_t sec;
#endif
int_fast32_t nsec;
};
</pre>
<p><b>sec</b> represents the whole seconds that have passed since the epoch.</p>
<p><b>nsec</b> represents the nanoseconds since <code>sec.</code>
<hr>
<h3>xtime_get</h3>
<pre>
int xtime_get(struct xtime* xtp, int clock_type);
</pre>
<p><b>Postcondition:</b> <code>xtp</code> represents the current point in time
as a duration since the epoch specified by the <code>clock_type</code>.</p>
<p><b>Returns:</b> <code>clock_type</code> if successful, otherwise 0.
<p><b>Notes:</b> The resolution is implementation specific. For many
implementations the best resolution of time is far more than one nanosecond, and
even when the resolution is reasonably good, the latency of a call to <code>xtime_get()</code>
may be significant. For maximum portability, avoid durations of less than
one second.</p>
<hr>
<h2><a name="Example">Example Usage</a></h2>
<pre>
#include <a href="../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
#include <a href="../../../boost/thread/tss.hpp">&lt;boost/thread/xtime.hpp&gt;</a>
int main(int argc, char* argv[])
{
boost::xtime xt;
boost::xtime_get(&amp;xt, boost::TIME_UTC);
xt.sec += 1;
boost::thread::sleep(xt); // Sleep for 1 second
}
</pre>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 October, 2001<!--webbot bot="Timestamp" endspan i-checksum="38291" -->
</p>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html>

View File

23
example/Jamfile.v2 Normal file
View File

@@ -0,0 +1,23 @@
# Copyright (C) 2001-2003
# William E. Kempf
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
project boost/thread/example
: requirements <library>../build//boost_thread <threading>multi
;
exe monitor : monitor.cpp ;
exe starvephil : starvephil.cpp ;
exe tennis : tennis.cpp ;
exe condition : condition.cpp ;
exe mutex : mutex.cpp ;
exe once : once.cpp ;
exe recursive_mutex : recursive_mutex.cpp ;
exe thread : thread.cpp ;
exe thread_group : thread_group.cpp ;
exe tss : tss.cpp ;
exe xtime : xtime.cpp ;

82
example/condition.cpp Normal file
View File

@@ -0,0 +1,82 @@
// 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)
#include <iostream>
#include <vector>
#include <boost/utility.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/thread.hpp>
class bounded_buffer : private boost::noncopyable
{
public:
typedef boost::mutex::scoped_lock lock;
bounded_buffer(int n) : begin(0), end(0), buffered(0), circular_buf(n) { }
void send (int m) {
lock lk(monitor);
while (buffered == circular_buf.size())
buffer_not_full.wait(lk);
circular_buf[end] = m;
end = (end+1) % circular_buf.size();
++buffered;
buffer_not_empty.notify_one();
}
int receive() {
lock lk(monitor);
while (buffered == 0)
buffer_not_empty.wait(lk);
int i = circular_buf[begin];
begin = (begin+1) % circular_buf.size();
--buffered;
buffer_not_full.notify_one();
return i;
}
private:
int begin, end, buffered;
std::vector<int> circular_buf;
boost::condition buffer_not_full, buffer_not_empty;
boost::mutex monitor;
};
bounded_buffer buf(2);
boost::mutex io_mutex;
void sender() {
int n = 0;
while (n < 100) {
buf.send(n);
{
boost::mutex::scoped_lock io_lock(io_mutex);
std::cout << "sent: " << n << std::endl;
}
++n;
}
buf.send(-1);
}
void receiver() {
int n;
do {
n = buf.receive();
{
boost::mutex::scoped_lock io_lock(io_mutex);
std::cout << "received: " << n << std::endl;
}
} while (n != -1); // -1 indicates end of buffer
}
int main(int, char*[])
{
boost::thread thrd1(&sender);
boost::thread thrd2(&receiver);
thrd1.join();
thrd2.join();
return 0;
}

View File

@@ -1,3 +1,9 @@
// 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)
#include <vector>
#include <iostream>
#include <boost/thread/condition.hpp>
@@ -6,21 +12,21 @@
#include <boost/thread/thread.hpp>
namespace {
const int ITERS = 100;
boost::mutex io_mutex;
};
const int ITERS = 100;
boost::mutex io_mutex;
} // namespace
template <typename M>
class buffer_t
{
public:
typedef typename M::scoped_lock scoped_lock;
buffer_t(int n)
: p(0), c(0), full(0), buf(n)
{
}
void send(int m)
{
scoped_lock lk(mutex);
@@ -29,7 +35,7 @@ public:
buf[p] = m;
p = (p+1) % buf.size();
++full;
cond.notify_all();
cond.notify_one();
}
int receive()
{
@@ -39,41 +45,40 @@ public:
int i = buf[c];
c = (c+1) % buf.size();
--full;
cond.notify_all();
cond.notify_one();
return i;
}
static buffer_t& get_buffer()
{
static buffer_t buf(2);
return buf;
}
static void do_sender_thread()
{
for (int n = 0; n < ITERS; ++n)
{
get_buffer().send(n);
{
boost::mutex::scoped_lock lock(io_mutex);
std::cout << "sent: " << n << std::endl;
std::cout << "sending: " << n << std::endl;
}
get_buffer().send(n);
}
}
static void do_receiver_thread()
{
int n;
do
for (int x=0; x < (ITERS/2); ++x)
{
n = get_buffer().receive();
int n = get_buffer().receive();
{
boost::mutex::scoped_lock lock(io_mutex);
std::cout << "received: " << n << std::endl;
}
} while (n < ITERS - 1);
}
}
private:
M mutex;
boost::condition cond;
@@ -86,10 +91,12 @@ void do_test(M* dummy=0)
{
typedef buffer_t<M> buffer_type;
buffer_type::get_buffer();
boost::thread thrd1(&buffer_type::do_sender_thread);
boost::thread thrd1(&buffer_type::do_receiver_thread);
boost::thread thrd2(&buffer_type::do_receiver_thread);
boost::thread thrd3(&buffer_type::do_sender_thread);
thrd1.join();
thrd2.join();
thrd3.join();
}
void test_buffer()

47
example/mutex.cpp Normal file
View File

@@ -0,0 +1,47 @@
// 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)
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <iostream>
boost::mutex io_mutex; // The iostreams are not guaranteed to be thread-safe!
class counter
{
public:
counter() : count(0) { }
int increment() {
boost::mutex::scoped_lock scoped_lock(mutex);
return ++count;
}
private:
boost::mutex mutex;
int count;
};
counter c;
void change_count()
{
int i = c.increment();
boost::mutex::scoped_lock scoped_lock(io_mutex);
std::cout << "count == " << i << std::endl;
}
int main(int, char*[])
{
const int num_threads = 4;
boost::thread_group thrds;
for (int i=0; i < num_threads; ++i)
thrds.create_thread(&change_count);
thrds.join_all();
return 0;
}

31
example/once.cpp Normal file
View File

@@ -0,0 +1,31 @@
// 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)
#include <boost/thread/thread.hpp>
#include <boost/thread/once.hpp>
#include <cassert>
int value=0;
boost::once_flag once = BOOST_ONCE_INIT;
void init()
{
++value;
}
void thread_proc()
{
boost::call_once(&init, once);
}
int main(int argc, char* argv[])
{
boost::thread_group threads;
for (int i=0; i<5; ++i)
threads.create_thread(&thread_proc);
threads.join_all();
assert(value == 1);
}

View File

@@ -0,0 +1,49 @@
// 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)
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/thread.hpp>
#include <iostream>
class counter
{
public:
counter() : count(0) { }
int add(int val) {
boost::recursive_mutex::scoped_lock scoped_lock(mutex);
count += val;
return count;
}
int increment() {
boost::recursive_mutex::scoped_lock scoped_lock(mutex);
return add(1);
}
private:
boost::recursive_mutex mutex;
int count;
};
counter c;
void change_count()
{
std::cout << "count == " << c.increment() << std::endl;
}
int main(int, char*[])
{
const int num_threads=4;
boost::thread_group threads;
for (int i=0; i < num_threads; ++i)
threads.create_thread(&change_count);
threads.join_all();
return 0;
}

185
example/starvephil.cpp Normal file
View File

@@ -0,0 +1,185 @@
// 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)
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
#include <iostream>
#include <time.h>
namespace
{
boost::mutex iomx;
} // namespace
class canteen
{
public:
canteen() : m_chickens(0) { }
void get(int id)
{
boost::mutex::scoped_lock lock(m_mutex);
while (m_chickens == 0)
{
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << id <<
": wot, no chickens? I'll WAIT ..." << std::endl;
}
m_condition.wait(lock);
}
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << id <<
": those chickens look good ... one please ..." << std::endl;
}
m_chickens--;
}
void put(int value)
{
boost::mutex::scoped_lock lock(m_mutex);
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock()
<< ") Chef: ouch ... make room ... this dish is "
<< "very hot ..." << std::endl;
}
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 3;
boost::thread::sleep(xt);
m_chickens += value;
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() <<
") Chef: more chickens ... " << m_chickens <<
" now available ... NOTIFYING ..." << std::endl;
}
m_condition.notify_all();
}
private:
boost::mutex m_mutex;
boost::condition m_condition;
int m_chickens;
};
canteen g_canteen;
void chef()
{
const int chickens = 4;
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Chef: starting ..." << std::endl;
}
for (;;)
{
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Chef: cooking ..." << std::endl;
}
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 2;
boost::thread::sleep(xt);
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Chef: " << chickens
<< " chickens, ready-to-go ..." << std::endl;
}
g_canteen.put(chickens);
}
}
struct phil
{
phil(int id) : m_id(id) { }
void run() {
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << m_id
<< ": starting ..." << std::endl;
}
for (;;)
{
if (m_id > 0)
{
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 3;
boost::thread::sleep(xt);
}
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << m_id
<< ": gotta eat ..." << std::endl;
}
g_canteen.get(m_id);
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << m_id
<< ": mmm ... that's good ..." << std::endl;
}
}
}
static void do_thread(void* param) {
static_cast<phil*>(param)->run();
}
int m_id;
};
struct thread_adapt
{
thread_adapt(void (*func)(void*), void* param)
: _func(func), _param(param)
{
}
int operator()() const
{
_func(_param);
return 0;
}
void (*_func)(void*);
void* _param;
};
class thread_adapter
{
public:
thread_adapter(void (*func)(void*), void* param)
: _func(func), _param(param)
{
}
void operator()() const { _func(_param); }
private:
void (*_func)(void*);
void* _param;
};
int main(int argc, char* argv[])
{
boost::thread thrd_chef(&chef);
phil p[] = { phil(0), phil(1), phil(2), phil(3), phil(4) };
boost::thread thrd_phil0(thread_adapter(&phil::do_thread, &p[0]));
boost::thread thrd_phil1(thread_adapter(&phil::do_thread, &p[1]));
boost::thread thrd_phil2(thread_adapter(&phil::do_thread, &p[2]));
boost::thread thrd_phil3(thread_adapter(&phil::do_thread, &p[3]));
boost::thread thrd_phil4(thread_adapter(&phil::do_thread, &p[4]));
thrd_chef.join();
thrd_phil0.join();
thrd_phil1.join();
thrd_phil2.join();
thrd_phil3.join();
thrd_phil4.join();
return 0;
}

View File

@@ -1,171 +0,0 @@
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
#include <iostream>
#include <time.h>
namespace
{
boost::mutex iomx;
};
class canteen
{
public:
canteen() : m_chickens(0) { }
void get(int id)
{
boost::mutex::scoped_lock lock(m_mutex);
while (m_chickens == 0)
{
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << id <<
": wot, no chickens? I'll WAIT ..." << std::endl;
}
m_condition.wait(lock);
}
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << id <<
": those chickens look good ... one please ..." << std::endl;
}
m_chickens--;
}
void put(int value)
{
boost::mutex::scoped_lock lock(m_mutex);
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() <<
") Chef: ouch ... make room ... this dish is very hot ..." << std::endl;
}
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 3;
boost::thread::sleep(xt);
m_chickens += value;
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() <<
") Chef: more chickens ... " << m_chickens <<
" now available ... NOTIFYING ..." << std::endl;
}
m_condition.notify_all();
}
private:
boost::mutex m_mutex;
boost::condition m_condition;
int m_chickens;
};
canteen g_canteen;
void chef()
{
const int chickens = 4;
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Chef: starting ..." << std::endl;
}
for (;;)
{
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Chef: cooking ..." << std::endl;
}
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 2;
boost::thread::sleep(xt);
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Chef: " << chickens
<< " chickens, ready-to-go ..." << std::endl;
}
g_canteen.put(chickens);
}
}
struct phil
{
phil(int id) : m_id(id) { }
void run() {
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << m_id << ": starting ..." << std::endl;
}
for (;;)
{
if (m_id > 0)
{
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 3;
boost::thread::sleep(xt);
}
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << m_id
<< ": gotta eat ..." << std::endl;
}
g_canteen.get(m_id);
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << m_id
<< ": mmm ... that's good ..." << std::endl;
}
}
}
static void do_thread(void* param) {
static_cast<phil*>(param)->run();
}
int m_id;
};
struct thread_adapt
{
thread_adapt(void (*func)(void*), void* param) : _func(func), _param(param) { }
int operator()() const
{
_func(_param);
return 0;
}
void (*_func)(void*);
void* _param;
};
class thread_adapter
{
public:
thread_adapter(void (*func)(void*), void* param) : _func(func), _param(param) { }
void operator()() const { _func(_param); }
private:
void (*_func)(void*);
void* _param;
};
int main(int argc, char* argv[])
{
boost::thread thrd_chef(&chef);
phil p[] = { phil(0), phil(1), phil(2), phil(3), phil(4) };
boost::thread thrd_phil0(thread_adapter(&phil::do_thread, &p[0]));
boost::thread thrd_phil1(thread_adapter(&phil::do_thread, &p[1]));
boost::thread thrd_phil2(thread_adapter(&phil::do_thread, &p[2]));
boost::thread thrd_phil3(thread_adapter(&phil::do_thread, &p[3]));
boost::thread thrd_phil4(thread_adapter(&phil::do_thread, &p[4]));
thrd_chef.join();
thrd_phil0.join();
thrd_phil1.join();
thrd_phil2.join();
thrd_phil3.join();
thrd_phil4.join();
return 0;
}

View File

@@ -1,13 +1,18 @@
// 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)
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/semaphore.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
#include <iostream>
#if defined(BOOST_HAS_WINTHREADS)
# include <windows.h>
# include <process.h>
# include <windows.h>
# include <process.h>
#endif
enum game_state
@@ -50,7 +55,10 @@ void player(void* param)
{
cond.wait(lock);
if (state == other)
std::cout << "---" << player_name(active) << ": Spurious wakeup!" << std::endl;
{
std::cout << "---" << player_name(active)
<< ": Spurious wakeup!" << std::endl;
}
} while (state == other);
}
@@ -61,7 +69,10 @@ void player(void* param)
struct thread_adapt
{
thread_adapt(void (*func)(void*), void* param) : _func(func), _param(param) { }
thread_adapt(void (*func)(void*), void* param)
: _func(func), _param(param)
{
}
int operator()() const
{
_func(_param);
@@ -75,7 +86,10 @@ struct thread_adapt
class thread_adapter
{
public:
thread_adapter(void (*func)(void*), void* param) : _func(func), _param(param) { }
thread_adapter(void (*func)(void*), void* param)
: _func(func), _param(param)
{
}
void operator()() const { _func(_param); }
private:
void (*_func)(void*);

35
example/thread.cpp Normal file
View File

@@ -0,0 +1,35 @@
// 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)
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
#include <iostream>
struct thread_alarm
{
thread_alarm(int secs) : m_secs(secs) { }
void operator()()
{
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += m_secs;
boost::thread::sleep(xt);
std::cout << "alarm sounded..." << std::endl;
}
int m_secs;
};
int main(int argc, char* argv[])
{
int secs = 5;
std::cout << "setting alarm for 5 seconds..." << std::endl;
thread_alarm alarm(secs);
boost::thread thrd(alarm);
thrd.join();
}

25
example/thread_group.cpp Normal file
View File

@@ -0,0 +1,25 @@
// 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)
#include <boost/thread/thread.hpp>
#include <iostream>
int count = 0;
boost::mutex mutex;
void increment_count()
{
boost::mutex::scoped_lock lock(mutex);
std::cout << "count = " << ++count << std::endl;
}
int main(int argc, char* argv[])
{
boost::thread_group threads;
for (int i = 0; i < 10; ++i)
threads.create_thread(&increment_count);
threads.join_all();
}

36
example/tss.cpp Normal file
View File

@@ -0,0 +1,36 @@
// 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)
#include <boost/thread/thread.hpp>
#include <boost/thread/tss.hpp>
#include <cassert>
boost::thread_specific_ptr<int> value;
void increment()
{
int* p = value.get();
++*p;
}
void thread_proc()
{
value.reset(new int(0)); // initialize the thread's storage
for (int i=0; i<10; ++i)
{
increment();
int* p = value.get();
assert(*p == i+1);
}
}
int main(int argc, char* argv[])
{
boost::thread_group threads;
for (int i=0; i<5; ++i)
threads.create_thread(&thread_proc);
threads.join_all();
}

16
example/xtime.cpp Normal file
View File

@@ -0,0 +1,16 @@
// 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)
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
int main(int argc, char* argv[])
{
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 1;
boost::thread::sleep(xt); // Sleep for 1 second
}

25
include/boost/thread.hpp Normal file
View File

@@ -0,0 +1,25 @@
// Copyright (C) 2001-2003
// William E. Kempf
// (C) Copyright 2008 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)
// See www.boost.org/libs/thread for documentation.
#if !defined(BOOST_THREAD_WEK01082003_HPP)
#define BOOST_THREAD_WEK01082003_HPP
#include <boost/thread/thread.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/once.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/tss.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/barrier.hpp>
#endif

View File

@@ -0,0 +1,63 @@
// Copyright (C) 2002-2003
// David Moore, William E. Kempf
// Copyright (C) 2007-8 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_BARRIER_JDM030602_HPP
#define BOOST_BARRIER_JDM030602_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
#include <string>
#include <stdexcept>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class barrier
{
public:
barrier(unsigned int count)
: m_threshold(count), m_count(count), m_generation(0)
{
if (count == 0)
throw std::invalid_argument("count cannot be zero.");
}
bool wait()
{
boost::mutex::scoped_lock lock(m_mutex);
unsigned int gen = m_generation;
if (--m_count == 0)
{
m_generation++;
m_count = m_threshold;
m_cond.notify_all();
return true;
}
while (gen == m_generation)
m_cond.wait(lock);
return false;
}
private:
mutex m_mutex;
condition_variable m_cond;
unsigned int m_threshold;
unsigned int m_count;
unsigned int m_generation;
};
} // namespace boost
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,156 +1,16 @@
// Copyright (C) 2001
// William E. Kempf
#ifndef BOOST_THREAD_CONDITION_HPP
#define BOOST_THREAD_CONDITION_HPP
// (C) Copyright 2007 Anthony Williams
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONDITION_WEK070601_HPP
#define BOOST_CONDITION_WEK070601_HPP
#include <boost/thread/condition_variable.hpp>
#include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS
# error Thread support is unavailable!
#endif
#include <boost/thread/exceptions.hpp>
#include <boost/utility.hpp>
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
#endif
namespace boost {
struct xtime;
class condition : private noncopyable
namespace boost
{
public:
condition();
~condition();
void notify_one();
void notify_all();
typedef condition_variable_any condition;
}
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:
template <typename M>
void do_wait(M& mutex)
{
#if defined(BOOST_HAS_WINTHREADS)
enter_wait();
#endif
typename M::cv_state state;
mutex.do_unlock(state);
#if defined(BOOST_HAS_PTHREADS)
do_wait(state.pmutex);
#elif defined(BOOST_HAS_WINTHREADS)
do_wait();
#endif
mutex.do_lock(state);
}
template <typename M>
bool do_timed_wait(M& mutex, const xtime& xt)
{
#if defined(BOOST_HAS_WINTHREADS)
enter_wait();
#endif
typename M::cv_state state;
mutex.do_unlock(state);
bool ret = false;
#if defined(BOOST_HAS_PTHREADS)
ret = do_timed_wait(xt, state.pmutex);
#elif defined(BOOST_HAS_WINTHREADS)
ret = do_timed_wait(xt);
#endif
mutex.do_lock(state);
return ret;
}
#if defined(BOOST_HAS_WINTHREADS)
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)
unsigned long m_gate;
unsigned long m_queue;
unsigned long m_mutex;
unsigned m_gone; // # threads that timed out and never made it to the m_queue
unsigned long m_blocked; // # threads m_blocked m_waiting for the condition
unsigned m_waiting; // # threads m_waiting no longer m_waiting for the condition but still
// m_waiting to be removed from the m_queue
#elif defined(BOOST_HAS_PTHREADS)
pthread_cond_t m_condition;
#endif
};
} // 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.
#endif // BOOST_CONDITION_WEK070601_HPP

View File

@@ -0,0 +1,21 @@
#ifndef BOOST_THREAD_CONDITION_VARIABLE_HPP
#define BOOST_THREAD_CONDITION_VARIABLE_HPP
// condition_variable.hpp
//
// (C) Copyright 2007 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/platform.hpp>
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#include <boost/thread/win32/condition_variable.hpp>
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
#include <boost/thread/pthread/condition_variable.hpp>
#else
#error "Boost threads unavailable on this platform"
#endif
#endif

View File

@@ -1,100 +0,0 @@
// Copyright (C) 2001
// 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.
// This file is used to configure Boost.Threads during development
// in order to decouple dependency on any Boost release. Once
// accepted into Boost these contents will be moved to <boost/config>
// or some other appropriate build configuration and all
// #include <boost/thread/config.hpp> statements will be changed
// accordingly.
#ifndef BOOST_THREAD_CONFIG_WEK070601_HPP
#define BOOST_THREAD_CONFIG_WEK070601_HPP
#include <boost/config.hpp>
#error "Included <boost/thread/config.hpp>"
/*// Define if threading support is enabled for the toolset.
#undef BOOST_HAS_THREADS
// Define if threading should be implemented in terms of Win32 threads.
#undef BOOST_HAS_WINTHREADS
// Define if threading should be implemented in terms of POSIX threads.
#undef BOOST_HAS_PTHREADS
// Define if BOOST_HAS_PTHREADS and pthread_delay_np() exists.
#undef BOOST_HAS_PTHREAD_DELAY_NP
// Define if BOOST_HAS_PTHREADS and not BOOST_HAS_PTHREAD_DELAY_NP
// but nanosleep can be used instead.
#undef BOOST_HAS_NANOSLEEP
// Define if BOOST_HAS_PTHREADS and pthread_yield() exists.
#undef BOOST_HAS_PTHREAD_YIELD
// Define if BOOST_HAS_PTHREADS and not BOOST_HAS_PTHREAD_YIELD and
// sched_yield() exists.
#undef BOOST_HAS_SCHED_YIELD
// Define if gettimeofday() exists.
#undef BOOST_HAS_GETTIMEOFDAY
// Define if not BOOST_HAS_GETTIMEOFDAY and clock_gettime() exists.
#undef BOOST_HAS_CLOCK_GETTIME
// Define if not BOOST_HAS_GETTIMEOFDAY and not BOOST_HAS_CLOCK_GETTIME and
// GetSystemTimeAsFileTime() can be called with an FTIME structure.
#undef BOOST_HAS_FTIME
// Define if pthread_mutexattr_settype and pthread_mutexattr_gettype exist.
#undef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
// Here we'll set up known compiler options.
#if defined(BOOST_MSVC)
# if defined(_MT)
# define BOOST_HAS_THREADS
# endif
# define BOOST_HAS_WINTHREADS // comment out this to test pthreads-win32.
# if !defined(BOOST_HAS_WINTHREADS)
# define BOOST_HAS_PTHREADS
# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
# define PtW32NoCatchWarn
# pragma comment(lib, "pthreadVCE.lib")
# endif
# define BOOST_HAS_FTIME
// pdm: this is for linux - is there a better #define to #if on?
// wek: not sure how else to do this, but GNU CC on Win32 should probably
// use BOOST_HAS_WINTHREADS, and I expect there will be other
// platform specific variations for this compiler toolset. Need
// to decide how to handle this.
#elif defined( __GNUC__ )
# define BOOST_HAS_THREADS
# define BOOST_HAS_PTHREADS
# define BOOST_HAS_NANOSLEEP
# define BOOST_HAS_GETTIMEOFDAY
// pdm: From the pthread.h header, one of these macros
// must be defined for this stuff to exist.
// wek: This seems like a harmless enough method to determine these
// switches, but one should note that some implementations may not
// use these. Notably, pthreads-win32 doesn't define either
// __USE_UNIX98 or __USE_GNU.
# if defined( __USE_UNIX98 )
# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
# elif defined( __USE_GNU )
# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
# define BOOST_HAS_PTHREAD_YIELD
# endif
#endif*/
#endif // BOOST_THREAD_CONFIG_WEK070601_HPP

View File

@@ -0,0 +1,94 @@
// 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)
#ifndef BOOST_THREAD_CONFIG_WEK01032003_HPP
#define BOOST_THREAD_CONFIG_WEK01032003_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
# pragma warn -8008 // Condition always true/false
# pragma warn -8080 // Identifier declared but never used
# pragma warn -8057 // Parameter never used
# pragma warn -8066 // Unreachable code
#endif
#include "platform.hpp"
// compatibility with the rest of Boost's auto-linking code:
#if defined(BOOST_THREAD_DYN_DLL) || defined(BOOST_ALL_DYN_LINK)
# undef BOOST_THREAD_USE_LIB
# define BOOST_THREAD_USE_DLL
#endif
#if defined(BOOST_THREAD_BUILD_DLL) //Build dll
#elif defined(BOOST_THREAD_BUILD_LIB) //Build lib
#elif defined(BOOST_THREAD_USE_DLL) //Use dll
#elif defined(BOOST_THREAD_USE_LIB) //Use lib
#else //Use default
# if defined(BOOST_THREAD_PLATFORM_WIN32)
# if defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)
//For compilers supporting auto-tss cleanup
//with Boost.Threads lib, use Boost.Threads lib
# define BOOST_THREAD_USE_LIB
# else
//For compilers not yet supporting auto-tss cleanup
//with Boost.Threads lib, use Boost.Threads dll
# define BOOST_THREAD_USE_DLL
# endif
# else
# define BOOST_THREAD_USE_LIB
# endif
#endif
#if defined(BOOST_HAS_DECLSPEC)
# if defined(BOOST_THREAD_BUILD_DLL) //Build dll
# define BOOST_THREAD_DECL __declspec(dllexport)
# elif defined(BOOST_THREAD_USE_DLL) //Use dll
# define BOOST_THREAD_DECL __declspec(dllimport)
# else
# define BOOST_THREAD_DECL
# endif
#else
# define BOOST_THREAD_DECL
#endif // BOOST_HAS_DECLSPEC
//
// Automatically link to the correct build variant where possible.
//
#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_THREAD_NO_LIB) && !defined(BOOST_THREAD_BUILD_DLL) && !defined(BOOST_THREAD_BUILD_LIB)
//
// Tell the autolink to link dynamically, this will get undef'ed by auto_link.hpp
// once it's done with it:
//
#if defined(BOOST_THREAD_USE_DLL)
# define BOOST_DYN_LINK
#endif
//
// Set the name of our library, this will get undef'ed by auto_link.hpp
// once it's done with it:
//
#if defined(BOOST_THREAD_LIB_NAME)
# define BOOST_LIB_NAME BOOST_THREAD_LIB_NAME
#else
# define BOOST_LIB_NAME boost_thread
#endif
//
// If we're importing code from a dll, then tell auto_link.hpp about it:
//
// And include the header that does the work:
//
#include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
#endif // BOOST_THREAD_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.

View File

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

View File

@@ -1,172 +0,0 @@
// Copyright (C) 2001
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#ifndef BOOST_XLOCK_WEK070601_HPP
#define BOOST_XLOCK_WEK070601_HPP
#include <boost/utility.hpp>
#include <boost/thread/exceptions.hpp>
namespace boost {
class condition;
struct xtime;
namespace detail { namespace thread {
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();
m_mutex.do_lock();
m_locked = true;
}
void unlock()
{
if (!m_locked) throw lock_error();
m_mutex.do_unlock();
m_locked = false;
}
bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; }
private:
friend class boost::condition;
Mutex& m_mutex;
bool m_locked;
};
template <typename TryMutex>
class scoped_try_lock : private noncopyable
{
public:
typedef TryMutex mutex_type;
explicit scoped_try_lock(TryMutex& mx)
: m_mutex(mx), m_locked(false)
{
try_lock();
}
scoped_try_lock(TryMutex& mx, bool initially_locked)
: m_mutex(mx), m_locked(false)
{
if (initially_locked) lock();
}
~scoped_try_lock()
{
if (m_locked) unlock();
}
void lock()
{
if (m_locked) throw lock_error();
m_mutex.do_lock();
m_locked = true;
}
bool try_lock()
{
if (m_locked) throw lock_error();
return (m_locked = m_mutex.do_trylock());
}
void unlock()
{
if (!m_locked) throw lock_error();
m_mutex.do_unlock();
m_locked = false;
}
bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; }
private:
friend class boost::condition;
TryMutex& m_mutex;
bool m_locked;
};
template <typename TimedMutex>
class scoped_timed_lock : private noncopyable
{
public:
typedef TimedMutex mutex_type;
scoped_timed_lock(TimedMutex& mx, const xtime& xt)
: m_mutex(mx), m_locked(false)
{
timed_lock(xt);
}
scoped_timed_lock(TimedMutex& mx, bool initially_locked)
: m_mutex(mx), m_locked(false)
{
if (initially_locked) lock();
}
~scoped_timed_lock()
{
if (m_locked) unlock();
}
void lock()
{
if (m_locked) throw lock_error();
m_mutex.do_lock();
m_locked = true;
}
bool timed_lock(const xtime& xt)
{
if (m_locked) throw lock_error();
return (m_locked = m_mutex.do_timedlock(xt));
}
void unlock()
{
if (!m_locked) throw lock_error();
m_mutex.do_unlock();
m_locked = false;
}
bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; }
private:
friend class boost::condition;
TimedMutex& m_mutex;
bool m_locked;
};
} // namespace thread
} // namespace detail
} // namespace boost
// 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_XLOCK_WEK070601_HPP

View File

@@ -0,0 +1,60 @@
// Distributed under the 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-8 Anthony Williams
#ifndef BOOST_THREAD_MOVE_HPP
#define BOOST_THREAD_MOVE_HPP
#ifndef BOOST_NO_SFINAE
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_convertible.hpp>
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
template<typename T>
struct thread_move_t
{
T& t;
explicit thread_move_t(T& t_):
t(t_)
{}
T& operator*() const
{
return t;
}
T* operator->() const
{
return &t;
}
private:
void operator=(thread_move_t&);
};
}
#ifndef BOOST_NO_SFINAE
template<typename T>
typename enable_if<boost::is_convertible<T&,detail::thread_move_t<T> >, T >::type move(T& t)
{
return T(detail::thread_move_t<T>(t));
}
#endif
template<typename T>
detail::thread_move_t<T> move(detail::thread_move_t<T> t)
{
return t;
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

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

View File

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

View File

@@ -0,0 +1,575 @@
#ifndef BOOST_THREAD_THREAD_COMMON_HPP
#define BOOST_THREAD_THREAD_COMMON_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
#include <boost/thread/exceptions.hpp>
#include <ostream>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/thread/detail/thread_heap_alloc.hpp>
#include <boost/utility.hpp>
#include <boost/assert.hpp>
#include <list>
#include <algorithm>
#include <boost/ref.hpp>
#include <boost/cstdint.hpp>
#include <boost/bind.hpp>
#include <stdlib.h>
#include <memory>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/config/abi_prefix.hpp>
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4251)
#endif
namespace boost
{
namespace detail
{
template<typename F>
class thread_data:
public detail::thread_data_base
{
public:
#ifdef BOOST_HAS_RVALUE_REFS
thread_data(F&& f_):
f(static_cast<F&&>(f_))
{}
#else
thread_data(F f_):
f(f_)
{}
thread_data(detail::thread_move_t<F> f_):
f(f_)
{}
#endif
void run()
{
f();
}
private:
F f;
void operator=(thread_data&);
thread_data(thread_data&);
};
template<typename F>
class thread_data<boost::reference_wrapper<F> >:
public detail::thread_data_base
{
private:
F& f;
void operator=(thread_data&);
thread_data(thread_data&);
public:
thread_data(boost::reference_wrapper<F> f_):
f(f_)
{}
void run()
{
f();
}
};
template<typename F>
class thread_data<const boost::reference_wrapper<F> >:
public detail::thread_data_base
{
private:
F& f;
void operator=(thread_data&);
thread_data(thread_data&);
public:
thread_data(const boost::reference_wrapper<F> f_):
f(f_)
{}
void run()
{
f();
}
};
}
class BOOST_THREAD_DECL thread
{
private:
thread(thread&);
thread& operator=(thread&);
void release_handle();
mutable boost::mutex thread_info_mutex;
detail::thread_data_ptr thread_info;
void start_thread();
explicit thread(detail::thread_data_ptr data);
detail::thread_data_ptr get_thread_info() const;
#ifdef BOOST_HAS_RVALUE_REFS
template<typename F>
static inline detail::thread_data_ptr make_thread_info(F&& f)
{
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<typename boost::remove_reference<F>::type> >(static_cast<F&&>(f)));
}
static inline detail::thread_data_ptr make_thread_info(void (*f)())
{
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(f));
}
#else
template<typename F>
static inline detail::thread_data_ptr make_thread_info(F f)
{
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
}
template<typename F>
static inline detail::thread_data_ptr make_thread_info(boost::detail::thread_move_t<F> f)
{
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
}
struct dummy;
#endif
public:
thread();
~thread();
#ifdef BOOST_HAS_RVALUE_REFS
template <class F>
thread(F&& f):
thread_info(make_thread_info(static_cast<F&&>(f)))
{
start_thread();
}
thread(thread&& other)
{
thread_info.swap(other.thread_info);
}
thread& operator=(thread&& other)
{
thread_info=other.thread_info;
other.thread_info.reset();
return *this;
}
thread&& move()
{
return static_cast<thread&&>(*this);
}
#else
#ifdef BOOST_NO_SFINAE
template <class F>
explicit thread(F f):
thread_info(make_thread_info(f))
{
start_thread();
}
#else
template <class F>
explicit thread(F f,typename disable_if<boost::is_convertible<F&,detail::thread_move_t<F> >, dummy* >::type=0):
thread_info(make_thread_info(f))
{
start_thread();
}
#endif
template <class F>
explicit thread(detail::thread_move_t<F> f):
thread_info(make_thread_info(f))
{
start_thread();
}
thread(detail::thread_move_t<thread> x)
{
thread_info=x->thread_info;
x->thread_info.reset();
}
thread& operator=(detail::thread_move_t<thread> x)
{
thread new_thread(x);
swap(new_thread);
return *this;
}
operator detail::thread_move_t<thread>()
{
return move();
}
detail::thread_move_t<thread> move()
{
detail::thread_move_t<thread> x(*this);
return x;
}
#endif
template <class F,class A1>
thread(F f,A1 a1):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1)))
{
start_thread();
}
template <class F,class A1,class A2>
thread(F f,A1 a1,A2 a2):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2)))
{
start_thread();
}
template <class F,class A1,class A2,class A3>
thread(F f,A1 a1,A2 a2,A3 a3):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3)))
{
start_thread();
}
template <class F,class A1,class A2,class A3,class A4>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4)))
{
start_thread();
}
template <class F,class A1,class A2,class A3,class A4,class A5>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5)))
{
start_thread();
}
template <class F,class A1,class A2,class A3,class A4,class A5,class A6>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6)))
{
start_thread();
}
template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7)))
{
start_thread();
}
template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8)))
{
start_thread();
}
template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8,class A9>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8,a9)))
{
start_thread();
}
void swap(thread& x)
{
thread_info.swap(x.thread_info);
}
class id;
id get_id() const;
bool joinable() const;
void join();
bool timed_join(const system_time& wait_until);
template<typename TimeDuration>
inline bool timed_join(TimeDuration const& rel_time)
{
return timed_join(get_system_time()+rel_time);
}
void detach();
static unsigned hardware_concurrency();
typedef detail::thread_data_base::native_handle_type native_handle_type;
native_handle_type native_handle();
// backwards compatibility
bool operator==(const thread& other) const;
bool operator!=(const thread& other) const;
static inline void yield()
{
this_thread::yield();
}
static inline void sleep(const system_time& xt)
{
this_thread::sleep(xt);
}
// extensions
void interrupt();
bool interruption_requested() const;
};
inline void swap(thread& lhs,thread& rhs)
{
return lhs.swap(rhs);
}
#ifdef BOOST_HAS_RVALUE_REFS
inline thread&& move(thread&& t)
{
return t;
}
#else
inline thread move(detail::thread_move_t<thread> t)
{
return thread(t);
}
#endif
namespace this_thread
{
class BOOST_THREAD_DECL disable_interruption
{
disable_interruption(const disable_interruption&);
disable_interruption& operator=(const disable_interruption&);
bool interruption_was_enabled;
friend class restore_interruption;
public:
disable_interruption();
~disable_interruption();
};
class BOOST_THREAD_DECL restore_interruption
{
restore_interruption(const restore_interruption&);
restore_interruption& operator=(const restore_interruption&);
public:
explicit restore_interruption(disable_interruption& d);
~restore_interruption();
};
thread::id BOOST_THREAD_DECL get_id();
void BOOST_THREAD_DECL interruption_point();
bool BOOST_THREAD_DECL interruption_enabled();
bool BOOST_THREAD_DECL interruption_requested();
inline void sleep(xtime const& abs_time)
{
sleep(system_time(abs_time));
}
}
class thread::id
{
private:
detail::thread_data_ptr thread_data;
id(detail::thread_data_ptr thread_data_):
thread_data(thread_data_)
{}
friend class thread;
friend id this_thread::get_id();
public:
id():
thread_data()
{}
bool operator==(const id& y) const
{
return thread_data==y.thread_data;
}
bool operator!=(const id& y) const
{
return thread_data!=y.thread_data;
}
bool operator<(const id& y) const
{
return thread_data<y.thread_data;
}
bool operator>(const id& y) const
{
return y.thread_data<thread_data;
}
bool operator<=(const id& y) const
{
return !(y.thread_data<thread_data);
}
bool operator>=(const id& y) const
{
return !(thread_data<y.thread_data);
}
template<class charT, class traits>
friend std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const id& x)
{
if(x.thread_data)
{
return os<<x.thread_data;
}
else
{
return os<<"{Not-any-thread}";
}
}
};
inline bool thread::operator==(const thread& other) const
{
return get_id()==other.get_id();
}
inline bool thread::operator!=(const thread& other) const
{
return get_id()!=other.get_id();
}
namespace detail
{
struct thread_exit_function_base
{
virtual ~thread_exit_function_base()
{}
virtual void operator()() const=0;
};
template<typename F>
struct thread_exit_function:
thread_exit_function_base
{
F f;
thread_exit_function(F f_):
f(f_)
{}
void operator()() const
{
f();
}
};
void add_thread_exit_function(thread_exit_function_base*);
}
namespace this_thread
{
template<typename F>
void at_thread_exit(F f)
{
detail::thread_exit_function_base* const thread_exit_func=detail::heap_new<detail::thread_exit_function<F> >(f);
detail::add_thread_exit_function(thread_exit_func);
}
}
class thread_group:
private noncopyable
{
public:
~thread_group()
{
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
it!=end;
++it)
{
delete *it;
}
}
template<typename F>
thread* create_thread(F threadfunc)
{
boost::lock_guard<mutex> guard(m);
std::auto_ptr<thread> new_thread(new thread(threadfunc));
threads.push_back(new_thread.get());
return new_thread.release();
}
void add_thread(thread* thrd)
{
if(thrd)
{
boost::lock_guard<mutex> guard(m);
threads.push_back(thrd);
}
}
void remove_thread(thread* thrd)
{
boost::lock_guard<mutex> guard(m);
std::list<thread*>::iterator const it=std::find(threads.begin(),threads.end(),thrd);
if(it!=threads.end())
{
threads.erase(it);
}
}
void join_all()
{
boost::lock_guard<mutex> guard(m);
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
it!=end;
++it)
{
(*it)->join();
}
}
void interrupt_all()
{
boost::lock_guard<mutex> guard(m);
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
it!=end;
++it)
{
(*it)->interrupt();
}
}
size_t size() const
{
boost::lock_guard<mutex> guard(m);
return threads.size();
}
private:
std::list<thread*> threads;
mutable mutex m;
};
}
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,23 @@
#ifndef BOOST_THREAD_THREAD_HEAP_ALLOC_HPP
#define BOOST_THREAD_THREAD_HEAP_ALLOC_HPP
// thread_heap_alloc.hpp
//
// (C) Copyright 2008 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/platform.hpp>
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#include <boost/thread/win32/thread_heap_alloc.hpp>
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
#include <boost/thread/pthread/thread_heap_alloc.hpp>
#else
#error "Boost threads unavailable on this platform"
#endif
#endif

View File

@@ -0,0 +1,82 @@
// (C) Copyright Michael Glassford 2004.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#if !defined(BOOST_TLS_HOOKS_HPP)
#define BOOST_TLS_HOOKS_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/config/abi_prefix.hpp>
#if defined(BOOST_HAS_WINTHREADS)
typedef void (__cdecl *thread_exit_handler)(void);
extern "C" BOOST_THREAD_DECL int at_thread_exit(
thread_exit_handler exit_handler
);
//Add a function to the list of functions that will
//be called when a thread is about to exit.
//Currently only implemented for Win32, but should
//later be implemented for all platforms.
//Used by Win32 implementation of Boost.Threads
//tss to perform cleanup.
//Like the C runtime library atexit() function,
//which it mimics, at_thread_exit() returns
//zero if successful and a nonzero
//value if an error occurs.
#endif //defined(BOOST_HAS_WINTHREADS)
#if defined(BOOST_HAS_WINTHREADS)
extern "C" BOOST_THREAD_DECL void on_process_enter(void);
//Function to be called when the exe or dll
//that uses Boost.Threads first starts
//or is first loaded.
//Should be called only before the first call to
//on_thread_enter().
//Called automatically by Boost.Threads when
//a method for doing so has been discovered.
//May be omitted; may be called multiple times.
extern "C" BOOST_THREAD_DECL void on_process_exit(void);
//Function to be called when the exe or dll
//that uses Boost.Threads first starts
//or is first loaded.
//Should be called only after the last call to
//on_exit_thread().
//Called automatically by Boost.Threads when
//a method for doing so has been discovered.
//Must not be omitted; may be called multiple times.
extern "C" BOOST_THREAD_DECL void on_thread_enter(void);
//Function to be called just after a thread starts
//in an exe or dll that uses Boost.Threads.
//Must be called in the context of the thread
//that is starting.
//Called automatically by Boost.Threads when
//a method for doing so has been discovered.
//May be omitted; may be called multiple times.
extern "C" BOOST_THREAD_DECL void __cdecl on_thread_exit(void);
//Function to be called just be fore a thread ends
//in an exe or dll that uses Boost.Threads.
//Must be called in the context of the thread
//that is ending.
//Called automatically by Boost.Threads when
//a method for doing so has been discovered.
//Must not be omitted; may be called multiple times.
extern "C" void tss_cleanup_implemented(void);
//Dummy function used both to detect whether tss cleanup
//cleanup has been implemented and to force
//it to be linked into the Boost.Threads library.
#endif //defined(BOOST_HAS_WINTHREADS)
#include <boost/config/abi_suffix.hpp>
#endif //!defined(BOOST_TLS_HOOKS_HPP)

View File

@@ -1,46 +1,114 @@
// Copyright (C) 2001
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright (C) 2007-8 Anthony Williams
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// This file is used to configure Boost.Threads during development
// in order to decouple dependency on any Boost release. Once
// accepted into Boost these contents will be moved to <boost/config>
// or some other appropriate build configuration and all
// #include <boost/thread/config.hpp> statements will be changed
// accordingly.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_THREAD_EXCEPTIONS_PDM070801_H
#define BOOST_THREAD_EXCEPTIONS_PDM070801_H
#include <boost/thread/detail/config.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 {
#include <boost/config/abi_prefix.hpp>
class lock_error : public std::runtime_error
namespace boost
{
class BOOST_THREAD_DECL thread_interrupted
{};
class BOOST_THREAD_DECL thread_exception : public std::exception
{
protected:
thread_exception();
thread_exception(int sys_err_code);
public:
lock_error() : std::runtime_error("thread lock error") { }
~thread_exception() throw();
int native_error() const;
private:
int m_sys_err;
};
class thread_resource_error : public std::runtime_error
class condition_error:
public std::exception
{
public:
const char* what() const throw()
{
return "Condition error";
}
};
class BOOST_THREAD_DECL lock_error : public thread_exception
{
public:
thread_resource_error() : std::runtime_error("thread resource error") { }
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
#include <boost/config/abi_suffix.hpp>
#endif // BOOST_THREAD_CONFIG_PDM070801_H
// Change log:
// 3 Jan 03 WEKEMPF Modified for DLL implementation.

File diff suppressed because it is too large Load Diff

View File

@@ -1,146 +1,21 @@
// Copyright (C) 2001
// William E. Kempf
#ifndef BOOST_THREAD_MUTEX_HPP
#define BOOST_THREAD_MUTEX_HPP
// mutex.hpp
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// (C) Copyright 2007 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MUTEX_WEK070601_HPP
#define BOOST_MUTEX_WEK070601_HPP
#include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS
# error Thread support is unavailable!
#include <boost/thread/detail/platform.hpp>
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#include <boost/thread/win32/mutex.hpp>
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
#include <boost/thread/pthread/mutex.hpp>
#else
#error "Boost threads unavailable on this platform"
#endif
#include <boost/utility.hpp>
#include <boost/thread/detail/lock.hpp>
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
#endif
namespace boost {
class condition;
struct xtime;
class mutex : private noncopyable
{
public:
friend class detail::thread::scoped_lock<mutex>;
friend class condition;
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;
};
#endif
void do_lock();
void do_unlock();
void do_lock(cv_state& state);
void do_unlock(cv_state& state);
#if defined(BOOST_HAS_WINTHREADS)
unsigned long m_mutex;
#elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex;
#endif
};
class try_mutex : private noncopyable
{
public:
friend class detail::thread::scoped_lock<try_mutex>;
friend class detail::thread::scoped_try_lock<try_mutex>;
friend class condition;
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;
};
#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)
unsigned long m_mutex;
#elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex;
#endif
};
class timed_mutex : private noncopyable
{
public:
friend class detail::thread::scoped_lock<timed_mutex>;
friend class detail::thread::scoped_try_lock<timed_mutex>;
friend class detail::thread::scoped_timed_lock<timed_mutex>;
friend class condition;
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;
};
#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)
unsigned long m_mutex;
#elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex;
pthread_cond_t m_condition;
bool m_locked;
#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.
#endif // BOOST_MUTEX_WEK070601_HPP

View File

@@ -1,45 +1,33 @@
// Copyright (C) 2001
// William E. Kempf
#ifndef BOOST_THREAD_ONCE_HPP
#define BOOST_THREAD_ONCE_HPP
// once.hpp
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// (C) Copyright 2006-7 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_ONCE_WEK080101_HPP
#define BOOST_ONCE_WEK080101_HPP
#include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS
# error Thread support is unavailable!
#include <boost/thread/detail/platform.hpp>
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#include <boost/thread/win32/once.hpp>
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
#include <boost/thread/pthread/once.hpp>
#else
#error "Boost threads unavailable on this platform"
#endif
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost {
namespace boost
{
inline void call_once(void (*func)(),once_flag& flag)
{
call_once(flag,func);
}
}
#if defined(BOOST_HAS_PTHREADS)
typedef pthread_once_t once_flag;
const once_flag once_init = PTHREAD_ONCE_INIT;
#elif defined(BOOST_HAS_WINTHREADS)
typedef bool once_flag;
const once_flag once_init = false;
#include <boost/config/abi_suffix.hpp>
#endif
void call_once(void (*func)(), once_flag& flag);
} // namespace boost
// Change Log:
// 1 Aug 01 WEKEMPF Initial version.
#endif // BOOST_ONCE_WEK080101_HPP

View File

@@ -0,0 +1,176 @@
#ifndef BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP
#define BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
#include "timespec.hpp"
#include "pthread_mutex_scoped_lock.hpp"
#include "thread_data.hpp"
#include "condition_variable_fwd.hpp"
#include <boost/config/abi_prefix.hpp>
namespace boost
{
inline void condition_variable::wait(unique_lock<mutex>& m)
{
detail::interruption_checker check_for_interruption(&cond);
BOOST_VERIFY(!pthread_cond_wait(&cond,m.mutex()->native_handle()));
}
inline bool condition_variable::timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until)
{
detail::interruption_checker check_for_interruption(&cond);
struct timespec const timeout=detail::get_timespec(wait_until);
int const cond_res=pthread_cond_timedwait(&cond,m.mutex()->native_handle(),&timeout);
if(cond_res==ETIMEDOUT)
{
return false;
}
BOOST_ASSERT(!cond_res);
return true;
}
inline void condition_variable::notify_one()
{
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
inline void condition_variable::notify_all()
{
BOOST_VERIFY(!pthread_cond_broadcast(&cond));
}
class condition_variable_any
{
pthread_mutex_t internal_mutex;
pthread_cond_t cond;
condition_variable_any(condition_variable&);
condition_variable_any& operator=(condition_variable&);
public:
condition_variable_any()
{
int const res=pthread_mutex_init(&internal_mutex,NULL);
if(res)
{
throw thread_resource_error();
}
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
throw thread_resource_error();
}
}
~condition_variable_any()
{
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
BOOST_VERIFY(!pthread_cond_destroy(&cond));
}
template<typename lock_type>
void wait(lock_type& m)
{
int res=0;
{
detail::interruption_checker check_for_interruption(&cond);
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
m.unlock();
res=pthread_cond_wait(&cond,&internal_mutex);
}
m.lock();
}
if(res)
{
throw condition_error();
}
}
template<typename lock_type,typename predicate_type>
void wait(lock_type& m,predicate_type pred)
{
while(!pred()) wait(m);
}
template<typename lock_type>
bool timed_wait(lock_type& m,boost::system_time const& wait_until)
{
struct timespec const timeout=detail::get_timespec(wait_until);
int res=0;
{
detail::interruption_checker check_for_interruption(&cond);
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
m.unlock();
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
}
m.lock();
}
if(res==ETIMEDOUT)
{
return false;
}
if(res)
{
throw condition_error();
}
return true;
}
template<typename lock_type>
bool timed_wait(lock_type& m,xtime const& wait_until)
{
return timed_wait(m,system_time(wait_until));
}
template<typename lock_type,typename duration_type>
bool timed_wait(lock_type& m,duration_type const& wait_duration)
{
return timed_wait(m,get_system_time()+wait_duration);
}
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred)
{
while (!pred())
{
if(!timed_wait(m, wait_until))
return pred();
}
return true;
}
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,xtime const& wait_until,predicate_type pred)
{
return timed_wait(m,system_time(wait_until),pred);
}
template<typename lock_type,typename duration_type,typename predicate_type>
bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
{
return timed_wait(m,get_system_time()+wait_duration,pred);
}
void notify_one()
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
void notify_all()
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
BOOST_VERIFY(!pthread_cond_broadcast(&cond));
}
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,97 @@
#ifndef BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_HPP
#define BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
#include <boost/assert.hpp>
#include <pthread.h>
#include <boost/thread/mutex.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class condition_variable
{
private:
pthread_cond_t cond;
condition_variable(condition_variable&);
condition_variable& operator=(condition_variable&);
public:
condition_variable()
{
int const res=pthread_cond_init(&cond,NULL);
if(res)
{
throw thread_resource_error();
}
}
~condition_variable()
{
BOOST_VERIFY(!pthread_cond_destroy(&cond));
}
void wait(unique_lock<mutex>& m);
template<typename predicate_type>
void wait(unique_lock<mutex>& m,predicate_type pred)
{
while(!pred()) wait(m);
}
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until);
bool timed_wait(unique_lock<mutex>& m,xtime const& wait_until)
{
return timed_wait(m,system_time(wait_until));
}
template<typename duration_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration)
{
return timed_wait(m,get_system_time()+wait_duration);
}
template<typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until,predicate_type pred)
{
while (!pred())
{
if(!timed_wait(m, wait_until))
return pred();
}
return true;
}
template<typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,xtime const& wait_until,predicate_type pred)
{
return timed_wait(m,system_time(wait_until),pred);
}
template<typename duration_type,typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
{
return timed_wait(m,get_system_time()+wait_duration,pred);
}
typedef pthread_cond_t* native_handle_type;
native_handle_type native_handle()
{
return &cond;
}
void notify_one();
void notify_all();
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,210 @@
#ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_MUTEX_HPP
// (C) Copyright 2007-8 Anthony Williams
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <pthread.h>
#include <boost/utility.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/assert.hpp>
#include <errno.h>
#include "timespec.hpp"
#include "pthread_mutex_scoped_lock.hpp"
#ifdef _POSIX_TIMEOUTS
#if _POSIX_TIMEOUTS >= 0
#define BOOST_PTHREAD_HAS_TIMEDLOCK
#endif
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class mutex:
boost::noncopyable
{
private:
pthread_mutex_t m;
public:
mutex()
{
int const res=pthread_mutex_init(&m,NULL);
if(res)
{
throw thread_resource_error();
}
}
~mutex()
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
}
void lock()
{
BOOST_VERIFY(!pthread_mutex_lock(&m));
}
void unlock()
{
BOOST_VERIFY(!pthread_mutex_unlock(&m));
}
bool try_lock()
{
int const res=pthread_mutex_trylock(&m);
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
return &m;
}
typedef unique_lock<mutex> scoped_lock;
typedef detail::try_lock_wrapper<mutex> scoped_try_lock;
};
typedef mutex try_mutex;
class timed_mutex:
boost::noncopyable
{
private:
pthread_mutex_t m;
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
pthread_cond_t cond;
bool is_locked;
#endif
public:
timed_mutex()
{
int const res=pthread_mutex_init(&m,NULL);
if(res)
{
throw thread_resource_error();
}
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
throw thread_resource_error();
}
is_locked=false;
#endif
}
~timed_mutex()
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
BOOST_VERIFY(!pthread_cond_destroy(&cond));
#endif
}
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time)
{
return timed_lock(get_system_time()+relative_time);
}
bool timed_lock(boost::xtime const & absolute_time)
{
return timed_lock(system_time(absolute_time));
}
#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
void lock()
{
BOOST_VERIFY(!pthread_mutex_lock(&m));
}
void unlock()
{
BOOST_VERIFY(!pthread_mutex_unlock(&m));
}
bool try_lock()
{
int const res=pthread_mutex_trylock(&m);
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
bool timed_lock(system_time const & abs_time)
{
struct timespec const timeout=detail::get_timespec(abs_time);
int const res=pthread_mutex_timedlock(&m,&timeout);
BOOST_ASSERT(!res || res==ETIMEDOUT);
return !res;
}
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
return &m;
}
#else
void lock()
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
while(is_locked)
{
BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
}
is_locked=true;
}
void unlock()
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
is_locked=false;
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
bool try_lock()
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(is_locked)
{
return false;
}
is_locked=true;
return true;
}
bool timed_lock(system_time const & abs_time)
{
struct timespec const timeout=detail::get_timespec(abs_time);
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
while(is_locked)
{
int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
if(cond_res==ETIMEDOUT)
{
return false;
}
BOOST_ASSERT(!cond_res);
}
is_locked=true;
return true;
}
#endif
typedef unique_lock<timed_mutex> scoped_timed_lock;
typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,90 @@
#ifndef BOOST_THREAD_PTHREAD_ONCE_HPP
#define BOOST_THREAD_PTHREAD_ONCE_HPP
// once.hpp
//
// (C) Copyright 2007-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/config.hpp>
#include <pthread.h>
#include <boost/assert.hpp>
#include "pthread_mutex_scoped_lock.hpp"
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include <boost/cstdint.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
struct once_flag
{
boost::uintmax_t epoch;
};
namespace detail
{
BOOST_THREAD_DECL boost::uintmax_t& get_once_per_thread_epoch();
BOOST_THREAD_DECL extern boost::uintmax_t once_global_epoch;
BOOST_THREAD_DECL extern pthread_mutex_t once_epoch_mutex;
BOOST_THREAD_DECL extern pthread_cond_t once_epoch_cv;
}
#define BOOST_ONCE_INITIAL_FLAG_VALUE 0
#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
// Based on Mike Burrows fast_pthread_once algorithm as described in
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html
template<typename Function>
void call_once(once_flag& flag,Function f)
{
static boost::uintmax_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
static boost::uintmax_t const being_initialized=uninitialized_flag+1;
boost::uintmax_t const epoch=flag.epoch;
boost::uintmax_t& this_thread_epoch=detail::get_once_per_thread_epoch();
if(epoch<this_thread_epoch)
{
pthread::pthread_mutex_scoped_lock lk(&detail::once_epoch_mutex);
while(flag.epoch<=being_initialized)
{
if(flag.epoch==uninitialized_flag)
{
flag.epoch=being_initialized;
try
{
pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex);
f();
}
catch(...)
{
flag.epoch=uninitialized_flag;
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
throw;
}
flag.epoch=--detail::once_global_epoch;
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
}
else
{
while(flag.epoch==being_initialized)
{
BOOST_VERIFY(!pthread_cond_wait(&detail::once_epoch_cv,&detail::once_epoch_mutex));
}
}
}
this_thread_epoch=detail::once_global_epoch;
}
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,54 @@
#ifndef BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP
#define BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP
// (C) Copyright 2007-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <pthread.h>
#include <boost/assert.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace pthread
{
class pthread_mutex_scoped_lock
{
pthread_mutex_t* m;
public:
explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_):
m(m_)
{
BOOST_VERIFY(!pthread_mutex_lock(m));
}
~pthread_mutex_scoped_lock()
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
}
};
class pthread_mutex_scoped_unlock
{
pthread_mutex_t* m;
public:
explicit pthread_mutex_scoped_unlock(pthread_mutex_t* m_):
m(m_)
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
}
~pthread_mutex_scoped_unlock()
{
BOOST_VERIFY(!pthread_mutex_lock(m));
}
};
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,266 @@
#ifndef BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
// (C) Copyright 2007-8 Anthony Williams
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <pthread.h>
#include <boost/utility.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/assert.hpp>
#ifndef _WIN32
#include <unistd.h>
#endif
#include <boost/date_time/posix_time/conversion.hpp>
#include <errno.h>
#include "timespec.hpp"
#include "pthread_mutex_scoped_lock.hpp"
#ifdef _POSIX_TIMEOUTS
#if _POSIX_TIMEOUTS >= 0
#define BOOST_PTHREAD_HAS_TIMEDLOCK
#endif
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class recursive_mutex:
boost::noncopyable
{
private:
pthread_mutex_t m;
public:
recursive_mutex()
{
pthread_mutexattr_t attr;
int const init_attr_res=pthread_mutexattr_init(&attr);
if(init_attr_res)
{
throw thread_resource_error();
}
int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
if(set_attr_res)
{
throw thread_resource_error();
}
int const res=pthread_mutex_init(&m,&attr);
if(res)
{
throw thread_resource_error();
}
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
}
~recursive_mutex()
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
}
void lock()
{
BOOST_VERIFY(!pthread_mutex_lock(&m));
}
void unlock()
{
BOOST_VERIFY(!pthread_mutex_unlock(&m));
}
bool try_lock()
{
int const res=pthread_mutex_trylock(&m);
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
return &m;
}
typedef unique_lock<recursive_mutex> scoped_lock;
typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
};
typedef recursive_mutex recursive_try_mutex;
class recursive_timed_mutex:
boost::noncopyable
{
private:
pthread_mutex_t m;
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
pthread_cond_t cond;
bool is_locked;
pthread_t owner;
unsigned count;
#endif
public:
recursive_timed_mutex()
{
#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
pthread_mutexattr_t attr;
int const init_attr_res=pthread_mutexattr_init(&attr);
if(init_attr_res)
{
throw thread_resource_error();
}
int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
if(set_attr_res)
{
throw thread_resource_error();
}
int const res=pthread_mutex_init(&m,&attr);
if(res)
{
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
throw thread_resource_error();
}
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
#else
int const res=pthread_mutex_init(&m,NULL);
if(res)
{
throw thread_resource_error();
}
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
throw thread_resource_error();
}
is_locked=false;
count=0;
#endif
}
~recursive_timed_mutex()
{
BOOST_VERIFY(!pthread_mutex_destroy(&m));
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
BOOST_VERIFY(!pthread_cond_destroy(&cond));
#endif
}
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time)
{
return timed_lock(get_system_time()+relative_time);
}
#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
void lock()
{
BOOST_VERIFY(!pthread_mutex_lock(&m));
}
void unlock()
{
BOOST_VERIFY(!pthread_mutex_unlock(&m));
}
bool try_lock()
{
int const res=pthread_mutex_trylock(&m);
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
bool timed_lock(system_time const & abs_time)
{
struct timespec const timeout=detail::get_timespec(abs_time);
int const res=pthread_mutex_timedlock(&m,&timeout);
BOOST_ASSERT(!res || res==ETIMEDOUT);
return !res;
}
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
return &m;
}
#else
void lock()
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(is_locked && pthread_equal(owner,pthread_self()))
{
++count;
return;
}
while(is_locked)
{
BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
}
is_locked=true;
++count;
owner=pthread_self();
}
void unlock()
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(!--count)
{
is_locked=false;
}
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
bool try_lock()
{
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(is_locked && !pthread_equal(owner,pthread_self()))
{
return false;
}
is_locked=true;
++count;
owner=pthread_self();
return true;
}
bool timed_lock(system_time const & abs_time)
{
struct timespec const timeout=detail::get_timespec(abs_time);
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(is_locked && pthread_equal(owner,pthread_self()))
{
++count;
return true;
}
while(is_locked)
{
int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
if(cond_res==ETIMEDOUT)
{
return false;
}
BOOST_ASSERT(!cond_res);
}
is_locked=true;
++count;
owner=pthread_self();
return true;
}
#endif
typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,303 @@
#ifndef BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
// (C) Copyright 2006-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class shared_mutex
{
private:
struct state_data
{
unsigned shared_count;
bool exclusive;
bool upgrade;
bool exclusive_waiting_blocked;
};
state_data state;
boost::mutex state_change;
boost::condition_variable shared_cond;
boost::condition_variable exclusive_cond;
boost::condition_variable upgrade_cond;
void release_waiters()
{
exclusive_cond.notify_one();
shared_cond.notify_all();
}
public:
shared_mutex()
{
state_data state_={0,0,0,0};
state=state_;
}
~shared_mutex()
{
}
void lock_shared()
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked)
{
shared_cond.wait(lk);
}
++state.shared_count;
}
bool try_lock_shared()
{
boost::mutex::scoped_lock lk(state_change);
if(state.exclusive || state.exclusive_waiting_blocked)
{
return false;
}
else
{
++state.shared_count;
return true;
}
}
bool timed_lock_shared(system_time const& timeout)
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked)
{
if(!shared_cond.timed_wait(lk,timeout))
{
return false;
}
}
++state.shared_count;
return true;
}
template<typename TimeDuration>
bool timed_lock_shared(TimeDuration const & relative_time)
{
return timed_lock_shared(get_system_time()+relative_time);
}
void unlock_shared()
{
boost::mutex::scoped_lock lk(state_change);
bool const last_reader=!--state.shared_count;
if(last_reader)
{
if(state.upgrade)
{
state.upgrade=false;
state.exclusive=true;
upgrade_cond.notify_one();
}
else
{
state.exclusive_waiting_blocked=false;
}
release_waiters();
}
}
void lock()
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=true;
exclusive_cond.wait(lk);
}
state.exclusive=true;
}
bool timed_lock(system_time const& timeout)
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=true;
if(!exclusive_cond.timed_wait(lk,timeout))
{
if(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=false;
exclusive_cond.notify_one();
return false;
}
break;
}
}
state.exclusive=true;
return true;
}
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time)
{
return timed_lock(get_system_time()+relative_time);
}
bool try_lock()
{
boost::mutex::scoped_lock lk(state_change);
if(state.shared_count || state.exclusive)
{
return false;
}
else
{
state.exclusive=true;
return true;
}
}
void unlock()
{
boost::mutex::scoped_lock lk(state_change);
state.exclusive=false;
state.exclusive_waiting_blocked=false;
release_waiters();
}
void lock_upgrade()
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
shared_cond.wait(lk);
}
++state.shared_count;
state.upgrade=true;
}
bool timed_lock_upgrade(system_time const& timeout)
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
if(!shared_cond.timed_wait(lk,timeout))
{
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
return false;
}
break;
}
}
++state.shared_count;
state.upgrade=true;
return true;
}
template<typename TimeDuration>
bool timed_lock_upgrade(TimeDuration const & relative_time)
{
return timed_lock(get_system_time()+relative_time);
}
bool try_lock_upgrade()
{
boost::mutex::scoped_lock lk(state_change);
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
return false;
}
else
{
++state.shared_count;
state.upgrade=true;
return true;
}
}
void unlock_upgrade()
{
boost::mutex::scoped_lock lk(state_change);
state.upgrade=false;
bool const last_reader=!--state.shared_count;
if(last_reader)
{
state.exclusive_waiting_blocked=false;
release_waiters();
}
}
void unlock_upgrade_and_lock()
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lk(state_change);
--state.shared_count;
while(state.shared_count)
{
upgrade_cond.wait(lk);
}
state.upgrade=false;
state.exclusive=true;
}
void unlock_and_lock_upgrade()
{
boost::mutex::scoped_lock lk(state_change);
state.exclusive=false;
state.upgrade=true;
++state.shared_count;
state.exclusive_waiting_blocked=false;
release_waiters();
}
void unlock_and_lock_shared()
{
boost::mutex::scoped_lock lk(state_change);
state.exclusive=false;
++state.shared_count;
state.exclusive_waiting_blocked=false;
release_waiters();
}
void unlock_upgrade_and_lock_shared()
{
boost::mutex::scoped_lock lk(state_change);
state.upgrade=false;
state.exclusive_waiting_blocked=false;
release_waiters();
}
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,118 @@
#ifndef BOOST_THREAD_PTHREAD_THREAD_DATA_HPP
#define BOOST_THREAD_PTHREAD_THREAD_DATA_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007 Anthony Williams
#include <boost/thread/detail/config.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/optional.hpp>
#include <pthread.h>
#include "condition_variable_fwd.hpp"
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class thread;
namespace detail
{
struct thread_exit_callback_node;
struct tss_data_node;
struct thread_data_base;
typedef boost::shared_ptr<thread_data_base> thread_data_ptr;
struct BOOST_THREAD_DECL thread_data_base:
enable_shared_from_this<thread_data_base>
{
thread_data_ptr self;
pthread_t thread_handle;
boost::mutex data_mutex;
boost::condition_variable done_condition;
boost::mutex sleep_mutex;
boost::condition_variable sleep_condition;
bool done;
bool join_started;
bool joined;
boost::detail::thread_exit_callback_node* thread_exit_callbacks;
boost::detail::tss_data_node* tss_data;
bool interrupt_enabled;
bool interrupt_requested;
pthread_cond_t* current_cond;
thread_data_base():
done(false),join_started(false),joined(false),
thread_exit_callbacks(0),tss_data(0),
interrupt_enabled(true),
interrupt_requested(false),
current_cond(0)
{}
virtual ~thread_data_base();
typedef pthread_t native_handle_type;
virtual void run()=0;
};
BOOST_THREAD_DECL thread_data_base* get_current_thread_data();
class interruption_checker
{
thread_data_base* const thread_info;
void check_for_interruption()
{
if(thread_info->interrupt_requested)
{
thread_info->interrupt_requested=false;
throw thread_interrupted();
}
}
void operator=(interruption_checker&);
public:
explicit interruption_checker(pthread_cond_t* cond):
thread_info(detail::get_current_thread_data())
{
if(thread_info && thread_info->interrupt_enabled)
{
lock_guard<mutex> guard(thread_info->data_mutex);
check_for_interruption();
thread_info->current_cond=cond;
}
}
~interruption_checker()
{
if(thread_info && thread_info->interrupt_enabled)
{
lock_guard<mutex> guard(thread_info->data_mutex);
thread_info->current_cond=NULL;
check_for_interruption();
}
}
};
}
namespace this_thread
{
void BOOST_THREAD_DECL yield();
void BOOST_THREAD_DECL sleep(system_time const& abs_time);
template<typename TimeDuration>
inline void sleep(TimeDuration const& rel_time)
{
this_thread::sleep(get_system_time()+rel_time);
}
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,242 @@
// Distributed under the 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 2008 Anthony Williams
#ifndef THREAD_HEAP_ALLOC_PTHREAD_HPP
#define THREAD_HEAP_ALLOC_PTHREAD_HPP
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
template<typename T>
inline T* heap_new()
{
return new T();
}
#ifdef BOOST_HAS_RVALUE_REFS
template<typename T,typename A1>
inline T* heap_new(A1&& a1)
{
return new T(static_cast<A1&&>(a1));
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1&& a1,A2&& a2)
{
return new T(static_cast<A1&&>(a1),static_cast<A2&&>(a2));
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1&& a1,A2&& a2,A3&& a3)
{
return new T(static_cast<A1&&>(a1),static_cast<A2&&>(a2),
static_cast<A3&&>(a3));
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1&& a1,A2&& a2,A3&& a3,A4&& a4)
{
return new T(static_cast<A1&&>(a1),static_cast<A2&&>(a2),
static_cast<A3&&>(a3),static_cast<A4&&>(a4));
}
#else
template<typename T,typename A1>
inline T* heap_new_impl(A1 a1)
{
return new T(a1);
}
template<typename T,typename A1,typename A2>
inline T* heap_new_impl(A1 a1,A2 a2)
{
return new T(a1,a2);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3)
{
return new T(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4)
{
return new T(a1,a2,a3,a4);
}
template<typename T,typename A1>
inline T* heap_new(A1 const& a1)
{
return heap_new_impl<T,A1 const&>(a1);
}
template<typename T,typename A1>
inline T* heap_new(A1& a1)
{
return heap_new_impl<T,A1&>(a1);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1 const& a1,A2 const& a2)
{
return heap_new_impl<T,A1 const&,A2 const&>(a1,a2);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1& a1,A2 const& a2)
{
return heap_new_impl<T,A1&,A2 const&>(a1,a2);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1 const& a1,A2& a2)
{
return heap_new_impl<T,A1 const&,A2&>(a1,a2);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1& a1,A2& a2)
{
return heap_new_impl<T,A1&,A2&>(a1,a2);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3)
{
return heap_new_impl<T,A1 const&,A2 const&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3)
{
return heap_new_impl<T,A1&,A2 const&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3)
{
return heap_new_impl<T,A1 const&,A2&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2& a2,A3 const& a3)
{
return heap_new_impl<T,A1&,A2&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3)
{
return heap_new_impl<T,A1 const&,A2 const&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2 const& a2,A3& a3)
{
return heap_new_impl<T,A1&,A2 const&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2& a2,A3& a3)
{
return heap_new_impl<T,A1 const&,A2&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2& a2,A3& a3)
{
return heap_new_impl<T,A1&,A2&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4);
}
#endif
template<typename T>
inline void heap_delete(T* data)
{
delete data;
}
template<typename T>
struct do_heap_delete
{
void operator()(T* data) const
{
detail::heap_delete(data);
}
};
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,36 @@
#ifndef BOOST_THREAD_PTHREAD_TIMESPEC_HPP
#define BOOST_THREAD_PTHREAD_TIMESPEC_HPP
// (C) Copyright 2007-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/thread_time.hpp>
#include <boost/date_time/posix_time/conversion.hpp>
#include <pthread.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
inline struct timespec get_timespec(boost::system_time const& abs_time)
{
struct timespec timeout={0,0};
boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0);
timeout.tv_sec=time_since_epoch.total_seconds();
timeout.tv_nsec=(long)(time_since_epoch.fractional_seconds()*(1000000000l/time_since_epoch.ticks_per_second()));
return timeout;
}
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,167 +1,21 @@
// Copyright (C) 2001
// William E. Kempf
#ifndef BOOST_THREAD_RECURSIVE_MUTEX_HPP
#define BOOST_THREAD_RECURSIVE_MUTEX_HPP
// recursive_mutex.hpp
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// (C) Copyright 2007 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_RECURSIVE_MUTEX_WEK070601_HPP
#define BOOST_RECURSIVE_MUTEX_WEK070601_HPP
#include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS
# error Thread support is unavailable!
#include <boost/thread/detail/platform.hpp>
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#include <boost/thread/win32/recursive_mutex.hpp>
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
#include <boost/thread/pthread/recursive_mutex.hpp>
#else
#error "Boost threads unavailable on this platform"
#endif
#include <boost/utility.hpp>
#include <boost/thread/detail/lock.hpp>
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
#endif
namespace boost {
class condition;
struct xtime;
class recursive_mutex : private noncopyable
{
public:
friend class detail::thread::scoped_lock<recursive_mutex>;
friend class condition;
typedef detail::thread::scoped_lock<recursive_mutex> scoped_lock;
recursive_mutex();
~recursive_mutex();
private:
#if defined(BOOST_HAS_WINTHREADS)
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)
unsigned long m_mutex;
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
#endif
};
class recursive_try_mutex : private noncopyable
{
public:
friend class detail::thread::scoped_lock<recursive_try_mutex>;
friend class detail::thread::scoped_try_lock<recursive_try_mutex>;
friend class condition;
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)
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)
unsigned long m_mutex;
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
#endif
};
class recursive_timed_mutex : private noncopyable
{
public:
friend class detail::thread::scoped_lock<recursive_timed_mutex>;
friend class detail::thread::scoped_try_lock<recursive_timed_mutex>;
friend class detail::thread::scoped_timed_lock<recursive_timed_mutex>;
friend class condition;
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)
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)
unsigned long 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;
#endif
};
} // namespace boost
// 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.
#endif // BOOST_RECURSIVE_MUTEX_WEK070601_HPP

View File

@@ -1,57 +0,0 @@
// Copyright (C) 2001
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#ifndef BOOST_SEMAPHORE_WEK070601_HPP
#define BOOST_SEMAPHORE_WEK070601_HPP
#include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS
# error Thread support is unavailable!
#endif
#include <boost/utility.hpp>
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
#endif
namespace boost {
struct xtime;
class semaphore : private noncopyable
{
public:
explicit semaphore(unsigned count=0, unsigned max=0);
~semaphore();
bool up(unsigned count=1, unsigned* prev=0);
void down();
bool down(const xtime& xt);
private:
#if defined(BOOST_HAS_WINTHREADS)
unsigned long m_sema;
#elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex;
pthread_cond_t m_condition;
unsigned m_available;
unsigned m_max;
#endif
};
} // namespace boost
// Change Log:
// 8 Feb 01 WEKEMPF Initial version.
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
#endif // BOOST_SEMAPHORE_WEK070601_HPP

View File

@@ -0,0 +1,21 @@
#ifndef BOOST_THREAD_SHARED_MUTEX_HPP
#define BOOST_THREAD_SHARED_MUTEX_HPP
// shared_mutex.hpp
//
// (C) Copyright 2007 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/platform.hpp>
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#include <boost/thread/win32/shared_mutex.hpp>
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
#include <boost/thread/pthread/shared_mutex.hpp>
#else
#error "Boost threads unavailable on this platform"
#endif
#endif

View File

@@ -1,84 +1,25 @@
// Copyright (C) 2001
// William E. Kempf
#ifndef BOOST_THREAD_THREAD_HPP
#define BOOST_THREAD_THREAD_HPP
// thread.hpp
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// (C) Copyright 2007-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_THREAD_WEK070601_HPP
#define BOOST_THREAD_WEK070601_HPP
#include <boost/thread/detail/platform.hpp>
#include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS
# error Thread support is unavailable!
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#include <boost/thread/win32/thread_data.hpp>
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
#include <boost/thread/pthread/thread_data.hpp>
#else
#error "Boost threads unavailable on this platform"
#endif
#include <boost/utility.hpp>
#include <boost/function.hpp>
#include <boost/thread/mutex.hpp>
#include <list>
#include <memory>
#include <boost/thread/detail/thread.hpp>
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
# include <boost/thread/condition.hpp>
#endif
namespace boost {
struct xtime;
class 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)
unsigned long m_thread;
unsigned int m_id;
#elif defined(BOOST_HAS_PTHREADS)
private:
pthread_t m_thread;
#endif
bool m_joinable;
};
class thread_group : private noncopyable
{
public:
thread_group();
~thread_group();
thread* create_thread(const function0<void>& threadfunc);
void add_thread(thread* thrd);
void remove_thread(thread* thrd);
void join_all();
private:
std::list<thread*> m_threads;
mutex m_mutex;
};
} // namespace boost
// Change Log:
// 8 Feb 01 WEKEMPF Initial version.
// 1 Jun 01 WEKEMPF Added boost::thread initial implementation.
// 3 Jul 01 WEKEMPF Redesigned boost::thread to be noncopyable.
#endif // BOOST_THREAD_WEK070601_HPP

View File

@@ -0,0 +1,50 @@
#ifndef BOOST_THREAD_TIME_HPP
#define BOOST_THREAD_TIME_HPP
// (C) Copyright 2007 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/date_time/microsec_time_clock.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
typedef boost::posix_time::ptime system_time;
inline system_time get_system_time()
{
return boost::date_time::microsec_clock<system_time>::universal_time();
}
namespace detail
{
inline system_time get_system_time_sentinel()
{
return system_time(boost::posix_time::pos_infin);
}
inline unsigned long get_milliseconds_until(system_time const& target_time)
{
if(target_time.is_pos_infinity())
{
return ~(unsigned long)0;
}
system_time const now=get_system_time();
if(target_time<=now)
{
return 0;
}
return static_cast<unsigned long>((target_time-now).total_milliseconds()+1);
}
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,72 +1,111 @@
// Copyright (C) 2001
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#ifndef BOOST_TSS_WEK070601_HPP
#define BOOST_TSS_WEK070601_HPP
#include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS
# error Thread support is unavailable!
#endif
#include <boost/utility.hpp>
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
#endif
namespace boost {
namespace detail {
class tss : private noncopyable
{
public:
tss(void (*cleanup)(void*)=0);
~tss();
void* get() const;
bool set(void* value);
private:
#if defined(BOOST_HAS_WINTHREADS)
unsigned long m_key;
void (*m_cleanup)(void*);
#elif defined(BOOST_HAS_PTHREADS)
pthread_key_t m_key;
#endif
};
}
template <typename T>
class thread_specific_ptr : private noncopyable
{
public:
thread_specific_ptr() : m_tss(&thread_specific_ptr<T>::cleanup) { }
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(); m_tss.set(0); return temp; }
void reset(T* p=0) { T* cur = get(); if (cur == p) return; delete cur; m_tss.set(p); }
private:
static void cleanup(void* p) { delete static_cast<T*>(p); }
mutable detail::tss m_tss;
};
} // namespace boost
// Change Log:
// 6 Jun 01 WEKEMPF Initial version.
#endif // BOOST_TSS_WEK070601_HPP
#ifndef BOOST_THREAD_TSS_HPP
#define BOOST_THREAD_TSS_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
#include <boost/thread/detail/config.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/detail/thread_heap_alloc.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
struct tss_cleanup_function
{
virtual ~tss_cleanup_function()
{}
virtual void operator()(void* data)=0;
};
BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
BOOST_THREAD_DECL void* get_tss_data(void const* key);
}
template <typename T>
class thread_specific_ptr
{
private:
thread_specific_ptr(thread_specific_ptr&);
thread_specific_ptr& operator=(thread_specific_ptr&);
struct delete_data:
detail::tss_cleanup_function
{
void operator()(void* data)
{
delete static_cast<T*>(data);
}
};
struct run_custom_cleanup_function:
detail::tss_cleanup_function
{
void (*cleanup_function)(T*);
explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)):
cleanup_function(cleanup_function_)
{}
void operator()(void* data)
{
cleanup_function(static_cast<T*>(data));
}
};
boost::shared_ptr<detail::tss_cleanup_function> cleanup;
public:
thread_specific_ptr():
cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
{}
explicit thread_specific_ptr(void (*func_)(T*))
{
if(func_)
{
cleanup.reset(detail::heap_new<run_custom_cleanup_function>(func_),detail::do_heap_delete<run_custom_cleanup_function>());
}
}
~thread_specific_ptr()
{
reset();
}
T* get() const
{
return static_cast<T*>(detail::get_tss_data(this));
}
T* operator->() const
{
return get();
}
T& operator*() const
{
return *get();
}
T* release()
{
T* const temp=get();
detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,false);
return temp;
}
void reset(T* new_value=0)
{
T* const current_value=get();
if(current_value!=new_value)
{
detail::set_tss_data(this,cleanup,new_value,true);
}
}
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

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

View File

@@ -0,0 +1,178 @@
#ifndef BOOST_BASIC_TIMED_MUTEX_WIN32_HPP
#define BOOST_BASIC_TIMED_MUTEX_WIN32_HPP
// basic_timed_mutex_win32.hpp
//
// (C) Copyright 2006-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/assert.hpp>
#include "thread_primitives.hpp"
#include "interlocked_read.hpp"
#include <boost/thread/thread_time.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/detail/interlocked.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
struct basic_timed_mutex
{
BOOST_STATIC_CONSTANT(unsigned char,lock_flag_bit=31);
BOOST_STATIC_CONSTANT(unsigned char,event_set_flag_bit=30);
BOOST_STATIC_CONSTANT(long,lock_flag_value=1<<lock_flag_bit);
BOOST_STATIC_CONSTANT(long,event_set_flag_value=1<<event_set_flag_bit);
long active_count;
void* event;
void initialize()
{
active_count=0;
event=0;
}
void destroy()
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4312)
#endif
void* const old_event=BOOST_INTERLOCKED_EXCHANGE_POINTER(&event,0);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
if(old_event)
{
win32::CloseHandle(old_event);
}
}
bool try_lock()
{
return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit);
}
void lock()
{
BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
}
bool timed_lock(::boost::system_time const& wait_until)
{
if(!win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit))
{
return true;
}
long old_count=active_count;
for(;;)
{
long const new_count=(old_count&lock_flag_value)?(old_count+1):(old_count|lock_flag_value);
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
if(current==old_count)
{
break;
}
old_count=current;
}
if(old_count&lock_flag_value)
{
bool lock_acquired=false;
void* const sem=get_event();
do
{
if(win32::WaitForSingleObject(sem,::boost::detail::get_milliseconds_until(wait_until))!=0)
{
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
}
old_count&=~lock_flag_value;
old_count|=event_set_flag_value;
for(;;)
{
long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value;
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
if(current==old_count)
{
break;
}
old_count=current;
}
lock_acquired=!(old_count&lock_flag_value);
}
while(!lock_acquired);
}
return true;
}
template<typename Duration>
bool timed_lock(Duration const& timeout)
{
return timed_lock(get_system_time()+timeout);
}
bool timed_lock(boost::xtime const& timeout)
{
return timed_lock(system_time(timeout));
}
void unlock()
{
long const offset=lock_flag_value;
long const old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,lock_flag_value);
if(!(old_count&event_set_flag_value) && (old_count>offset))
{
if(!win32::interlocked_bit_test_and_set(&active_count,event_set_flag_bit))
{
win32::SetEvent(get_event());
}
}
}
private:
void* get_event()
{
void* current_event=::boost::detail::interlocked_read_acquire(&event);
if(!current_event)
{
void* const new_event=win32::create_anonymous_event(win32::auto_reset_event,win32::event_initially_reset);
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4311)
#pragma warning(disable:4312)
#endif
void* const old_event=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&event,new_event,0);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
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}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,418 @@
#ifndef BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP
#define BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
#include <boost/thread/mutex.hpp>
#include "thread_primitives.hpp"
#include <limits.h>
#include <boost/assert.hpp>
#include <algorithm>
#include <boost/thread/thread.hpp>
#include <boost/thread/thread_time.hpp>
#include "interlocked_read.hpp"
#include <boost/thread/xtime.hpp>
#include <vector>
#include <boost/intrusive_ptr.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
class basic_cv_list_entry;
void intrusive_ptr_add_ref(basic_cv_list_entry * p);
void intrusive_ptr_release(basic_cv_list_entry * p);
class basic_cv_list_entry
{
private:
detail::win32::handle_manager semaphore;
detail::win32::handle_manager wake_sem;
long waiters;
bool notified;
long references;
basic_cv_list_entry(basic_cv_list_entry&);
void operator=(basic_cv_list_entry&);
public:
explicit basic_cv_list_entry(detail::win32::handle_manager const& wake_sem_):
semaphore(detail::win32::create_anonymous_semaphore(0,LONG_MAX)),
wake_sem(wake_sem_.duplicate()),
waiters(1),notified(false),references(0)
{}
static bool no_waiters(boost::intrusive_ptr<basic_cv_list_entry> const& entry)
{
return !detail::interlocked_read_acquire(&entry->waiters);
}
void add_waiter()
{
BOOST_INTERLOCKED_INCREMENT(&waiters);
}
void remove_waiter()
{
BOOST_INTERLOCKED_DECREMENT(&waiters);
}
void release(unsigned count_to_release)
{
notified=true;
detail::win32::ReleaseSemaphore(semaphore,count_to_release,0);
}
void release_waiters()
{
release(detail::interlocked_read_acquire(&waiters));
}
bool is_notified() const
{
return notified;
}
bool wait(timeout wait_until)
{
return this_thread::interruptible_wait(semaphore,wait_until);
}
bool woken()
{
unsigned long const woken_result=detail::win32::WaitForSingleObject(wake_sem,0);
BOOST_ASSERT((woken_result==detail::win32::timeout) || (woken_result==0));
return woken_result==0;
}
friend void intrusive_ptr_add_ref(basic_cv_list_entry * p);
friend void intrusive_ptr_release(basic_cv_list_entry * p);
};
inline void intrusive_ptr_add_ref(basic_cv_list_entry * p)
{
BOOST_INTERLOCKED_INCREMENT(&p->references);
}
inline void intrusive_ptr_release(basic_cv_list_entry * p)
{
if(!BOOST_INTERLOCKED_DECREMENT(&p->references))
{
delete p;
}
}
class basic_condition_variable
{
boost::mutex internal_mutex;
long total_count;
unsigned active_generation_count;
typedef basic_cv_list_entry list_entry;
typedef boost::intrusive_ptr<list_entry> entry_ptr;
typedef std::vector<entry_ptr> generation_list;
generation_list generations;
detail::win32::handle_manager wake_sem;
void wake_waiters(long count_to_wake)
{
detail::interlocked_write_release(&total_count,total_count-count_to_wake);
detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0);
}
template<typename lock_type>
struct relocker
{
lock_type& lock;
bool unlocked;
relocker(lock_type& lock_):
lock(lock_),unlocked(false)
{}
void unlock()
{
lock.unlock();
unlocked=true;
}
~relocker()
{
if(unlocked)
{
lock.lock();
}
}
private:
relocker(relocker&);
void operator=(relocker&);
};
entry_ptr get_wait_entry()
{
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
if(!wake_sem)
{
wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
BOOST_ASSERT(wake_sem);
}
detail::interlocked_write_release(&total_count,total_count+1);
if(generations.empty() || generations.back()->is_notified())
{
entry_ptr new_entry(new list_entry(wake_sem));
generations.push_back(new_entry);
return new_entry;
}
else
{
generations.back()->add_waiter();
return generations.back();
}
}
struct entry_manager
{
entry_ptr const entry;
entry_manager(entry_ptr const& entry_):
entry(entry_)
{}
~entry_manager()
{
entry->remove_waiter();
}
list_entry* operator->()
{
return entry.get();
}
private:
void operator=(entry_manager&);
entry_manager(entry_manager&);
};
protected:
template<typename lock_type>
bool do_wait(lock_type& lock,timeout wait_until)
{
relocker<lock_type> locker(lock);
entry_manager entry(get_wait_entry());
locker.unlock();
bool woken=false;
while(!woken)
{
if(!entry->wait(wait_until))
{
return false;
}
woken=entry->woken();
}
return woken;
}
template<typename lock_type,typename predicate_type>
bool do_wait(lock_type& m,timeout const& wait_until,predicate_type pred)
{
while (!pred())
{
if(!do_wait(m, wait_until))
return pred();
}
return true;
}
basic_condition_variable(const basic_condition_variable& other);
basic_condition_variable& operator=(const basic_condition_variable& other);
public:
basic_condition_variable():
total_count(0),active_generation_count(0),wake_sem(0)
{}
~basic_condition_variable()
{}
void notify_one()
{
if(detail::interlocked_read_acquire(&total_count))
{
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
if(!total_count)
{
return;
}
wake_waiters(1);
for(generation_list::iterator it=generations.begin(),
end=generations.end();
it!=end;++it)
{
(*it)->release(1);
}
generations.erase(std::remove_if(generations.begin(),generations.end(),&basic_cv_list_entry::no_waiters),generations.end());
}
}
void notify_all()
{
if(detail::interlocked_read_acquire(&total_count))
{
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
if(!total_count)
{
return;
}
wake_waiters(total_count);
for(generation_list::iterator it=generations.begin(),
end=generations.end();
it!=end;++it)
{
(*it)->release_waiters();
}
generations.clear();
wake_sem=detail::win32::handle(0);
}
}
};
}
class condition_variable:
private detail::basic_condition_variable
{
private:
condition_variable(condition_variable&);
void operator=(condition_variable&);
public:
condition_variable()
{}
using detail::basic_condition_variable::notify_one;
using detail::basic_condition_variable::notify_all;
void wait(unique_lock<mutex>& m)
{
do_wait(m,detail::timeout::sentinel());
}
template<typename predicate_type>
void wait(unique_lock<mutex>& m,predicate_type pred)
{
while(!pred()) wait(m);
}
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until)
{
return do_wait(m,wait_until);
}
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& wait_until)
{
return do_wait(m,system_time(wait_until));
}
template<typename duration_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration)
{
return do_wait(m,wait_duration.total_milliseconds());
}
template<typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until,predicate_type pred)
{
return do_wait(m,wait_until,pred);
}
template<typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& wait_until,predicate_type pred)
{
return do_wait(m,system_time(wait_until),pred);
}
template<typename duration_type,typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
{
return do_wait(m,wait_duration.total_milliseconds(),pred);
}
};
class condition_variable_any:
private detail::basic_condition_variable
{
private:
condition_variable_any(condition_variable_any&);
void operator=(condition_variable_any&);
public:
condition_variable_any()
{}
using detail::basic_condition_variable::notify_one;
using detail::basic_condition_variable::notify_all;
template<typename lock_type>
void wait(lock_type& m)
{
do_wait(m,detail::timeout::sentinel());
}
template<typename lock_type,typename predicate_type>
void wait(lock_type& m,predicate_type pred)
{
while(!pred()) wait(m);
}
template<typename lock_type>
bool timed_wait(lock_type& m,boost::system_time const& wait_until)
{
return do_wait(m,wait_until);
}
template<typename lock_type>
bool timed_wait(lock_type& m,boost::xtime const& wait_until)
{
return do_wait(m,system_time(wait_until));
}
template<typename lock_type,typename duration_type>
bool timed_wait(lock_type& m,duration_type const& wait_duration)
{
return do_wait(m,wait_duration.total_milliseconds());
}
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred)
{
return do_wait(m,wait_until,pred);
}
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,boost::xtime const& wait_until,predicate_type pred)
{
return do_wait(m,system_time(wait_until),pred);
}
template<typename lock_type,typename duration_type,typename predicate_type>
bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
{
return do_wait(m,wait_duration.total_milliseconds(),pred);
}
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,80 @@
#ifndef BOOST_THREAD_DETAIL_INTERLOCKED_READ_WIN32_HPP
#define BOOST_THREAD_DETAIL_INTERLOCKED_READ_WIN32_HPP
// interlocked_read_win32.hpp
//
// (C) Copyright 2005-8 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/config/abi_prefix.hpp>
#ifdef BOOST_MSVC
extern "C" void _ReadWriteBarrier(void);
#pragma intrinsic(_ReadWriteBarrier)
namespace boost
{
namespace detail
{
inline long interlocked_read_acquire(long volatile* x)
{
long const res=*x;
_ReadWriteBarrier();
return res;
}
inline void* interlocked_read_acquire(void* volatile* x)
{
void* const res=*x;
_ReadWriteBarrier();
return res;
}
inline void interlocked_write_release(long volatile* x,long value)
{
_ReadWriteBarrier();
*x=value;
}
inline void interlocked_write_release(void* volatile* x,void* value)
{
_ReadWriteBarrier();
*x=value;
}
}
}
#else
namespace boost
{
namespace detail
{
inline long interlocked_read_acquire(long volatile* x)
{
return BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,0,0);
}
inline void* interlocked_read_acquire(void* volatile* x)
{
return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(x,0,0);
}
inline void interlocked_write_release(long volatile* x,long value)
{
BOOST_INTERLOCKED_EXCHANGE(x,value);
}
inline void interlocked_write_release(void* volatile* x,void* value)
{
BOOST_INTERLOCKED_EXCHANGE_POINTER(x,value);
}
}
}
#endif
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,65 @@
#ifndef BOOST_THREAD_WIN32_MUTEX_HPP
#define BOOST_THREAD_WIN32_MUTEX_HPP
// (C) Copyright 2005-7 Anthony Williams
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "basic_timed_mutex.hpp"
#include <boost/utility.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
typedef ::boost::detail::basic_timed_mutex underlying_mutex;
}
class mutex:
boost::noncopyable,
public ::boost::detail::underlying_mutex
{
public:
mutex()
{
initialize();
}
~mutex()
{
destroy();
}
typedef unique_lock<mutex> scoped_lock;
typedef detail::try_lock_wrapper<mutex> scoped_try_lock;
};
typedef mutex try_mutex;
class timed_mutex:
boost::noncopyable,
public ::boost::detail::basic_timed_mutex
{
public:
timed_mutex()
{
initialize();
}
~timed_mutex()
{
destroy();
}
typedef unique_lock<timed_mutex> scoped_timed_lock;
typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,136 @@
#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>
#include <boost/config/abi_prefix.hpp>
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std
{
using ::memcpy;
using ::ptrdiff_t;
}
#endif
namespace boost
{
typedef long once_flag;
#define BOOST_ONCE_INIT 0
namespace detail
{
struct win32_mutex_scoped_lock
{
void* const mutex_handle;
explicit win32_mutex_scoped_lock(void* mutex_handle_):
mutex_handle(mutex_handle_)
{
BOOST_VERIFY(!win32::WaitForSingleObject(mutex_handle,win32::infinite));
}
~win32_mutex_scoped_lock()
{
BOOST_VERIFY(win32::ReleaseMutex(mutex_handle)!=0);
}
private:
void operator=(win32_mutex_scoped_lock&);
};
#ifdef BOOST_NO_ANSI_APIS
template <class I>
void int_to_string(I p, wchar_t* buf)
{
for(unsigned i=0; i < sizeof(I)*2; ++i,++buf)
{
*buf = L'A' + static_cast<wchar_t>((p >> (i*4)) & 0x0f);
}
*buf = 0;
}
#else
template <class I>
void int_to_string(I p, char* buf)
{
for(unsigned i=0; i < sizeof(I)*2; ++i,++buf)
{
*buf = 'A' + static_cast<char>((p >> (i*4)) & 0x0f);
}
*buf = 0;
}
#endif
// create a named mutex. It doesn't really matter what this name is
// as long as it is unique both to this process, and to the address of "flag":
inline void* create_once_mutex(void* flag_address)
{
#ifdef BOOST_NO_ANSI_APIS
typedef wchar_t char_type;
static const char_type fixed_mutex_name[]=L"{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
#else
typedef char char_type;
static const char_type fixed_mutex_name[]="{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
#endif
unsigned const once_mutex_name_fixed_buffer_size=sizeof(fixed_mutex_name)/sizeof(char_type);
unsigned const once_mutex_name_fixed_length=once_mutex_name_fixed_buffer_size-1;
unsigned const once_mutex_name_length=once_mutex_name_fixed_buffer_size+sizeof(void*)*2+sizeof(unsigned long)*2;
char_type mutex_name[once_mutex_name_length];
std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name));
BOOST_STATIC_ASSERT(sizeof(void*) == sizeof(std::ptrdiff_t));
detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address), mutex_name + once_mutex_name_fixed_length);
detail::int_to_string(win32::GetCurrentProcessId(), mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2);
#ifdef BOOST_NO_ANSI_APIS
return win32::CreateMutexW(0, 0, mutex_name);
#else
return win32::CreateMutexA(0, 0, mutex_name);
#endif
}
}
template<typename Function>
void call_once(once_flag& flag,Function f)
{
// Try for a quick win: if the procedure has already been called
// just skip through:
long const function_complete_flag_value=0xc15730e2;
if(::boost::detail::interlocked_read_acquire(&flag)!=function_complete_flag_value)
{
void* const mutex_handle(::boost::detail::create_once_mutex(&flag));
BOOST_ASSERT(mutex_handle);
detail::win32::handle_manager const closer(mutex_handle);
detail::win32_mutex_scoped_lock const lock(mutex_handle);
if(flag!=function_complete_flag_value)
{
f();
BOOST_INTERLOCKED_EXCHANGE(&flag,function_complete_flag_value);
}
}
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,64 @@
#ifndef BOOST_RECURSIVE_MUTEX_WIN32_HPP
#define BOOST_RECURSIVE_MUTEX_WIN32_HPP
// recursive_mutex.hpp
//
// (C) Copyright 2006-7 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/utility.hpp>
#include "basic_recursive_mutex.hpp"
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class recursive_mutex:
boost::noncopyable,
public ::boost::detail::basic_recursive_mutex
{
public:
recursive_mutex()
{
::boost::detail::basic_recursive_mutex::initialize();
}
~recursive_mutex()
{
::boost::detail::basic_recursive_mutex::destroy();
}
typedef unique_lock<recursive_mutex> scoped_lock;
typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
};
typedef recursive_mutex recursive_try_mutex;
class recursive_timed_mutex:
boost::noncopyable,
public ::boost::detail::basic_recursive_timed_mutex
{
public:
recursive_timed_mutex()
{
::boost::detail::basic_recursive_timed_mutex::initialize();
}
~recursive_timed_mutex()
{
::boost::detail::basic_recursive_timed_mutex::destroy();
}
typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,566 @@
#ifndef BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
#define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
// (C) Copyright 2006-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/assert.hpp>
#include <boost/detail/interlocked.hpp>
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/static_assert.hpp>
#include <limits.h>
#include <boost/utility.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class shared_mutex:
private boost::noncopyable
{
private:
struct state_data
{
unsigned shared_count:11,
shared_waiting:11,
exclusive:1,
upgrade:1,
exclusive_waiting:7,
exclusive_waiting_blocked:1;
friend bool operator==(state_data const& lhs,state_data const& rhs)
{
return *reinterpret_cast<unsigned const*>(&lhs)==*reinterpret_cast<unsigned const*>(&rhs);
}
};
template<typename T>
T interlocked_compare_exchange(T* target,T new_value,T comparand)
{
BOOST_STATIC_ASSERT(sizeof(T)==sizeof(long));
long const res=BOOST_INTERLOCKED_COMPARE_EXCHANGE(reinterpret_cast<long*>(target),
*reinterpret_cast<long*>(&new_value),
*reinterpret_cast<long*>(&comparand));
return *reinterpret_cast<T const*>(&res);
}
state_data state;
detail::win32::handle semaphores[2];
detail::win32::handle &unlock_sem;
detail::win32::handle &exclusive_sem;
detail::win32::handle upgrade_sem;
void release_waiters(state_data old_state)
{
if(old_state.exclusive_waiting)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(exclusive_sem,1,0)!=0);
}
if(old_state.shared_waiting || old_state.exclusive_waiting)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(unlock_sem,old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
}
}
public:
shared_mutex():
unlock_sem(semaphores[0]),
exclusive_sem(semaphores[1])
{
unlock_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
exclusive_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
upgrade_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
state_data state_={0};
state=state_;
}
~shared_mutex()
{
detail::win32::CloseHandle(upgrade_sem);
detail::win32::CloseHandle(unlock_sem);
detail::win32::CloseHandle(exclusive_sem);
}
bool try_lock_shared()
{
state_data old_state=state;
for(;;)
{
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;
}
return !(old_state.exclusive| old_state.exclusive_waiting_blocked);
}
void lock_shared()
{
BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel()));
}
template<typename TimeDuration>
bool timed_lock_shared(TimeDuration const & relative_time)
{
return timed_lock_shared(get_system_time()+relative_time);
}
bool timed_lock_shared(boost::system_time const& wait_until)
{
for(;;)
{
state_data old_state=state;
for(;;)
{
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;
}
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
return true;
}
unsigned long const res=detail::win32::WaitForSingleObject(unlock_sem,::boost::detail::get_milliseconds_until(wait_until));
if(res==detail::win32::timeout)
{
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
{
if(new_state.shared_waiting)
{
--new_state.shared_waiting;
}
}
else
{
++new_state.shared_count;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
return true;
}
return false;
}
BOOST_ASSERT(res==0);
}
}
void unlock_shared()
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
bool const last_reader=!--new_state.shared_count;
if(last_reader)
{
if(new_state.upgrade)
{
new_state.upgrade=false;
new_state.exclusive=true;
}
else
{
if(new_state.exclusive_waiting)
{
--new_state.exclusive_waiting;
new_state.exclusive_waiting_blocked=false;
}
new_state.shared_waiting=0;
}
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
if(last_reader)
{
if(old_state.upgrade)
{
BOOST_VERIFY(detail::win32::ReleaseSemaphore(upgrade_sem,1,0)!=0);
}
else
{
release_waiters(old_state);
}
}
break;
}
old_state=current_state;
}
}
void lock()
{
BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
}
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time)
{
return timed_lock(get_system_time()+relative_time);
}
bool try_lock()
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
return false;
}
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;
}
return true;
}
bool timed_lock(boost::system_time const& wait_until)
{
for(;;)
{
state_data old_state=state;
for(;;)
{
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;
}
if(!old_state.shared_count && !old_state.exclusive)
{
return true;
}
unsigned long const wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,true,::boost::detail::get_milliseconds_until(wait_until));
if(wait_res==detail::win32::timeout)
{
for(;;)
{
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
if(new_state.exclusive_waiting)
{
if(!--new_state.exclusive_waiting)
{
new_state.exclusive_waiting_blocked=false;
}
}
}
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;
}
if(!old_state.shared_count && !old_state.exclusive)
{
return true;
}
return false;
}
BOOST_ASSERT(wait_res<2);
}
}
void unlock()
{
state_data old_state=state;
for(;;)
{
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;
}
release_waiters(old_state);
}
void lock_upgrade()
{
for(;;)
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
{
++new_state.shared_waiting;
}
else
{
++new_state.shared_count;
new_state.upgrade=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
if(!(old_state.exclusive|| old_state.exclusive_waiting_blocked|| old_state.upgrade))
{
return;
}
BOOST_VERIFY(!detail::win32::WaitForSingleObject(unlock_sem,detail::win32::infinite));
}
}
bool try_lock_upgrade()
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
{
return false;
}
else
{
++new_state.shared_count;
new_state.upgrade=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
return true;
}
void unlock_upgrade()
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
new_state.upgrade=false;
bool const last_reader=!--new_state.shared_count;
if(last_reader)
{
if(new_state.exclusive_waiting)
{
--new_state.exclusive_waiting;
new_state.exclusive_waiting_blocked=false;
}
new_state.shared_waiting=0;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
if(last_reader)
{
release_waiters(old_state);
}
break;
}
old_state=current_state;
}
}
void unlock_upgrade_and_lock()
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
bool const last_reader=!--new_state.shared_count;
if(last_reader)
{
new_state.upgrade=false;
new_state.exclusive=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
if(!last_reader)
{
BOOST_VERIFY(!detail::win32::WaitForSingleObject(upgrade_sem,detail::win32::infinite));
}
break;
}
old_state=current_state;
}
}
void unlock_and_lock_upgrade()
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
new_state.exclusive=false;
new_state.upgrade=true;
++new_state.shared_count;
if(new_state.exclusive_waiting)
{
--new_state.exclusive_waiting;
new_state.exclusive_waiting_blocked=false;
}
new_state.shared_waiting=0;
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
release_waiters(old_state);
}
void unlock_and_lock_shared()
{
state_data old_state=state;
for(;;)
{
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;
}
release_waiters(old_state);
}
void unlock_upgrade_and_lock_shared()
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
new_state.upgrade=false;
if(new_state.exclusive_waiting)
{
--new_state.exclusive_waiting;
new_state.exclusive_waiting_blocked=false;
}
new_state.shared_waiting=0;
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
release_waiters(old_state);
}
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,178 @@
#ifndef BOOST_THREAD_PTHREAD_THREAD_DATA_HPP
#define BOOST_THREAD_PTHREAD_THREAD_DATA_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2008 Anthony Williams
#include <boost/thread/detail/config.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/thread/thread_time.hpp>
#include "thread_primitives.hpp"
#include "thread_heap_alloc.hpp"
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
struct thread_exit_callback_node;
struct tss_data_node;
struct thread_data_base;
void intrusive_ptr_add_ref(thread_data_base * p);
void intrusive_ptr_release(thread_data_base * p);
struct thread_data_base
{
long count;
detail::win32::handle_manager thread_handle;
detail::win32::handle_manager interruption_handle;
boost::detail::thread_exit_callback_node* thread_exit_callbacks;
boost::detail::tss_data_node* tss_data;
bool interruption_enabled;
unsigned id;
thread_data_base():
count(0),thread_handle(detail::win32::invalid_handle_value),
interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)),
thread_exit_callbacks(0),tss_data(0),
interruption_enabled(true),
id(0)
{}
virtual ~thread_data_base()
{}
friend void intrusive_ptr_add_ref(thread_data_base * p)
{
BOOST_INTERLOCKED_INCREMENT(&p->count);
}
friend void intrusive_ptr_release(thread_data_base * p)
{
if(!BOOST_INTERLOCKED_DECREMENT(&p->count))
{
detail::heap_delete(p);
}
}
void interrupt()
{
BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0);
}
typedef detail::win32::handle native_handle_type;
virtual void run()=0;
};
typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr;
struct timeout
{
unsigned long start;
uintmax_t milliseconds;
bool relative;
boost::system_time abs_time;
static unsigned long const max_non_infinite_wait=0xfffffffe;
timeout(uintmax_t milliseconds_):
start(win32::GetTickCount()),
milliseconds(milliseconds_),
relative(true),
abs_time(boost::get_system_time())
{}
timeout(boost::system_time const& abs_time_):
start(win32::GetTickCount()),
milliseconds(0),
relative(false),
abs_time(abs_time_)
{}
struct remaining_time
{
bool more;
unsigned long milliseconds;
remaining_time(uintmax_t remaining):
more(remaining>max_non_infinite_wait),
milliseconds(more?max_non_infinite_wait:(unsigned long)remaining)
{}
};
remaining_time remaining_milliseconds() const
{
if(is_sentinel())
{
return remaining_time(win32::infinite);
}
else if(relative)
{
unsigned long const now=win32::GetTickCount();
unsigned long const elapsed=now-start;
return remaining_time((elapsed<milliseconds)?(milliseconds-elapsed):0);
}
else
{
system_time const now=get_system_time();
if(abs_time<=now)
{
return remaining_time(0);
}
return remaining_time((abs_time-now).total_milliseconds()+1);
}
}
bool is_sentinel() const
{
return milliseconds==~uintmax_t(0);
}
static timeout sentinel()
{
return timeout(sentinel_type());
}
private:
struct sentinel_type
{};
explicit timeout(sentinel_type):
start(0),milliseconds(~uintmax_t(0)),relative(true)
{}
};
}
namespace this_thread
{
void BOOST_THREAD_DECL yield();
bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
inline void interruptible_wait(unsigned long milliseconds)
{
interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
}
inline void interruptible_wait(system_time const& abs_time)
{
interruptible_wait(detail::win32::invalid_handle_value,abs_time);
}
template<typename TimeDuration>
inline void sleep(TimeDuration const& rel_time)
{
interruptible_wait(static_cast<unsigned long>(rel_time.total_milliseconds()));
}
inline void sleep(system_time const& abs_time)
{
interruptible_wait(abs_time);
}
}
}
#include <boost/config/abi_suffix.hpp>
#endif

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