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

Compare commits

...

319 Commits

Author SHA1 Message Date
nobody
1215b371c9 This commit was manufactured by cvs2svn to create tag
'Version_1_34_1_RC1'.

[SVN r38058]
2007-06-22 01:24:25 +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
Roland Schwarz
db2aaa04fd Merged from HEAD.
[SVN r36923]
2007-02-11 13:55:21 +00:00
Roland Schwarz
b48f9aa609 Merged patch from trunk.
[SVN r36921]
2007-02-11 13:14:44 +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
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
dfd865d67d Fixed missing tss_null file.
[SVN r36332]
2006-12-11 19:51:14 +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
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
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
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
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
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
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
Nicola Musatti
811a03f281 Updated Borland workaround
[SVN r33942]
2006-05-05 21:13:45 +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
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
161 changed files with 15451 additions and 7681 deletions

2
build/.cvsignore Normal file
View File

@@ -0,0 +1,2 @@
bin*
*.pdb

View File

@@ -1,49 +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)
{
if $(PTW32)
{
PTW32_REQUIREMENTS = <define>BOOST_HAS_PTHREADS <define>PtW32NoCatchWarn ;
}
else
{
dll libboost_threadmon : ../src/threadmon.cpp
# requirements
: <include>$(BOOST_ROOT)
<threading>multi
: debug release ;
}
}
# Base names of the source files for libboost_thread
CPP_SOURCES =
condition mutex recursive_mutex thread tss xtime once exceptions ;
lib libboost_thread : ../src/$(CPP_SOURCES).cpp
# requirements
: <include>$(BOOST_ROOT)
$(PTW32_REQUIREMENTS)
<threading>multi
: debug release ;

39
build/Jamfile.v2 Normal file
View File

@@ -0,0 +1,39 @@
# (C) Copyright Vladimir Prus, David Abrahams, Michael Stevens, Hartmut Kaiser,
# William E Kempf 2002-2006
# 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)
import os ;
project boost/thread
: source-location ../src
: requirements <link>shared:<define>BOOST_THREAD_BUILD_DLL=1 <threading>multi
: default-build <threading>multi
;
CPP_SOURCES =
barrier
condition
exceptions
mutex
once
recursive_mutex
# read_write_mutex
thread
tss_hooks
tss_dll
tss_pe
tss
xtime
;
lib boost_thread
: $(CPP_SOURCES).cpp
: <link>shared:<define>BOOST_THREAD_BUILD_DLL=1
<link>static:<define>BOOST_THREAD_BUILD_LIB=1
: # default build
: <link>shared:<define>BOOST_THREAD_BUILD_DLL=1
<link>static:<define>BOOST_THREAD_BUILD_LIB=1
;

11
doc/Jamfile.v2 Normal file
View File

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

View File

@@ -1,77 +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 summary="header" 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 &Egrave;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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p>&copy; <i>Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001</i></p>
</body>
</html>

73
doc/acknowledgements.xml Normal file
View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<section id="thread.acknowledgements"
last-revision="$Date$">
<title>Acknowledgements</title>
<para>William E. Kempf was the architect, designer, and implementor of
&Boost.Thread;.</para>
<para>Mac OS Carbon implementation written by Mac Murrett.</para>
<para>Dave Moore provided initial submissions and further comments on the
<code>barrier</code>
,
<code>thread_pool</code>
,
<code>read_write_mutex</code>
,
<code>read_write_try_mutex</code>
and
<code>read_write_timed_mutex</code>
classes.</para>
<para>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), Paul Mclachlan, Thomas Matelich and Iain Hanson (for help
in trying to get the build to work on other platforms), and Kevin S. Van
Horn (for several updates/corrections to the documentation).</para>
<para>Mike Glassford finished changes to &Boost.Thread; that were begun
by William Kempf and moved them into the main CVS branch.
He also addressed a number of issues that were brought up on the Boost
developer's mailing list and provided some additions and changes to the
read_write_mutex and related classes.</para>
<para>The documentation was written by William E. Kempf. Beman Dawes
provided additional documentation material and editing.
Mike Glassford finished William Kempf's conversion of the documentation to
BoostBook format and added a number of new sections.</para>
<para>Discussions on the boost.org mailing list were essential in the
development of &Boost.Thread;
. 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 &egrave;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, 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.</para>
<para>
As of February 2006 Anthony Williams and Roland Schwarz took over maintainance
and further development of the library after it has been in an orphaned state
for a rather long period of time.
</para>
<para>Apologies for anyone inadvertently missed.</para>
</section>

82
doc/barrier-ref.xml Normal file
View File

@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/barrier.hpp"
last-revision="$Date$">
<namespace name="boost">
<class name="barrier">
<inherit access="private">
<type><classname>boost::noncopyable</classname></type>
<purpose>Exposition only</purpose>
</inherit>
<purpose>
<para>An object of class <classname>barrier</classname> is a synchronization
primitive used to cause a set of threads to wait until they each perform a
certain function or each reach a particular point in their execution.</para>
</purpose>
<description>
<para>When a barrier is created, it is initialized with a thread count N.
The first N-1 calls to <code>wait()</code> will all cause their threads to be blocked.
The Nth call to <code>wait()</code> will allow all of the waiting threads, including
the Nth thread, to be placed in a ready state. The Nth call will also "reset"
the barrier such that, if an additional N+1th call is made to <code>wait()</code>,
it will be as though this were the first call to <code>wait()</code>; in other
words, the N+1th to 2N-1th calls to <code>wait()</code> will cause their
threads to be blocked, and the 2Nth call to <code>wait()</code> will allow all of
the waiting threads, including the 2Nth thread, to be placed in a ready state
and reset the barrier. This functionality allows the same set of N threads to re-use
a barrier object to synchronize their execution at multiple points during their
execution.</para>
<para>See <xref linkend="thread.glossary"/> for definitions of thread
states <link linkend="thread.glossary.thread-state">blocked</link>
and <link linkend="thread.glossary.thread-state">ready</link>.
Note that "waiting" is a synonym for blocked.</para>
</description>
<constructor>
<parameter name="count">
<paramtype>size_t</paramtype>
</parameter>
<effects><simpara>Constructs a <classname>barrier</classname> object that
will cause <code>count</code> threads to block on a call to <code>wait()</code>.
</simpara></effects>
</constructor>
<destructor>
<effects><simpara>Destroys <code>*this</code>. If threads are still executing
their <code>wait()</code> operations, the behavior for these threads is undefined.
</simpara></effects>
</destructor>
<method-group name="waiting">
<method name="wait">
<type>bool</type>
<effects><simpara>Wait until N threads call <code>wait()</code>, where
N equals the <code>count</code> provided to the constructor for the
barrier object.</simpara>
<simpara><emphasis role="bold">Note</emphasis> that if the barrier is
destroyed before <code>wait()</code> can return, the behavior is
undefined.</simpara></effects>
<returns>Exactly one of the N threads will receive a return value
of <code>true</code>, the others will receive a value of <code>false</code>.
Precisely which thread receives the return value of <code>true</code> will
be implementation-defined. Applications can use this value to designate one
thread as a leader that will take a certain action, and the other threads
emerging from the barrier can wait for that action to take place.</returns>
</method>
</method-group>
</class>
</namespace>
</header>

View File

@@ -1,222 +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 summary="header" 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 summary="Bibliography" 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. Includes descriptions
of Path Expressions, Message Passing, and Remote Procedure
Call in addition to the basics.</p>
</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. <a href=
"http://www.boost.org">http://www.boost.org</a>
<p>Boost.Threads is one of many Boost libraries. The Boost
web site includes a great deal of documentation and general
information which applies to all Boost libraries. Current
copies of the libraries including documentation and test
programs may be downloaded from the web site.</p>
</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 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.</p>
</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 <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. 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 <a href=
"http://www.acm.org/classics/feb96/">
http://www.acm.org/classics/feb96/</a></p>
<p>Hoare and Brinch Hansen&#39;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> <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.</p>
</td>
</tr>
<tr>
<td width="102" valign="top" align="left"><b>[<a name=
"Schmidt">Schmidt</a>]</b> </td>
<td width="645">
<p>Douglas C. Schmidt and Irfan Pyarali, <cite>Strategies
for Implementing POSIX Condition Variables on Win32</cite>,
Department of Computer Science, Washington University, St.
Louis, Missouri. <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>]</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>, Wiley 2000, ISBN 0-471-60695-2 <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. Note that
the 3rd edition (and subsequent editions like the Special
Edition) has been rewritten to cover the ISO standard
language and library.</p>
</td>
</tr>
</table>
<p>Note: The URL&#39;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 -->05 Nov 2001<!--webbot bot="Timestamp" endspan i-checksum="15246" --></p>
<p>&copy; Copyright Beman Dawes, 2001</p>
</body>
</html>

234
doc/bibliography.xml Normal file
View File

@@ -0,0 +1,234 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<bibliography id="thread.bibliography"
last-revision="$Date$">
<title>Bibliography</title>
<biblioentry id="thread.bib.AndrewsSchneider83">
<abbrev id="thread.bib.AndrewsSchneider83.abbrev">AndrewsSchnieder83</abbrev>
<biblioset relation="journal">
<title>ACM Computing Surveys</title>
<volumenum>Vol. 15</volumenum>
<issuenum>No. 1</issuenum>
<date>March, 1983</date>
</biblioset>
<biblioset relation="article">
<authorgroup>
<author>
<firstname>Gregory</firstname>
<othername>R.</othername>
<surname>Andrews</surname>
</author>
<author>
<firstname>Fred</firstname>
<othername>B.</othername>
<surname>Schneider</surname>
</author>
</authorgroup>
<title>
<ulink
url="http://www.acm.org/pubs/citations/journals/surveys/1983-15-1/p3-andrews/"
>Concepts and Notations for Concurrent Programming</ulink>
</title>
</biblioset>
<para>Good general background reading. Includes descriptions of Path
Expressions, Message Passing, and Remote Procedure Call in addition to the
basics</para>
</biblioentry>
<biblioentry id="thread.bib.Boost">
<abbrev id="thread.bib.Boost.abbrev">Boost</abbrev>
<bibliomisc>The <emphasis>Boost</emphasis> world wide web site.
<ulink url="http:/www.boost.org">http://www.boost.org</ulink></bibliomisc>
<para>&Boost.Thread; is one of many Boost libraries. The Boost web
site includes a great deal of documentation and general information which
applies to all Boost libraries. Current copies of the libraries including
documentation and test programs may be downloaded from the web
site.</para>
</biblioentry>
<biblioentry id="thread.bib.Hansen73">
<abbrev id="thread.bib.Hansen73.abbrev">Hansen73</abbrev>
<biblioset relation="journal">
<title>ACM Computing Surveys</title>
<volumenum>Vol. 5</volumenum>
<issuenum>No. 4</issuenum>
<date>December, 1973</date>
</biblioset>
<biblioset relation="article">
<author>0-201-63392-2
<firstname>Per Brinch</firstname>
<lastname>Hansen</lastname>
</author>
<title>
<ulink
url="http://www.acm.org/pubs/articles/journals/surveys/1973-5-4/p223-hansen/"
>Concurrent Programming Concepts</ulink>
</title>
</biblioset>
<para>"This paper describes the evolution of language features for
multiprogramming from event queues and semaphores to critical regions and
monitors." Includes analysis of why events 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.</para>
</biblioentry>
<biblioentry id="thread.bib.Butenhof97">
<abbrev id="thread.bib.Butenhof97.abbrev">Butenhof97</abbrev>
<title>
<ulink url="http://cseng.aw.com/book/0,3828,0201633922,00.html"
>Programming with POSIX Threads </ulink>
</title>
<author>
<firstname>David</firstname>
<othername>R.</othername>
<surname>Butenhof</surname>
</author>
<publisher>Addison-Wesley</publisher>
<copyright><year>1997</year></copyright>
<isbn>ISNB: 0-201-63392-2</isbn>
<para>This is a very readable explanation of threads and how to use
them. Many of the insights given apply to all multithreaded programming, not
just POSIX Threads</para>
</biblioentry>
<biblioentry id="thread.bib.Hoare74">
<abbrev id="thread.bib.Hoare74.abbrev">Hoare74</abbrev>
<biblioset relation="journal">
<title>Communications of the ACM</title>
<volumenum>Vol. 17</volumenum>
<issuenum>No. 10</issuenum>
<date>October, 1974</date>
</biblioset>
<biblioset relation="article">
<title>
<ulink url=" http://www.acm.org/classics/feb96/"
>Monitors: An Operating System Structuring Concept</ulink>
</title>
<author>
<firstname>C.A.R.</firstname>
<surname>Hoare</surname>
</author>
<pagenums>549-557</pagenums>
</biblioset>
<para>Hoare and Brinch Hansen's work on Monitors is the basis for reliable
multithreading patterns. This is one of the most often referenced papers in
all of computer science, and with good reason.</para>
</biblioentry>
<biblioentry id="thread.bib.ISO98">
<abbrev id="thread.bib.ISO98.abbrev">ISO98</abbrev>
<title>
<ulink url="http://www.ansi.org">Programming Language C++</ulink>
</title>
<orgname>ISO/IEC</orgname>
<releaseinfo>14882:1998(E)</releaseinfo>
<para>This is the official C++ Standards document. Available from the ANSI
(American National Standards Institute) Electronic Standards Store.</para>
</biblioentry>
<biblioentry id="thread.bib.McDowellHelmbold89">
<abbrev id="thread.bib.McDowellHelmbold89.abbrev">McDowellHelmbold89</abbrev>
<biblioset relation="journal">
<title>Communications of the ACM</title>
<volumenum>Vol. 21</volumenum>
<issuenum>No. 2</issuenum>
<date>December, 1989</date>
</biblioset>
<biblioset>
<author>
<firstname>Charles</firstname>
<othername>E.</othername>
<surname>McDowell</surname>
</author>
<author>
<firstname>David</firstname>
<othername>P.</othername>
<surname>Helmbold</surname>
</author>
<title>
<ulink
url="http://www.acm.org/pubs/citations/journals/surveys/1989-21-4/p593-mcdowell/"
>Debugging Concurrent Programs</ulink>
</title>
</biblioset>
<para>Identifies many of the unique failure modes and debugging difficulties
associated with concurrent programs.</para>
</biblioentry>
<biblioentry id="thread.bib.SchmidtPyarali">
<abbrev id="thread.bib.SchmidtPyarali.abbrev">SchmidtPyarali</abbrev>
<title>
<ulink url="http://www.cs.wustl.edu/~schmidt/win32-cv-1.html8"
>Strategies for Implementing POSIX Condition Variables on Win32</ulink>
</title>
<authorgroup>
<author>
<firstname>Douglas</firstname>
<othername>C.</othername>
<surname>Schmidt</surname>
</author>
<author>
<firstname>Irfan</firstname>
<surname>Pyarali</surname>
</author>
</authorgroup>
<orgname>Department of Computer Science, Washington University, St. Louis,
Missouri</orgname>
<para>Rationale for understanding &Boost.Thread; condition
variables. Note that Alexander Terekhov found some bugs in the
implementation given in this article, so pthreads-win32 and &Boost.Thread;
are even more complicated yet.</para>
</biblioentry>
<biblioentry id="thread.bib.SchmidtStalRohnertBuschmann">
<abbrev
id="thread.bib.SchmidtStalRohnertBuschmann.abbrev">SchmidtStalRohnertBuschmann</abbrev>
<title>
<ulink
url="http://www.wiley.com/Corporate/Website/Objects/Products/0,9049,104671,00.html"
>Pattern-Oriented Architecture Volume 2</ulink>
</title>
<subtitle>Patterns for Concurrent and Networked Objects</subtitle>
<titleabbrev>POSA2</titleabbrev>
<authorgroup>
<author>
<firstname>Douglas</firstname>
<othername>C.</othername>
<surname>Schmidt</surname>
</author>
<author>
<firstname>Michael</firstname>
<lastname>Stal</lastname>
</author>
<author>
<firstname>Hans</firstname>
<surname>Rohnert</surname>
</author>
<author>
<firstname>Frank</firstname>
<surname>Buschmann</surname>
</author>
</authorgroup>
<publisher>Wiley</publisher>
<copyright><year>2000</year></copyright>
<para>This is a very good explanation of how to apply several patterns
useful for concurrent programming. Among the patterns documented is the
Monitor Pattern mentioned frequently in the &Boost.Thread;
documentation.</para>
</biblioentry>
<biblioentry id="thread.bib.Stroustrup">
<abbrev id="thread.bib.Stroustrup.abbrev">Stroustrup</abbrev>
<title>
<ulink url="http://cseng.aw.com/book/0,3828,0201700735,00.html"
>The C++ Programming Language</ulink>
</title>
<edition>Special Edition</edition>
<publisher>Addison-Wesley</publisher>
<copyright><year>2000</year></copyright>
<isbn>ISBN: 0-201-70073-5</isbn>
<para>The first book a C++ programmer should own. Note that the 3rd edition
(and subsequent editions like the Special Edition) has been rewritten to
cover the ISO standard language and library.</para>
</biblioentry>
</bibliography>

137
doc/build.xml Normal file
View File

@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Copyright (c) 2007 Roland Schwarz
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<section id="thread.build" last-revision="$Date$">
<title>Build</title>
<para>
How you build the &Boost.Thread; libraries, and how you build your own applications
that use those libraries, are some of the most frequently asked questions. Build
processes are difficult to deal with in a portable manner. That's one reason
why &Boost.Thread; makes use of &Boost.Build;.
In general you should refer to the documentation for &Boost.Build;.
This document will only supply you with some simple usage examples for how to
use <emphasis>bjam</emphasis> to build and test &Boost.Thread;. In addition, this document
will try to explain the build requirements so that users may create their own
build processes (for instance, create an IDE specific project), both for building
and testing &Boost.Thread;, as well as for building their own projects using
&Boost.Thread;.
</para>
<section id="thread.build.building">
<title>Building the &Boost.Thread; Libraries</title>
<para>
Building the &Boost.Thread; Library depends on how you intend to use it. You have several options:
<itemizedlist>
<listitem>
Using as a <link linkend="thread.build.precompiled">precompiled</link> library, possibly
with auto-linking, or for use from within an IDE.
</listitem>
<listitem>
Use from a <link linkend="thread.build.bjam">&Boost.Build;</link> project.
</listitem>
<listitem>
Using in <link linkend="thread.build.source">source</link> form.
</listitem>
</itemizedlist>
</para>
<section id="thread.build.precompiled">
<title>Precompiled</title>
<para>
Using the &Boost.Thread; library in precompiled form is the way to go if you want to
install the library to a standard place, from where your linker is able to resolve code
in binary form. You also will want this option if compile time is a concern. Multiple
variants are available, for different toolsets and build variants (debug/release).
The library files are named <emphasis>{lead}boost_thread{build-specific-tags}.{extension}</emphasis>,
where the build-specific-tags indicate the toolset used to build the library, whether it's
a debug or release build, what version of &Boost; was used, etc.; and the lead and extension
are the appropriate extensions for a dynamic link library or static library for the platform
for which &Boost.Thread; is being built.
For instance, a debug build of the dynamic library built for Win32 with VC++ 7.1 using Boost 1.34 would
be named <emphasis>boost_thread-vc71-mt-gd-1_34.dll</emphasis>.
More information on this should be available from the &Boost.Build; documentation.
</para>
<para>
Building should be possible with the default configuration. If you are running into problems,
it might be wise to adjust your local settings of &Boost.Build; though. Typically you will
need to get your user-config.jam file to reflect your environment, i.e. used toolsets. Please
refer to the &Boost.Build; documentation to learn how to do this.
</para>
<para>
To create the libraries you need to open a command shell and change to the
<emphasis>boost_root</emphasis> directory. From there you give the command
<programlisting>bjam --toolset=<emphasis>mytoolset</emphasis> stage --with-thread</programlisting>
Replace <emphasis>mytoolset</emphasis> with the name of your toolset, e.g. msvc-7.1 .
This will compile and put the libraries into the <emphasis>stage</emphasis> directory which is just below the
<emphasis>boost_root</emphasis> directory. &Boost.Build; by default will generate static and
dynamic variants for debug and release.
</para>
<note>
Invoking the above command without the --with-thread switch &Boost.Build; will build all of
the Boost distribution, including &Boost.Thread;.
</note>
<para>
The next step is to copy your libraries to a place where your linker is able to pick them up.
It is also quite possible to leave them in the stage directory and instruct your IDE to take them
from there.
</para>
<para>
In your IDE you then need to add <emphasis>boost_root</emphasis>/boost to the paths where the compiler
expects to find files to be included. For toolsets that support <emphasis>auto-linking</emphasis>
it is not necessary to explicitly specify the name of the library to link against, it is sufficient
to specify the path of the stage directory. Typically this is true on Windows. For gcc you need
to specify the exact library name (including all the tags). Please don't forget that threading
support must be turned on to be able to use the library. You should be able now to build your
project from the IDE.
</para>
</section>
<section id="thread.build.bjam">
<title>&Boost.Build; Project</title>
<para>
If you have decided to use &Boost.Build; as a build environment for your application, you simply
need to add a single line to your <emphasis>Jamroot</emphasis> file:
<programlisting>use-project /boost : {path-to-boost-root} ;</programlisting>
where <emphasis>{path-to-boost-root}</emphasis> needs to be replaced with the location of
your copy of the boost tree.
Later when you specify a component that needs to link against &Boost.Thread; you specify this
as e.g.:
<programlisting>exe myapp : {myappsources} /boost//thread ;</programlisting>
and you are done.
</para>
</section>
<section id="thread.build.source">
<title>Source Form</title>
<para>
Of course it is also possible to use the &Boost.Thread; library in source form.
First you need to specify the <emphasis>boost_root</emphasis>/boost directory as
a path where your compiler expects to find files to include. It is not easy
to isolate the &Boost.Thread; include files from the rest of the boost
library though. You would also need to isolate every include file that the thread
library depends on. Next you need to copy the files from
<emphasis>boost_root</emphasis>/libs/thread/src to your project and instruct your
build system to compile them together with your project. Please look into the
<emphasis>Jamfile</emphasis> in <emphasis>boost_root</emphasis>/libs/thread/build
to find out which compiler options and defines you will need to get a clean compile.
Using the boost library in this way is the least recommended, and should only be
considered if avoiding dependency on &Boost.Build; is a requirement. Even if so
it might be a better option to use the library in it's precompiled form.
Precompiled downloads are available from the boost consulting web site, or as
part of most linux distributions.
</para>
</section>
</section>
<section id="thread.build.testing">
<title>Testing the &Boost.Thread; Libraries</title>
<para>
To test the &Boost.Thread; libraries using &Boost.Build;, simply change to the
directory <emphasis>boost_root</emphasis>/libs/thread/test and execute the command:
<programlisting>bjam --toolset=<emphasis>mytoolset</emphasis> test</programlisting>
</para>
</section>
</section>

View File

@@ -1,132 +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 summary="header" 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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>

2305
doc/concepts.xml Normal file

File diff suppressed because it is too large Load Diff

196
doc/condition-ref.xml Normal file
View File

@@ -0,0 +1,196 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/condition.hpp"
last-revision="$Date$">
<namespace name="boost">
<class name="condition">
<inherit access="private">
<type><classname>boost::noncopyable</classname></type>
<purpose>Exposition only</purpose>
</inherit>
<purpose>
<para>An object of class <classname>condition</classname> is a
synchronization primitive used to cause a thread to wait until a
particular shared-data condition (or time) is met.</para>
</purpose>
<description>
<para>A <classname>condition</classname> object is always used in
conjunction with a <link linkend="thread.concepts.mutexes">mutex</link>
object (an object whose type is a model of a <link
linkend="thread.concepts.Mutex">Mutex</link> or one of its
refinements). The mutex object must be locked prior to waiting on the
condition, which is verified by passing a lock object (an object whose
type is a model of <link linkend="thread.concepts.Lock">Lock</link> or
one of its refinements) to the <classname>condition</classname> object's
wait functions. Upon blocking on the <classname>condition</classname>
object, the thread unlocks the mutex object. When the thread returns
from a call to one of the <classname>condition</classname> object's wait
functions the mutex object is again locked. The tricky unlock/lock
sequence is performed automatically by the
<classname>condition</classname> object's wait functions.</para>
<para>The <classname>condition</classname> type is often used to
implement the Monitor Object and other important patterns (see
&cite.SchmidtStalRohnertBuschmann; and &cite.Hoare74;). Monitors are one
of the most important patterns for creating reliable multithreaded
programs.</para>
<para>See <xref linkend="thread.glossary"/> for definitions of <link
linkend="thread.glossary.thread-state">thread states</link>
blocked and ready. Note that "waiting" is a synonym for blocked.</para>
</description>
<constructor>
<effects><simpara>Constructs a <classname>condition</classname>
object.</simpara></effects>
</constructor>
<destructor>
<effects><simpara>Destroys <code>*this</code>.</simpara></effects>
</destructor>
<method-group name="notification">
<method name="notify_one">
<type>void</type>
<effects><simpara>If there is a thread waiting on <code>*this</code>,
change that thread's state to ready. Otherwise there is no
effect.</simpara></effects>
<notes><simpara>If more than one thread is waiting on <code>*this</code>,
it is unspecified which is made ready. After returning to a ready
state the notified thread must still acquire the mutex again (which
occurs within the call to one of the <classname>condition</classname>
object's wait functions.)</simpara></notes>
</method>
<method name="notify_all">
<type>void</type>
<effects><simpara>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.</simpara></effects>
</method>
</method-group>
<method-group name="waiting">
<method name="wait">
<template>
<template-type-parameter name="ScopedLock"/>
</template>
<type>void</type>
<parameter name="lock">
<paramtype>ScopedLock&amp;</paramtype>
</parameter>
<requires><simpara><code>ScopedLock</code> meets the <link
linkend="thread.concepts.ScopedLock">ScopedLock</link>
requirements.</simpara></requires>
<effects><simpara>Releases the lock on the <link
linkend="thread.concepts.mutexes">mutex object</link>
associated with <code>lock</code>, blocks the current thread of execution
until readied by a call to <code>this->notify_one()</code>
or<code> this->notify_all()</code>, and then reacquires the
lock.</simpara></effects>
<throws><simpara><classname>lock_error</classname> if
<code>!lock.locked()</code></simpara></throws>
</method>
<method name="wait">
<template>
<template-type-parameter name="ScopedLock"/>
<template-type-parameter name="Pred"/>
</template>
<type>void</type>
<parameter name="lock">
<paramtype>ScopedLock&amp;</paramtype>
</parameter>
<parameter name="pred">
<paramtype>Pred</paramtype>
</parameter>
<requires><simpara><code>ScopedLock</code> meets the <link
linkend="thread.concepts.ScopedLock">ScopedLock</link>
requirements and the return from <code>pred()</code> is
convertible to <code>bool</code>.</simpara></requires>
<effects><simpara>As if: <code>while (!pred())
wait(lock)</code></simpara></effects>
<throws><simpara><classname>lock_error</classname> if
<code>!lock.locked()</code></simpara></throws>
</method>
<method name="timed_wait">
<template>
<template-type-parameter name="ScopedLock"/>
</template>
<type>bool</type>
<parameter name="lock">
<paramtype>ScopedLock&amp;</paramtype>
</parameter>
<parameter name="xt">
<paramtype>const <classname>boost::xtime</classname>&amp;</paramtype>
</parameter>
<requires><simpara><code>ScopedLock</code> meets the <link
linkend="thread.concepts.ScopedLock">ScopedLock</link>
requirements.</simpara></requires>
<effects><simpara>Releases the lock on the <link
linkend="thread.concepts.mutexes">mutex object</link>
associated with <code>lock</code>, blocks the current thread of execution
until readied by a call to <code>this->notify_one()</code>
or<code> this->notify_all()</code>, or until time <code>xt</code>
is reached, and then reacquires the lock.</simpara></effects>
<returns><simpara><code>false</code> if time <code>xt</code> is reached,
otherwise <code>true</code>.</simpara></returns>
<throws><simpara><classname>lock_error</classname> if
<code>!lock.locked()</code></simpara></throws>
</method>
<method name="timed_wait">
<template>
<template-type-parameter name="ScopedLock"/>
<template-type-parameter name="Pred"/>
</template>
<type>bool</type>
<parameter name="lock">
<paramtype>ScopedLock&amp;</paramtype>
</parameter>
<parameter name="xt">
<paramtype>const <classname>boost::xtime</classname>&amp;</paramtype>
</parameter>
<parameter name="pred">
<paramtype>Pred</paramtype>
</parameter>
<requires><simpara><code>ScopedLock</code> meets the <link
linkend="thread.concepts.ScopedLock">ScopedLock</link>
requirements and the return from <code>pred()</code> is
convertible to <code>bool</code>.</simpara></requires>
<effects><simpara>As if: <code>while (!pred()) { if (!timed_wait(lock,
xt)) return false; } return true;</code></simpara></effects>
<returns><simpara><code>false</code> if <code>xt</code> is reached,
otherwise <code>true</code>.</simpara></returns>
<throws><simpara><classname>lock_error</classname> if
<code>!lock.locked()</code></simpara></throws>
</method>
</method-group>
</class>
</namespace>
</header>

View File

@@ -1,338 +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 summary="header" 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&#39;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&#39;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&#39;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
&quot;waiting&quot; 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&#39;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 &quot;spurious wake ups&quot;. 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 ScopedLock&gt;
bool timed_wait(ScopedLock&amp; lock, const <a href=
"xtime.html">xtime</a>&amp; xt);
</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 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 &quot;spurious wake ups&quot;. 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 ScopedLock, typename Pr&gt;
bool timed_wait(ScopedLock&amp; lock, const <a href=
"xtime.html">xtime</a>&amp; xt, 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())<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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,97 +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 summary="header" 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 summary="macros" 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&#39;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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>

96
doc/configuration.xml Normal file
View File

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

View File

@@ -1,348 +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 summary="header" 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>. 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. The
intent isn&#39;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]. 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. For example,
files.</li>
</ul>
<ul>
<li>The program itself. 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 summary="thread states" 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.</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 summary="state transitions" 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]</p>
</td>
<td>Ready</td>
<td>Thread is created by a call to a library function. 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. The result of a race condition
may be a bit pattern which isn&#39;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.</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. 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 summary="memory visibility" 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.</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. The preferred
behavior is the same as when there is no matching exception handler in
a program [15.3/9]. 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>.</p>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %b %Y" startspan -->05 Nov 2001<!--webbot bot="Timestamp" endspan i-checksum="15246" --></p>
<p>&copy; Copyright Beman Dawes, 2001</p>
</body>
</html>

159
doc/design.xml Normal file
View File

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

31
doc/entities.xml Normal file
View File

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

62
doc/exceptions-ref.xml Normal file
View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/exceptions.hpp"
last-revision="$Date$">
<namespace name="boost">
<class name="lock_error">
<purpose>
<simpara>The lock_error class defines an exception type thrown
to indicate a locking related error has been detected.</simpara>
</purpose>
<description>
<simpara>Examples of errors indicated by a lock_error exception
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.</simpara>
</description>
<inherit access="public">
<type><classname>std::logical_error</classname></type>
</inherit>
<constructor>
<effects><simpara>Constructs a <code>lock_error</code> object.
</simpara></effects>
</constructor>
</class>
<class name="thread_resource_error">
<purpose>
<simpara>The <classname>thread_resource_error</classname> class
defines an exception type that is thrown by constructors in the
&Boost.Thread; library when thread-related resources can not be
acquired.</simpara>
</purpose>
<description>
<simpara><classname>thread_resource_error</classname> is used
only when thread-related resources cannot be acquired; memory
allocation failures are indicated by
<classname>std::bad_alloc</classname>.</simpara>
</description>
<inherit access="public">
<type><classname>std::runtime_error</classname></type>
</inherit>
<constructor>
<effects><simpara>Constructs a <code>thread_resource_error</code>
object.</simpara></effects>
</constructor>
</class>
</namespace>
</header>

View File

@@ -1,193 +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 summary="header" 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&#39;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&#39;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&#39;t model such C based APIs.</p>
<h2>2b. Why wasn&#39;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&#39;t meet our C++ requirements, and were also missing
certain features. For instance, 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&#39;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&#39;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&#39;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&#39;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&#39;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&#39;t thread cancellation or termination provided?</h2>
<p>There&#39;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>
<h2>10. Why has class semaphore disappeared?</h2>
<p>Semaphore was removed as too error prone. The same effect can be
achieved with greater safety by the combination of a mutex and a
condition variable.</p>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>

235
doc/faq.xml Normal file
View File

@@ -0,0 +1,235 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<section id="thread.faq" last-revision="$Date$">
<title>Frequently Asked Questions</title>
<qandaset>
<qandaentry>
<question>
<para>Are lock objects <link
linkend="thread.glossary.thread-safe">thread safe</link>?</para>
</question>
<answer>
<para><emphasis role="bold">No!</emphasis> Lock objects are not meant to
be shared between threads. They are meant to be short-lived objects
created on automatic storage within a code block. Any other usage is
just likely to lead to errors and won't really be of actual benefit anyway.
Share <link linkend="thread.concepts.mutexes">Mutexes</link>, not
Locks. For more information see the <link
linkend="thread.rationale.locks">rationale</link> behind the
design for lock objects.</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Why was &Boost.Thread; modeled after (specific library
name)?</para>
</question>
<answer>
<para>It wasn't. &Boost.Thread; was designed from scratch. Extensive
design discussions involved numerous people representing a wide range of
experience across many platforms. To ensure portability, the initial
implements were done in parallel using POSIX Threads and the Win32
threading API. But the &Boost.Thread; design is very much in the spirit
of C++, and thus doesn't model such C based APIs.</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Why wasn't &Boost.Thread; modeled after (specific library
name)?</para>
</question>
<answer>
<para>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, the WIN32 thread API lacks condition
variables, even though these are critical for the important Monitor
pattern &cite.SchmidtStalRohnertBuschmann;.</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Why do <link linkend="thread.concepts.mutexes">Mutexes</link>
have noncopyable semantics?</para>
</question>
<answer>
<para>To ensure that <link
linkend="thread.glossary.deadlock">deadlocks</link> don't occur. The
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).</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>How can you prevent <link
linkend="thread.glossary.deadlock">deadlock</link> from occurring when
a thread must lock multiple mutexes?</para>
</question>
<answer>
<para>Always lock them in the same order. One easy way of doing this is
to use each mutex's address to determine the order in which they are
locked. A future &Boost.Thread; concept may wrap this pattern up in a
reusable class.</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Don't noncopyable <link
linkend="thread.concepts.mutexes">Mutex</link> semantics mean that a
class with a mutex member will be noncopyable as well?</para>
</question>
<answer>
<para>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 <emphasis role="bold">good thing</emphasis>,
however, since the compiler generated operations would not be <link
linkend="thread.glossary.thread-safe">thread-safe</link>. The following
is a simple example of a class with copyable semantics and internal
synchronization through a mutex member.</para>
<programlisting>
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 synchronize 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;
};
</programlisting>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>How can you lock a <link
linkend="thread.concepts.mutexes">Mutex</link> member in a const member
function, in order to implement the Monitor Pattern?</para>
</question>
<answer>
<para>The Monitor Pattern &cite.SchmidtStalRohnertBuschmann; mutex
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 (and in fact would be incorrect since
the logical state of a locked mutex clearly differs from the logical
state of an unlocked mutex). Declaring a mutex member as mutable clearly
documents the intended semantics.</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Why supply <classname>boost::condition</classname> variables rather than
event variables?</para>
</question>
<answer>
<para>Condition variables result in user code much less prone to <link
linkend="thread.glossary.race-condition">race conditions</link> than
event variables. See <xref linkend="thread.rationale.events" />
for analysis. Also see &cite.Hoare74; and &cite.SchmidtStalRohnertBuschmann;.
</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Why isn't thread cancellation or termination provided?</para>
</question>
<answer>
<para>There's a valid need for thread termination, so at some point
&Boost.Thread; probably will include it, but only after we can find a
truly safe (and portable) mechanism for this concept.</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Is it safe for threads to share automatic storage duration (stack)
objects via pointers or references?</para>
</question>
<answer>
<para>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).</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Why has class semaphore disappeared?</para>
</question>
<answer>
<para>Semaphore was removed as too error prone. The same effect can be
achieved with greater safety by the combination of a mutex and a
condition variable.</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Why doesn't the thread's ctor take at least a void* to pass any
information along with the function? All other threading libs support
that and it makes Boost.Threads inferiour. </para>
</question>
<answer>
<para>There is no need, because Boost.Threads are superiour! First
thing is that its ctor doesn't take a function but a functor. That
means that you can pass an object with an overloaded operator() and
include additional data as members in that object. Beware though that
this object is copied, use boost::ref to prevent that. Secondly, even
a boost::function&lt;void (void)&gt; can carry parameters, you only have to
use boost::bind() to create it from any function and bind its
parameters.</para>
<para>That is also why Boost.Threads are superiour, because they
don't require you to pass a type-unsafe void pointer. Rather, you can
use the flexible Boost.Functions to create a thread entry out of
anything that can be called.</para>
</answer>
</qandaentry>
</qandaset>
</section>

304
doc/glossary.xml Normal file
View File

@@ -0,0 +1,304 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<glossary id="thread.glossary" last-revision="$Date$">
<title>Glossary</title>
<para>Definitions are given in terms of the C++ Standard
&cite.ISO98;. References to the standard are in the form [1.2.3/4], which
represents the section number, with the paragraph number following the
"/".</para>
<para>Because the definitions are written in something akin to "standardese",
they can be difficult to understand. The intent isn't to confuse, but rather
to clarify the additional requirements &Boost.Thread; places on a C++
implementation as defined by the C++ Standard.</para>
<glossentry id="thread.glossary.thread">
<glossterm>Thread</glossterm>
<glossdef>
<para>Thread is short for "thread of execution". 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 multithreading environment
always has an initial thread even if the program explicitly creates no
additional threads.</para>
<para>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:</para>
<itemizedlist>
<listitem><para>Static storage duration (static, extern) objects
[3.7.1].</para></listitem>
<listitem><para>Dynamic storage duration (heap) objects [3.7.3]. Thus
each memory allocation will return a unique addresses, regardless of the
thread making the allocation request.</para></listitem>
<listitem><para>Automatic storage duration (stack) objects [3.7.2]
accessed via pointer or reference from another thread.</para></listitem>
<listitem><para>Resources provided by the operating system. For example,
files.</para></listitem>
<listitem><para>The program itself. In other words, each thread is
executing some function of the same program, not a totally different
program.</para></listitem>
</itemizedlist>
<para>Each thread has its own:</para>
<itemizedlist>
<listitem><para>Registers and current execution sequence (program
counter) [1.9/5].</para></listitem>
<listitem><para>Automatic storage duration (stack) objects
[3.7.2].</para></listitem>
</itemizedlist>
</glossdef>
</glossentry>
<glossentry id="thread.glossary.thread-safe">
<glossterm>Thread-safe</glossterm>
<glossdef>
<para>A program is thread-safe if it has no <link
linkend="thread.glossary.race-condition">race conditions</link>, does
not <link linkend="thread.glossary.deadlock">deadlock</link>, and has
no <link linkend="thread.glossary.priority-failure">priority
failures</link>.</para>
<para>Note that thread-safety does not necessarily imply efficiency, and
than while some thread-safety violations can be determined statically at
compile time, many thread-safety errors can only only be detected at
runtime.</para>
</glossdef>
</glossentry>
<glossentry id="thread.glossary.thread-state">
<glossterm>Thread State</glossterm>
<glossdef>
<para>During the lifetime of a thread, it shall be in one of the following
states:</para>
<table>
<title>Thread States</title>
<tgroup cols="2" align="left">
<thead>
<row>
<entry>State</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>Ready</entry>
<entry>Ready to run, but waiting for a processor.</entry>
</row>
<row>
<entry>Running</entry>
<entry>Currently executing on a processor. Zero or more threads
may be running at any time, with a maximum equal to the number of
processors.</entry>
</row>
<row>
<entry>Blocked</entry>
<entry>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 "waiting" is synonymous with
"blocked"</entry>
</row>
<row>
<entry>Terminated</entry>
<entry>Finished execution but not yet detached or joined.</entry>
</row>
</tbody>
</tgroup>
</table>
<para>Thread state transitions shall occur only as specified:</para>
<table>
<title>Thread States Transitions</title>
<tgroup cols="3" align="left">
<thead>
<row>
<entry>From</entry>
<entry>To</entry>
<entry>Cause</entry>
</row>
</thead>
<tbody>
<row>
<entry>[none]</entry>
<entry>Ready</entry>
<entry><para>Thread is created by a call to a library function.
In the case of the initial thread, creation is implicit and
occurs during the startup of the main() function [3.6.1].</para></entry>
</row>
<row>
<entry>Ready</entry>
<entry>Running</entry>
<entry><para>Processor becomes available.</para></entry>
</row>
<row>
<entry>Running</entry>
<entry>Ready</entry>
<entry>Thread preempted.</entry>
</row>
<row>
<entry>Running</entry>
<entry>Blocked</entry>
<entry>Thread calls a library function which waits for a resource or
for the completion of I/O.</entry>
</row>
<row>
<entry>Running</entry>
<entry>Terminated</entry>
<entry>Thread returns from its initial function, calls a thread
termination library function, or is canceled by some other thread
calling a thread termination library function.</entry>
</row>
<row>
<entry>Blocked</entry>
<entry>Ready</entry>
<entry>The resource being waited for becomes available, or the
blocking library function completes.</entry>
</row>
<row>
<entry>Terminated</entry>
<entry>[none]</entry>
<entry>Thread is detached or joined by some other thread calling the
appropriate library function, or by program termination
[3.6.3].</entry>
</row>
</tbody>
</tgroup>
</table>
<para>[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.]</para>
</glossdef>
</glossentry>
<glossentry id="thread.glossary.race-condition">
<glossterm>Race Condition</glossterm>
<glossdef>
<para>A race condition is what occurs when multiple threads read from and write
to the same memory without proper synchronization, resulting in an incorrect
value being read or written. 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].</para>
<para>Race conditions can be prevented by serializing memory access using
the tools provided by &Boost.Thread;.</para>
</glossdef>
</glossentry>
<glossentry id="thread.glossary.deadlock">
<glossterm>Deadlock</glossterm>
<glossdef>
<para>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.</para>
</glossdef>
</glossentry>
<glossentry id="thread.glossary.starvation">
<glossterm>Starvation</glossterm>
<glossdef>
<para>The condition in which a thread is not making sufficient progress in
its work during a given time interval.</para>
</glossdef>
</glossentry>
<glossentry id="thread.glossary.priority-failure">
<glossterm>Priority Failure</glossterm>
<glossdef>
<para>A priority failure (such as priority inversion or infinite overtaking)
occurs when threads are executed in such a sequence that required work is not
performed in time to be useful.</para>
</glossdef>
</glossentry>
<glossentry id="thread.glossary.undefined-behavior">
<glossterm>Undefined Behavior</glossterm>
<glossdef>
<para>The result of certain operations in &Boost.Thread; is undefined;
this means that those operations can invoke almost any behavior when
they are executed.</para>
<para>An operation whose behavior is undefined can work "correctly"
in some implementations (i.e., do what the programmer thought it
would do), while in other implementations it may exhibit almost
any "incorrect" behavior--such as returning an invalid value,
throwing an exception, generating an access violation, or terminating
the process.</para>
<para>Executing a statement whose behavior is undefined is a
programming error.</para>
</glossdef>
</glossentry>
<glossentry id="thread.glossary.memory-visibility">
<glossterm>Memory Visibility</glossterm>
<glossdef>
<para>An address [1.7] shall always point to the same memory byte,
regardless of the thread or processor dereferencing the address.</para>
<para>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.</para>
<para>For an object accessible from multiple threads, the value of the
object accessed from one thread may be indeterminate or different from the
value accessed from another thread, except under the conditions specified in
the following table. 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
"sequence point at a call" is the sequence point after the evaluation of all
function arguments [1.9/17], while the "sequence point after a call" is the
sequence point after the copying of the returned value... [1.9/17].</para>
<table>
<title>Memory Visibility</title>
<tgroup cols="2">
<thead>
<row>
<entry>Thread A</entry>
<entry>Thread B</entry>
</row>
</thead>
<tbody>
<row>
<entry>The sequence point at a call to a library thread-creation
function.</entry>
<entry>The first sequence point of the initial function in the new
thread created by the Thread A call.</entry>
</row>
<row>
<entry>The sequence point at a call to a library function which
locks a mutex, directly or by waiting for a condition
variable.</entry>
<entry>The sequence point after a call to a library function which
unlocks the same mutex.</entry>
</row>
<row>
<entry>The last sequence point before thread termination.</entry>
<entry>The sequence point after a call to a library function which
joins the terminated thread.</entry>
</row>
<row>
<entry>The sequence point at a call to a library function which
signals or broadcasts a condition variable.</entry>
<entry>The sequence point after the call to the library function
which was waiting on that same condition variable or signal.</entry>
</row>
</tbody>
</tgroup>
</table>
<para>The architecture of the execution environment and the observable
behavior of the abstract machine [1.9] shall be the same on all
processors.</para>
<para>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.</para>
<para>When an exception is thrown and there is no matching exception handler
in the same thread, behavior is undefined. The preferred behavior is the
same as when there is no matching exception handler in a program
[15.3/9]. That is, terminate() is called, and it is implementation-defined
whether or not the stack is unwound.</para>
</glossdef>
</glossentry>
<section>
<title>Acknowledgements</title>
<para>This document was originally written by Beman Dawes, and then much
improved by the incorporation of comments from William Kempf, who now
maintains the contents.</para>
<para>The visibility rules are based on &cite.Butenhof97;.</para>
</section>
</glossary>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<section id="thread.implementation_notes" last-revision="$Date$">
<title>Implementation Notes</title>
<section id="thread.implementation_notes.win32">
<title>Win32</title>
<para>
In the current Win32 implementation, creating a boost::thread object
during dll initialization will result in deadlock because the thread
class constructor causes the current thread to wait on the thread that
is being created until it signals that it has finished its initialization,
and, as stated in the
<ulink url="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/dllmain.asp">MSDN Library, "DllMain" article, "Remarks" section</ulink>,
"Because DLL notifications are serialized, entry-point functions should not
attempt to communicate with other threads or processes. Deadlocks may occur as a result."
(Also see <ulink url="http://www.microsoft.com/msj/archive/S220.aspx">"Under the Hood", January 1996</ulink>
for a more detailed discussion of this issue).
</para>
<para>
The following non-exhaustive list details some of the situations that
should be avoided until this issue can be addressed:
<itemizedlist>
<listitem>Creating a boost::thread object in DllMain() or in any function called by it.</listitem>
<listitem>Creating a boost::thread object in the constructor of a global static object or in any function called by one.</listitem>
<listitem>Creating a boost::thread object in MFC's CWinApp::InitInstance() function or in any function called by it.</listitem>
<listitem>Creating a boost::thread object in the function pointed to by MFC's _pRawDllMain function pointer or in any function called by it.</listitem>
</itemizedlist>
</para>
</section>
</section>

View File

@@ -1,138 +1,12 @@
<!-- Copyright (c) 2002-2003 Beman Dawes, William E. Kempf.
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<html>
<head>
<meta http-equiv="Content-Type" content=
"text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<title>Boost.Threads, Index</title>
</head>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
<table summary="header" 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>
<a href="mutex_concept.html">Mutex Concepts</a>
<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>
<li>
Mutex Classes
<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>
<li>
<a href="lock_concept.html">Lock Concepts</a>
<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>
<li>
Lock Classes
<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>
<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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p>&copy; <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>
<head>
<meta http-equiv="refresh" content="0; URL=../../../doc/html/thread.html">
</head>
<body>
Automatic redirection failed, please go to <a href="../../../doc/html/thread.html">../../../doc/html/thread.html</a>
</body>
</html>

View File

@@ -1,194 +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 summary="header" 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&#39;s world, it&#39;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++&#39;s
strengths, or to address C++&#39;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>
<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.</p>
</li>
</ul>
</li>
<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&#39;s use prohibitive for general
use.</p>
</li>
<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 &quot;native&quot; 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 &quot;state of the art&quot; and the
only concepts available to programmers. Recently there has been a lot
of research in other concepts, such as in &quot;Communicating
Sequential Processes.&quot; <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&#39;s a big
problem faced by developers wishing to supply such high quality
libraries, namely thread-safety. The C++ standard doesn&#39;t address
threads at all, but real world programs often make use of native
threading support. A portable library that doesn&#39;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&#39;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="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 &quot;core&quot; 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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,300 +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 summary="header" 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&#39;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 summary="Lock expressions" 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 summary="ScopedLock expressions" 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 summary="ScopedTryLock expressions" 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 summary="ScopedTimedLock expressions" 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 summary="Lock concept classes" 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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,110 +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 summary="header" 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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>

309
doc/mutex-ref.xml Normal file
View File

@@ -0,0 +1,309 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/mutex.hpp"
last-revision="$Date$">
<namespace name="boost">
<class name="mutex">
<purpose>
<para>The <classname>mutex</classname> class is a model of the
<link linkend="thread.concepts.Mutex">Mutex</link> concept.</para>
</purpose>
<description>
<para>The <classname>mutex</classname> class is a model of the
<link linkend="thread.concepts.Mutex">Mutex</link> concept.
It should be used to synchronize access to shared resources using
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
locking mechanics.</para>
<para>For classes that model related mutex concepts, see
<classname>try_mutex</classname> and <classname>timed_mutex</classname>.</para>
<para>For <link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
locking mechanics, see <classname>recursive_mutex</classname>,
<classname>recursive_try_mutex</classname>, and <classname>recursive_timed_mutex</classname>.
</para>
<para>The <classname>mutex</classname> class supplies the following typedef,
which <link linkend="thread.concepts.lock-models">models</link>
the specified locking strategy:
<informaltable>
<tgroup cols="2" align="left">
<thead>
<row>
<entry>Lock Name</entry>
<entry>Lock Concept</entry>
</row>
</thead>
<tbody>
<row>
<entry>scoped_lock</entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>The <classname>mutex</classname> class uses an
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
locking strategy, so attempts to recursively lock a <classname>mutex</classname>
object or attempts to unlock one by threads that don't own a lock on it result in
<emphasis role="bold">undefined behavior</emphasis>.
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
<code>NDEBUG</code> is not defined.</para>
<para>Like all
<link linkend="thread.concepts.mutex-models">mutex models</link>
in &Boost.Thread;, <classname>mutex</classname> leaves the
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
Programmers should make no assumptions about the order in which
waiting threads acquire a lock.</para>
</description>
<inherit access="private">
<type><classname>boost::noncopyable</classname></type>
<purpose>Exposition only</purpose>
</inherit>
<typedef name="scoped_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<constructor>
<effects>Constructs a <classname>mutex</classname> object.
</effects>
<postconditions><code>*this</code> is in an unlocked state.
</postconditions>
</constructor>
<destructor>
<effects>Destroys a <classname>mutex</classname> object.</effects>
<requires><code>*this</code> is in an unlocked state.</requires>
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
locked mutex is a serious programming error resulting in undefined
behavior such as a program crash.</notes>
</destructor>
</class>
<class name="try_mutex">
<purpose>
<para>The <classname>try_mutex</classname> class is a model of the
<link linkend="thread.concepts.TryMutex">TryMutex</link> concept.</para>
</purpose>
<description>
<para>The <classname>try_mutex</classname> class is a model of the
<link linkend="thread.concepts.TryMutex">TryMutex</link> concept.
It should be used to synchronize access to shared resources using
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
locking mechanics.</para>
<para>For classes that model related mutex concepts, see
<classname>mutex</classname> and <classname>timed_mutex</classname>.</para>
<para>For <link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
locking mechanics, see <classname>recursive_mutex</classname>,
<classname>recursive_try_mutex</classname>, and <classname>recursive_timed_mutex</classname>.
</para>
<para>The <classname>try_mutex</classname> class supplies the following typedefs,
which <link linkend="thread.concepts.lock-models">model</link>
the specified locking strategies:
<informaltable>
<tgroup cols="2" align="left">
<thead>
<row>
<entry>Lock Name</entry>
<entry>Lock Concept</entry>
</row>
</thead>
<tbody>
<row>
<entry>scoped_lock</entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
<row>
<entry>scoped_try_lock</entry>
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>The <classname>try_mutex</classname> class uses an
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
locking strategy, so attempts to recursively lock a <classname>try_mutex</classname>
object or attempts to unlock one by threads that don't own a lock on it result in
<emphasis role="bold">undefined behavior</emphasis>.
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
<code>NDEBUG</code> is not defined.</para>
<para>Like all
<link linkend="thread.concepts.mutex-models">mutex models</link>
in &Boost.Thread;, <classname>try_mutex</classname> leaves the
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
Programmers should make no assumptions about the order in which
waiting threads acquire a lock.</para>
</description>
<inherit access="private">
<type><classname>boost::noncopyable</classname></type>
<purpose>Exposition only</purpose>
</inherit>
<typedef name="scoped_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_try_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<constructor>
<effects>Constructs a <classname>try_mutex</classname> object.
</effects>
<postconditions><code>*this</code> is in an unlocked state.
</postconditions>
</constructor>
<destructor>
<effects>Destroys a <classname>try_mutex</classname> object.
</effects>
<requires><code>*this</code> is in an unlocked state.</requires>
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
locked mutex is a serious programming error resulting in undefined
behavior such as a program crash.</notes>
</destructor>
</class>
<class name="timed_mutex">
<purpose>
<para>The <classname>timed_mutex</classname> class is a model of the
<link linkend="thread.concepts.TimedMutex">TimedMutex</link> concept.</para>
</purpose>
<description>
<para>The <classname>timed_mutex</classname> class is a model of the
<link linkend="thread.concepts.TimedMutex">TimedMutex</link> concept.
It should be used to synchronize access to shared resources using
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
locking mechanics.</para>
<para>For classes that model related mutex concepts, see
<classname>mutex</classname> and <classname>try_mutex</classname>.</para>
<para>For <link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
locking mechanics, see <classname>recursive_mutex</classname>,
<classname>recursive_try_mutex</classname>, and <classname>recursive_timed_mutex</classname>.
</para>
<para>The <classname>timed_mutex</classname> class supplies the following typedefs,
which <link linkend="thread.concepts.lock-models">model</link>
the specified locking strategies:
<informaltable>
<tgroup cols="2" align="left">
<thead>
<row>
<entry>Lock Name</entry>
<entry>Lock Concept</entry>
</row>
</thead>
<tbody>
<row>
<entry>scoped_lock</entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
<row>
<entry>scoped_try_lock</entry>
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
</row>
<row>
<entry>scoped_timed_lock</entry>
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>The <classname>timed_mutex</classname> class uses an
<link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
locking strategy, so attempts to recursively lock a <classname>timed_mutex</classname>
object or attempts to unlock one by threads that don't own a lock on it result in
<emphasis role="bold">undefined behavior</emphasis>.
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
<code>NDEBUG</code> is not defined.</para>
<para>Like all
<link linkend="thread.concepts.mutex-models">mutex models</link>
in &Boost.Thread;, <classname>timed_mutex</classname> leaves the
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
Programmers should make no assumptions about the order in which
waiting threads acquire a lock.</para>
</description>
<inherit access="private">
<type><classname>boost::noncopyable</classname></type>
<purpose>Exposition only</purpose>
</inherit>
<typedef name="scoped_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_try_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_timed_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<constructor>
<effects>Constructs a <classname>timed_mutex</classname> object.
</effects>
<postconditions><code>*this</code> is in an unlocked state.
</postconditions>
</constructor>
<destructor>
<effects>Destroys a <classname>timed_mutex</classname> object.</effects>
<requires><code>*this</code> is in an unlocked state.</requires>
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
locked mutex is a serious programming error resulting in undefined
behavior such as a program crash.</notes>
</destructor>
</class>
</namespace>
</header>

View File

@@ -1,359 +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 summary="header" 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 summary="lock types" 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="#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&#39;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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,337 +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 summary="header" 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&#39;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&#39;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&#39;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&#39;s locked it
before the mutex model&#39;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&#39;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 summary="Mutex expressions" 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 summary="TryMutex expressions" 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 summary="TimedMutex expressions" 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 summary="Mutex concept classes" 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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>

90
doc/once-ref.xml Normal file
View File

@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/once.hpp"
last-revision="$Date$">
<macro name="BOOST_ONCE_INIT">
<purpose>The <functionname>call_once</functionname> function and
<code>once_flag</code> type (statically initialized to
<macroname>BOOST_ONCE_INIT</macroname>) can be used to run a
routine exactly once. This can be used to initialize data in a
<link linkend="thread.glossary.thread-safe">thread-safe</link>
manner.</purpose>
<description>The implementation-defined macro
<macroname>BOOST_ONCE_INIT</macroname> is a constant value used to
initialize <code>once_flag</code> instances to indicate that the
logically associated routine has not been run yet. See
<functionname>call_once</functionname> for more details.</description>
</macro>
<namespace name="boost">
<typedef name="once_flag">
<purpose>The <functionname>call_once</functionname> function and
<code>once_flag</code> type (statically initialized to
<macroname>BOOST_ONCE_INIT</macroname>) can be used to run a
routine exactly once. This can be used to initialize data in a
<link linkend="thread.glossary.thread-safe">thread-safe</link>
manner.</purpose>
<description>The implementation-defined type <code>once_flag</code>
is used as a flag to insure a routine is called only once.
Instances of this type should be statically initialized to
<macroname>BOOST_ONCE_INIT</macroname>. See
<functionname>call_once</functionname> for more details.
</description>
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<function name="call_once">
<purpose>The <functionname>call_once</functionname> function and
<code>once_flag</code> type (statically initialized to
<macroname>BOOST_ONCE_INIT</macroname>) can be used to run a
routine exactly once. This can be used to initialize data in a
<link linkend="thread.glossary.thread-safe">thread-safe</link>
manner.</purpose>
<description>
<para>Example usage is as follows:</para>
<para>
<programlisting>//Example usage:
boost::once_flag once = BOOST_ONCE_INIT;
void init()
{
//...
}
void thread_proc()
{
boost::call_once(&amp;init, once);
}</programlisting>
</para></description>
<parameter name="func">
<paramtype>void (*func)()</paramtype>
</parameter>
<parameter name="flag">
<paramtype>once_flag&amp;</paramtype>
</parameter>
<requires>The function <code>func</code> shall not throw
exceptions.</requires>
<effects>As if (in an atomic fashion):
<code>if (flag == BOOST_ONCE_INIT) func();</code></effects>
<postconditions><code>flag != BOOST_ONCE_INIT</code>
</postconditions>
</function>
</namespace>
</header>

View File

@@ -1,224 +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 summary="header" 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 called 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. 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.
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!</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>
<li><a href="definitions.html#Deadlock">Deadlock</a> (sometimes
called &quot;deadly embrace&quot;)</li>
<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. These aren&#39;t rare or exotic failures
- they are virtually guaranteed to occur unless multi-threaded code is
designed to avoid them. 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. That can make testing and debugging a
nightmare:</p>
<ul>
<li>Failures are often not repeatable.</li>
<li>Probe effect causes debuggers to produce very different results
from non-debug uses.</li>
<li>Debuggers require special support to show thread state.</li>
<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.</li>
<li>For programs which create a varying number of threads according
to workload, tests which don&#39;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>]. 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>Doing some reading before attempting multi-threaded designs will give
you a head start toward 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.</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</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. 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. 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. 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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p>&copy; Copyright 2001 Beman Dawes</p>
</body>
</html>

206
doc/overview.xml Normal file
View File

@@ -0,0 +1,206 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<section id="thread.overview" last-revision="$Date$">
<title>Overview</title>
<section id="thread.introduction">
<title>Introduction</title>
<para>&Boost.Thread; allows C++ programs to execute as multiple,
asynchronous, independent threads-of-execution. Each thread has its own
machine state including program instruction counter and registers. Programs
which execute as multiple threads are called multithreaded programs to
distinguish them from traditional single-threaded programs. The <link
linkend="thread.glossary">glossary</link> gives a more complete description
of the multithreading execution environment.</para>
<para>Multithreading provides several advantages:
<itemizedlist>
<listitem>
<para>Programs which would otherwise block waiting for some external
event can continue to respond if the blocking operation is placed in a
separate thread. Multithreading is usually an absolute requirement for
these programs.</para>
</listitem>
<listitem>
<para>Well-designed multithreaded programs may execute faster than
single-threaded programs, particularly on multiprocessor hardware.
Note, however, that poorly-designed multithreaded programs are often
slower than single-threaded programs.</para>
</listitem>
<listitem>
<para>Some program designs may be easier to formulate using a
multithreaded approach. After all, the real world is
asynchronous!</para>
</listitem>
</itemizedlist></para>
</section>
<section>
<title>Dangers</title>
<section>
<title>General considerations</title>
<para>Beyond the errors which can occur in single-threaded programs,
multithreaded programs are subject to additional errors:
<itemizedlist>
<listitem>
<para><link linkend="thread.glossary.race-condition">Race
conditions</link></para>
</listitem>
<listitem>
<para><link linkend="thread.glossary.deadlock">Deadlock</link>
(sometimes called "deadly embrace")</para>
</listitem>
<listitem>
<para><link linkend="thread.glossary.priority-failure">Priority
failures</link> (priority inversion, infinite overtaking, starvation,
etc.)</para>
</listitem>
</itemizedlist></para>
<para>Every multithreaded program must be designed carefully to avoid these
errors. These aren't rare or exotic failures - they are virtually guaranteed
to occur unless multithreaded code is designed to avoid them. Priority
failures are somewhat less common, but are nonetheless serious.</para>
<para>The <link linkend="thread.design">&Boost.Thread; design</link>
attempts to minimize these errors, but they will still occur unless the
programmer proactively designs to avoid them.</para>
<note>Please also see <xref linkend="thread.implementation_notes"/>
for additional, implementation-specific considerations.</note>
</section>
<section>
<title>Testing and debugging considerations</title>
<para>Multithreaded 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. That can make testing and debugging a
nightmare:
<itemizedlist>
<listitem>
<para>Failures are often not repeatable.</para>
</listitem>
<listitem>
<para>Probe effect causes debuggers to produce very different results
from non-debug uses.</para>
</listitem>
<listitem>
<para>Debuggers require special support to show thread state.</para>
</listitem>
<listitem>
<para>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.</para>
</listitem>
<listitem>
<para>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.</para>
</listitem>
</itemizedlist></para>
</section>
<section>
<title>Getting a head start</title>
<para>Although it might appear that multithreaded programs are inherently
unreliable, many reliable multithreaded programs do exist. Multithreading
techniques are known which lead to reliable programs.</para>
<para>Design patterns for reliable multithreaded programs, including the
important <emphasis>monitor</emphasis> pattern, are presented in
<emphasis>Pattern-Oriented Software Architecture Volume 2 - Patterns for
Concurrent and Networked Objects</emphasis>
&cite.SchmidtStalRohnertBuschmann;. Many important multithreading programming
considerations (independent of threading library) are discussed in
<emphasis>Programming with POSIX Threads</emphasis> &cite.Butenhof97;.</para>
<para>Doing some reading before attempting multithreaded designs will
give you a head start toward reliable multithreaded programs.</para>
</section>
</section>
<section>
<title>C++ Standard Library usage in multithreaded programs</title>
<section>
<title>Runtime libraries</title>
<para>
<emphasis role="bold">Warning:</emphasis> Multithreaded programs such as
those using &Boost.Thread; must link to <link
linkend="thread.glossary.thread-safe">thread-safe</link> versions of
all runtime libraries used by the program, including the runtime library
for the C++ Standard Library. Failure to do so will cause <link
linkend="thread.glossary.race-condition">race conditions</link> to occur
when multiple threads simultaneously execute runtime library functions for
<code>new</code>, <code>delete</code>, or other language features which
imply shared state.</para>
</section>
<section>
<title>Potentially non-thread-safe functions</title>
<para>Certain C++ Standard Library functions inherited from C are
particular problems because they hold internal state between
calls:
<itemizedlist>
<listitem>
<para><code>rand</code></para>
</listitem>
<listitem>
<para><code>strtok</code></para>
</listitem>
<listitem>
<para><code>asctime</code></para>
</listitem>
<listitem>
<para><code>ctime</code></para>
</listitem>
<listitem>
<para><code>gmtime</code></para>
</listitem>
<listitem>
<para><code>localtime</code></para>
</listitem>
</itemizedlist></para>
<para>It is possible to write thread-safe implementations of these by
using thread specific storage (see
<classname>boost::thread_specific_ptr</classname>), and several C++
compiler vendors do just that. The technique is well-know and is explained
in &cite.Butenhof97;.</para>
<para>But at least one vendor (HP-UX) does not provide thread-safe
implementations of the above functions in their otherwise thread-safe
runtime library. Instead they provide replacement functions with
different names and arguments.</para>
<para><emphasis role="bold">Recommendation:</emphasis> For the most
portable, yet thread-safe code, use Boost replacements for the problem
functions. See the <libraryname>Boost Random Number Library</libraryname>
and <libraryname>Boost Tokenizer Library</libraryname>.</para>
</section>
</section>
<section>
<title>Common guarantees for all &Boost.Thread; components</title>
<section>
<title>Exceptions</title>
<para>&Boost.Thread; destructors never
throw exceptions. Unless otherwise specified, other
&Boost.Thread; functions that do not have
an exception-specification may throw implementation-defined
exceptions.</para>
<para>In particular, &Boost.Thread;
reports failure to allocate storage by throwing an exception of type
<code>std::bad_alloc</code> or a class derived from
<code>std::bad_alloc</code>, failure to obtain thread resources other than
memory by throwing an exception of type
<classname>boost::thread_resource_error</classname>, and certain lock
related failures by throwing an exception of type
<classname>boost::lock_error</classname>.</para>
<para><emphasis role="bold">Rationale:</emphasis> Follows the C++ Standard
Library practice of allowing all functions except destructors or other
specified functions to throw exceptions on errors.</para>
</section>
<section>
<title>NonCopyable requirement</title>
<para>&Boost.Thread; classes documented as
meeting the NonCopyable requirement disallow copy construction and copy
assignment. For the sake of exposition, the synopsis of such classes show
private derivation from <classname>boost::noncopyable</classname>. Users
should not depend on this derivation, however, as implementations are free
to meet the NonCopyable requirement in other ways.</para>
</section>
</section>
</section>

View File

@@ -1,481 +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 summary="header" 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 &quot;potential parallelism&quot;
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&#39;t
directly support this concept.</p>
<p>Many platforms support multi-threaded programming despite the fact
that the language doesn&#39;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
&quot;pthread&quot; 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&#39;s available in a C library.</p>
<p>What&#39;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&#39;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 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&#39;s no way to mathematically prove
that a usage pattern is correct, meaning it doesn&#39;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&#39;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&#39;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&#39;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&#39;s not
thread-safe itself?</p>
<p>A lock object is not a synchronization primitive. A lock
object&#39;s sole responsibility is to ensure that a mutex is both
locked and unlocked in a manner that won&#39;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&#39;t be shared between threads.
Only the mutex objects will be created outside of block scope and/or
shared between threads. Though it&#39;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&#39;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&#39;t
a problem, and so long as the lock object is properly used there&#39;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&#39;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&#39;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&#39;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
&quot;reference management&quot; were used, such as ref-counting or
ref-lists, and many argued for a boost::thread_ref design instead. The
reasoning was that copying &quot;thread&quot; 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&#39;t appear to bear
them out. To illustrate the analysis we&#39;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&#39;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&#39;s only one that requires reference
management (number 6). Hopefully it&#39;s fairly obvious that this
usage pattern simply won&#39;t occur as often as the other usage
patterns. So there really isn&#39;t a &quot;typical need&quot; for a
thread concept, though there is some need.</p>
<p>Since the need isn&#39;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&#39;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&#39;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&#39;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&#39;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&#39;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&#39;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&#39;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. <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. 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. 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. They have written programs
which work using event variables, and wonder what the problem is. It
seems similar to the &quot;goto considered harmful&quot; controversy of
30 years ago. It isn&#39;t that events, like gotos, can&#39;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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>

438
doc/rationale.xml Normal file
View File

@@ -0,0 +1,438 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<section id="thread.rationale" last-revision="$Date$">
<title>Rationale</title>
<para>This page explains the rationale behind various design decisions in the
&Boost.Thread; library. Having the rationale documented here should explain
how we arrived at the current design as well as prevent future rehashing of
discussions and thought processes that have already occurred. It can also give
users a lot of insight into the design process required for this
library.</para>
<section id="thread.rationale.Boost.Thread">
<title>Rationale for the Creation of &Boost.Thread;</title>
<para>Processes often have a degree of "potential parallelism" and it can
often be more intuitive to design systems with this in mind. Further, these
parallel processes can result in more responsive programs. The benefits for
multithreaded programming are quite well known to most modern programmers,
yet the C++ language doesn't directly support this concept.</para>
<para>Many platforms support multithreaded 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.</para>
<para>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.</para>
<para>What's truly needed is C++ language support for threads. However, the
C++ standards committee needs existing practice or a good proposal as a
starting point for adding this to the standard.</para>
<para>The &Boost.Thread; library was developed to provide a C++ developer
with a portable interface for writing multithreaded programs on numerous
platforms. There's a hope that the library can be the basis for a more
detailed proposal for the C++ standards committee to consider for inclusion
in the next C++ standard.</para>
</section>
<section id="thread.rationale.primitives">
<title>Rationale for the Low Level Primitives Supported in &Boost.Thread;</title>
<para>The &Boost.Thread; library supplies a set of low level primitives for
writing multithreaded programs, such as mutexes and condition variables. In
fact, the first release of &Boost.Thread; supports only these low level
primitives. However, computer science research has shown that use of these
primitives is difficult since it's difficult to mathematically prove that a
usage pattern is correct, meaning it doesn't result in race conditions or
deadlocks. There are several algebras (such as CSP, CCS and Join calculus)
that have been developed to help write provably correct parallel
processes. In order to prove the correctness these processes must be coded
using higher level abstractions. So why does &Boost.Thread; support the
lower level concepts?</para>
<para>The reason is simple: the higher level concepts need to be implemented
using at least some of the lower level concepts. So having portable lower
level concepts makes it easier to develop the higher level concepts and will
allow researchers to experiment with various techniques.</para>
<para>Beyond this theoretical application of higher level concepts, however,
the fact remains that many multithreaded 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 unfamiliar with any of the higher
level concepts, supporting the lower level concepts provides
greater accessibility.</para>
</section>
<section id="thread.rationale.locks">
<title>Rationale for the Lock Design</title>
<para>Programmers who are used to multithreaded programming issues will
quickly note that the &Boost.Thread; design for mutex lock concepts is not
<link linkend="thread.glossary.thread-safe">thread-safe</link> (this is
clearly documented as well). At first this may seem like a serious design
flaw. Why have a multithreading primitive that's not thread-safe
itself?</para>
<para>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 (in fact, to do so would likely be an
error). Nor are there any cases when such usage would be required.</para>
<para>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.</para>
<para>So, to avoid the overhead of synchronizing access to the state
information and to avoid the race condition, the &Boost.Thread; library
simply does nothing to make lock objects thread-safe. Instead, sharing a
lock object between threads results in undefined behavior. Since the only
proper usage of lock objects is within block scope this isn't a problem, and
so long as the lock object is properly used there's no danger of any
multithreading issues.</para>
</section>
<section id="thread.rationale.non-copyable">
<title>Rationale for NonCopyable Thread Type</title>
<para>Programmers who are used to C libraries for multithreaded programming
are likely to wonder why &Boost.Thread; uses a noncopyable design for
<classname>boost::thread</classname>. After all, the C thread types are
copyable, and you often have a need for copying them within user
code. However, careful comparison of C designs to C++ designs shows a flaw
in this logic.</para>
<para>All C types are copyable. It is, in fact, not possible to make a
noncopyable 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 resource. 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.</para>
<para>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.</para>
<para>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 than
wrappers (such as boost::shared_ptr) around a noncopyable thread
concept. Analysis of whether or not these arguments would hold true doesn'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.</para>
<section id="thread.rationale.non-copyable.simple">
<title>1. Use case: Simple creation of a thread.</title>
<programlisting>
void foo()
{
create_thread(&amp;bar);
}
</programlisting>
</section>
<section id="thread.rationale.non-copyable.joined">
<title>2. Use case: Creation of a thread that's later joined.</title>
<programlisting>
void foo()
{
thread = create_thread(&amp;bar);
join(thread);
}
</programlisting>
</section>
<section id="thread.rationale.non-copyable.loop">
<title>3. Use case: Simple creation of several threads in a loop.</title>
<programlisting>
void foo()
{
for (int i=0; i&lt;NUM_THREADS; ++i)
create_thread(&amp;bar);
}
</programlisting>
</section>
<section id="thread.rationale.non-copyable.loop-join">
<title>4. Use case: Creation of several threads in a loop which are later joined.</title>
<programlisting>
void foo()
{
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();
}
</programlisting>
</section>
<section id="thread.rationale.non-copyable.pass">
<title>5. Use case: Creation of a thread whose ownership is passed to another object/method.</title>
<programlisting>
void foo()
{
thread = create_thread(&amp;bar);
manager.owns(thread);
}
</programlisting>
</section>
<section id="thread.rationale.non-copyable.shared">
<title>6. Use case: Creation of a thread whose ownership is shared between multiple
objects.</title>
<programlisting>
void foo()
{
thread = create_thread(&amp;bar);
manager1.add(thread);
manager2.add(thread);
}
</programlisting>
</section>
<para>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.</para>
<para>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.</para>
<para>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.</para>
<para>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.</para>
<section id="thread.rationale_comparison.non-copyable.simple">
<title>1. Comparison: simple creation of a thread.</title>
<programlisting>
void foo()
{
thread thrd(&amp;bar);
}
void foo()
{
thread_ref thrd = create_thread(&amp;bar);
}
</programlisting>
</section>
<section id="thread.rationale_comparison.non-copyable.joined">
<title>2. Comparison: creation of a thread that's later joined.</title>
<programlisting>
void foo()
{
thread thrd(&amp;bar);
thrd.join();
}
void foo()
{
thread_ref thrd =
create_thread(&amp;bar);thrd-&gt;join();
}
</programlisting>
</section>
<section id="thread.rationale_comparison.non-copyable.loop">
<title>3. Comparison: simple creation of several threads in a loop.</title>
<programlisting>
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);
}
</programlisting>
</section>
<section id="thread.rationale_comparison.non-copyable.loop-join">
<title>4. Comparison: creation of several threads in a loop which are later joined.</title>
<programlisting>
void foo()
{
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();
}
</programlisting>
</section>
<section id="thread.rationale_comparison.non-copyable.pass">
<title>5. Comparison: creation of a thread whose ownership is passed to another object/method.</title>
<programlisting>
void foo()
{
thread thrd* = new thread(&amp;bar);
manager.owns(thread);
}
void foo()
{
thread_ref thrd = create_thread(&amp;bar);
manager.owns(thrd);
}
</programlisting>
</section>
<section id="thread.rationale_comparison.non-copyable.shared">
<title>6. Comparison: creation of a thread whose ownership is shared
between multiple objects.</title>
<programlisting>
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);
}
</programlisting>
</section>
<para>This shows the usage patterns being nearly identical in complexity for
both designs. The only actual added complexity occurs because of the use of
operator new in
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>,
<link linkend="thread.rationale_comparison.non-copyable.pass">(5)</link>, and
<link linkend="thread.rationale_comparison.non-copyable.shared">(6)</link>;
and the use of std::auto_ptr and boost::shared_ptr in
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link> and
<link linkend="thread.rationale_comparison.non-copyable.shared">(6)</link>
respectively. However, that's not really
much added complexity, and C++ programmers are used to using these idioms
anyway. Some may dislike the presence of operator new in user code, but
this can be eliminated by proper design of higher level concepts, such as
the boost::thread_group class that simplifies example
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>
down to:</para>
<programlisting>
void foo()
{
thread_group threads;
for (int i=0; i&lt;NUM_THREADS; ++i)
threads.create_thread(&amp;bar);
threads.join_all();
}
</programlisting>
<para>So ease of use is really a wash and not much help in picking a
design.</para>
<para>So what about performance? Looking at the above code examples,
we can analyze the theoretical impact to performance that both designs
have. For <link linkend="thread.rationale_comparison.non-copyable.simple">(1)</link>
we can see that platforms that don't have a ref-counted native
thread type (POSIX, for instance) will be impacted by a thread_ref
design. Even if the native thread type is ref-counted there may be an impact
if more state information has to be maintained for concepts foreign to the
native API, such as clean up stacks for Win32 implementations.
For <link linkend="thread.rationale_comparison.non-copyable.joined">(2)</link>
and <link linkend="thread.rationale_comparison.non-copyable.loop">(3)</link>
the performance impact will be identical to
<link linkend="thread.rationale_comparison.non-copyable.simple">(1)</link>.
For <link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>
things get a little more interesting and we find that theoretically at least
the thread_ref may perform faster since the thread design requires dynamic
memory allocation/deallocation. However, in practice there may be dynamic
allocation for the thread_ref design as well, it will just be hidden from
the user. As long as the implementation has to do dynamic allocations the
thread_ref loses again because of the reference management. For
<link linkend="thread.rationale_comparison.non-copyable.pass">(5)</link> we see
the same impact as we do for
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>.
For <link linkend="thread.rationale_comparison.non-copyable.shared">(6)</link>
we still have a possible impact to
the thread design because of dynamic allocation but thread_ref no longer
suffers because of its reference management, and in fact, theoretically at
least, the thread_ref may do a better job of managing the references. All of
this indicates that thread wins for
<link linkend="thread.rationale_comparison.non-copyable.simple">(1)</link>,
<link linkend="thread.rationale_comparison.non-copyable.joined">(2)</link> and
<link linkend="thread.rationale_comparison.non-copyable.loop">(3)</link>; with
<link linkend="thread.rationale_comparison.non-copyable.loop-join">(4)</link>
and <link linkend="thread.rationale_comparison.non-copyable.pass">(5)</link> the
winner depending on the implementation and the platform but with the thread design
probably having a better chance; and with
<link linkend="thread.rationale_comparison.non-copyable.shared">(6)</link>
it will again depend on the
implementation and platform but this time we favor thread_ref
slightly. Given all of this it's a narrow margin, but the thread design
prevails.</para>
<para>Given this analysis, and the fact that noncopyable objects for system
resources are the normal designs that C++ programmers are used to dealing
with, the &Boost.Thread; library has gone with a noncopyable design.</para>
</section>
<section id="thread.rationale.events">
<title>Rationale for not providing <emphasis>Event Variables</emphasis></title>
<para><emphasis>Event variables</emphasis> are simply far too
error-prone. <classname>boost::condition</classname> variables are a much safer
alternative. [Note that Graphical User Interface <emphasis>events</emphasis> are
a different concept, and are not what is being discussed here.]</para>
<para>Event variables were one of the first synchronization primitives. They
are still used today, for example, in the native Windows multithreading
API. 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.</para>
<para>Per Brinch Hansen &cite.Hansen73; analyzed event variables in some
detail, pointing out [emphasis his] that "<emphasis>event operations force
the programmer to be aware of the relative speeds of the sending and
receiving processes</emphasis>". His summary:</para>
<blockquote>
<para>We must therefore conclude that event variables of the previous type
are impractical for system design. <emphasis>The effect of an interaction
between two processes must be independent of the speed at which it is
carried out.</emphasis></para>
</blockquote>
<para>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. Overt problems can be avoided, for example, by teaming the event
variable with a mutex, but that may just convert a <link
linkend="thread.glossary.race-condition">race condition</link> into another
problem, such as excessive resource use. One of the most distressing aspects
of the experience reports is the claim that many defects are latent. That
is, the programs appear to work correctly, but contain hidden timing
dependencies which will cause them to fail when environmental factors or
usage patterns change, altering relative thread timings.</para>
<para>The decision to exclude event variables from &Boost.Thread; has been
surprising to some Windows programmers. They have written programs which
work using event variables, and wonder what the problem is. It seems similar
to the "goto considered harmful" controversy of 30 years ago. It isn't that
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 will be less likely to contain latent defects.</para>
<para>[Rationale provided by Beman Dawes]</para>
</section>
</section>

View File

@@ -0,0 +1,492 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/read_write_mutex.hpp"
last-revision="$Date$">
<namespace name="boost">
<namespace name="read_write_scheduling_policy">
<enum name="read_write_scheduling_policy">
<enumvalue name="writer_priority" />
<enumvalue name="reader_priority" />
<enumvalue name="alternating_many_reads" />
<enumvalue name="alternating_single_read" />
<purpose>
<para>Specifies the
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
to use when a set of threads try to obtain different types of
locks simultaneously.</para>
</purpose>
<description>
<para>The only clock type supported by &Boost.Thread; is
<code>TIME_UTC</code>. The epoch for <code>TIME_UTC</code>
is 1970-01-01 00:00:00.</para>
</description>
</enum>
</namespace>
<class name="read_write_mutex">
<purpose>
<para>The <classname>read_write_mutex</classname> class is a model of the
<link linkend="thread.concepts.ReadWriteMutex">ReadWriteMutex</link> concept.</para>
<note> Unfortunately it turned out that the current implementation of Read/Write Mutex has
some serious problems. So it was decided not to put this implementation into
release grade code. Also discussions on the mailing list led to the
conclusion that the current concepts need to be rethought. In particular
the schedulings <link linkend="thread.concepts.read-write-scheduling-policies.inter-class">
Inter-Class Scheduling Policies</link> are deemed unnecessary.
There seems to be common belief that a fair scheme suffices.
The following documentation has been retained however, to give
readers of this document the opportunity to study the original design.
</note>
</purpose>
<description>
<para>The <classname>read_write_mutex</classname> class is a model of the
<link linkend="thread.concepts.ReadWriteMutex">ReadWriteMutex</link> concept.
It should be used to synchronize access to shared resources using
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
locking mechanics.</para>
<para>For classes that model related mutex concepts, see
<classname>try_read_write_mutex</classname> and <classname>timed_read_write_mutex</classname>.</para>
<para>The <classname>read_write_mutex</classname> class supplies the following typedefs,
which <link linkend="thread.concepts.read-write-lock-models">model</link>
the specified locking strategies:
<informaltable>
<tgroup cols="2" align="left">
<thead>
<row>
<entry>Lock Name</entry>
<entry>Lock Concept</entry>
</row>
</thead>
<tbody>
<row>
<entry>scoped_read_write_lock</entry>
<entry><link linkend="thread.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
</row>
<row>
<entry>scoped_read_lock</entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
<row>
<entry>scoped_write_lock</entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>The <classname>read_write_mutex</classname> class uses an
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
locking strategy, so attempts to recursively lock a <classname>read_write_mutex</classname>
object or attempts to unlock one by threads that don't own a lock on it result in
<emphasis role="bold">undefined behavior</emphasis>.
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
<code>NDEBUG</code> is not defined.</para>
<para>Like all
<link linkend="thread.concepts.read-write-mutex-models">read/write mutex models</link>
in &Boost.Thread;, <classname>read_write_mutex</classname> has two types of
<link linkend="thread.concepts.read-write-scheduling-policies">scheduling policies</link>, an
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
between threads trying to obtain different types of locks and an
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link>
between threads trying to obtain the same type of lock.
The <classname>read_write_mutex</classname> class allows the
programmer to choose what
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
will be used; however, like all read/write mutex models,
<classname>read_write_mutex</classname> leaves the
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>.
</para>
<note>Self-deadlock is virtually guaranteed if a thread tries to
lock the same <classname>read_write_mutex</classname> multiple times
unless all locks are read-locks (but see below)</note>
</description>
<inherit access="private">
<type><classname>boost::noncopyable</classname></type>
<purpose>Exposition only</purpose>
</inherit>
<inherit access="private">
<type><classname>boost::noncopyable</classname></type>
<purpose>Exposition only</purpose>
</inherit>
<typedef name="scoped_read_write_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_read_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_write_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<constructor>
<parameter name="count">
<paramtype>boost::read_write_scheduling_policy</paramtype>
</parameter>
<effects>Constructs a <classname>read_write_mutex</classname> object.
</effects>
<postconditions><code>*this</code> is in an unlocked state.
</postconditions>
</constructor>
<destructor>
<effects>Destroys a <classname>read_write_mutex</classname> object.</effects>
<requires><code>*this</code> is in an unlocked state.</requires>
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
locked mutex is a serious programming error resulting in undefined
behavior such as a program crash.</notes>
</destructor>
</class>
<class name="try_read_write_mutex">
<purpose>
<para>The <classname>try_read_write_mutex</classname> class is a model of the
<link linkend="thread.concepts.TryReadWriteMutex">TryReadWriteMutex</link> concept.</para>
<note> Unfortunately it turned out that the current implementation of Read/Write Mutex has
some serious problems. So it was decided not to put this implementation into
release grade code. Also discussions on the mailing list led to the
conclusion that the current concepts need to be rethought. In particular
the schedulings <link linkend="thread.concepts.read-write-scheduling-policies.inter-class">
Inter-Class Scheduling Policies</link> are deemed unnecessary.
There seems to be common belief that a fair scheme suffices.
The following documentation has been retained however, to give
readers of this document the opportunity to study the original design.
</note>
</purpose>
<description>
<para>The <classname>try_read_write_mutex</classname> class is a model of the
<link linkend="thread.concepts.TryReadWriteMutex">TryReadWriteMutex</link> concept.
It should be used to synchronize access to shared resources using
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
locking mechanics.</para>
<para>For classes that model related mutex concepts, see
<classname>read_write_mutex</classname> and <classname>timed_read_write_mutex</classname>.</para>
<para>The <classname>try_read_write_mutex</classname> class supplies the following typedefs,
which <link linkend="thread.concepts.read-write-lock-models">model</link>
the specified locking strategies:
<informaltable>
<tgroup cols="2" align="left">
<thead>
<row>
<entry>Lock Name</entry>
<entry>Lock Concept</entry>
</row>
</thead>
<tbody>
<row>
<entry>scoped_read_write_lock</entry>
<entry><link linkend="thread.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
</row>
<row>
<entry>scoped_try_read_write_lock</entry>
<entry><link linkend="thread.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
</row>
<row>
<entry>scoped_read_lock</entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
<row>
<entry>scoped_try_read_lock</entry>
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
</row>
<row>
<entry>scoped_write_lock</entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
<row>
<entry>scoped_try_write_lock</entry>
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>The <classname>try_read_write_mutex</classname> class uses an
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
locking strategy, so attempts to recursively lock a <classname>try_read_write_mutex</classname>
object or attempts to unlock one by threads that don't own a lock on it result in
<emphasis role="bold">undefined behavior</emphasis>.
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
<code>NDEBUG</code> is not defined.</para>
<para>Like all
<link linkend="thread.concepts.read-write-mutex-models">read/write mutex models</link>
in &Boost.Thread;, <classname>try_read_write_mutex</classname> has two types of
<link linkend="thread.concepts.read-write-scheduling-policies">scheduling policies</link>, an
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
between threads trying to obtain different types of locks and an
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link>
between threads trying to obtain the same type of lock.
The <classname>try_read_write_mutex</classname> class allows the
programmer to choose what
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
will be used; however, like all read/write mutex models,
<classname>try_read_write_mutex</classname> leaves the
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
<link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
</para>
<note>Self-deadlock is virtually guaranteed if a thread tries to
lock the same <classname>try_read_write_mutex</classname> multiple times
unless all locks are read-locks (but see below)</note>
</description>
<inherit access="private">
<type><classname>boost::noncopyable</classname></type>
<purpose>Exposition only</purpose>
</inherit>
<typedef name="scoped_read_write_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_try_read_write_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_read_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_try_read_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_write_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_try_write_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<constructor>
<parameter name="count">
<paramtype>boost::read_write_scheduling_policy</paramtype>
</parameter>
<effects>Constructs a <classname>try_read_write_mutex</classname> object.
</effects>
<postconditions><code>*this</code> is in an unlocked state.
</postconditions>
</constructor>
<destructor>
<effects>Destroys a <classname>try_read_write_mutex</classname> object.</effects>
<requires><code>*this</code> is in an unlocked state.</requires>
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
locked mutex is a serious programming error resulting in undefined
behavior such as a program crash.</notes>
</destructor>
</class>
<class name="timed_read_write_mutex">
<purpose>
<para>The <classname>timed_read_write_mutex</classname> class is a model of the
<link linkend="thread.concepts.TimedReadWriteMutex">TimedReadWriteMutex</link> concept.</para>
<note> Unfortunately it turned out that the current implementation of Read/Write Mutex has
some serious problems. So it was decided not to put this implementation into
release grade code. Also discussions on the mailing list led to the
conclusion that the current concepts need to be rethought. In particular
the schedulings <link linkend="thread.concepts.read-write-scheduling-policies.inter-class">
Inter-Class Scheduling Policies</link> are deemed unnecessary.
There seems to be common belief that a fair scheme suffices.
The following documentation has been retained however, to give
readers of this document the opportunity to study the original design.
</note>
</purpose>
<description>
<para>The <classname>timed_read_write_mutex</classname> class is a model of the
<link linkend="thread.concepts.TimedReadWriteMutex">TimedReadWriteMutex</link> concept.
It should be used to synchronize access to shared resources using
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
locking mechanics.</para>
<para>For classes that model related mutex concepts, see
<classname>read_write_mutex</classname> and <classname>try_read_write_mutex</classname>.</para>
<para>The <classname>timed_read_write_mutex</classname> class supplies the following typedefs,
which <link linkend="thread.concepts.read-write-lock-models">model</link>
the specified locking strategies:
<informaltable>
<tgroup cols="2" align="left">
<thead>
<row>
<entry>Lock Name</entry>
<entry>Lock Concept</entry>
</row>
</thead>
<tbody>
<row>
<entry>scoped_read_write_lock</entry>
<entry><link linkend="thread.concepts.ScopedReadWriteLock">ScopedReadWriteLock</link></entry>
</row>
<row>
<entry>scoped_try_read_write_lock</entry>
<entry><link linkend="thread.concepts.ScopedTryReadWriteLock">ScopedTryReadWriteLock</link></entry>
</row>
<row>
<entry>scoped_timed_read_write_lock</entry>
<entry><link linkend="thread.concepts.ScopedTimedReadWriteLock">ScopedTimedReadWriteLock</link></entry>
</row>
<row>
<entry>scoped_read_lock</entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
<row>
<entry>scoped_try_read_lock</entry>
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
</row>
<row>
<entry>scoped_timed_read_lock</entry>
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
</row>
<row>
<entry>scoped_write_lock</entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
<row>
<entry>scoped_try_write_lock</entry>
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
</row>
<row>
<entry>scoped_timed_write_lock</entry>
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>The <classname>timed_read_write_mutex</classname> class uses an
<link linkend="thread.concepts.read-write-locking-strategies.unspecified">Unspecified</link>
locking strategy, so attempts to recursively lock a <classname>timed_read_write_mutex</classname>
object or attempts to unlock one by threads that don't own a lock on it result in
<emphasis role="bold">undefined behavior</emphasis>.
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
<code>NDEBUG</code> is not defined.</para>
<para>Like all
<link linkend="thread.concepts.read-write-mutex-models">read/write mutex models</link>
in &Boost.Thread;, <classname>timed_read_write_mutex</classname> has two types of
<link linkend="thread.concepts.read-write-scheduling-policies">scheduling policies</link>, an
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
between threads trying to obtain different types of locks and an
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link>
between threads trying to obtain the same type of lock.
The <classname>timed_read_write_mutex</classname> class allows the
programmer to choose what
<link linkend="thread.concepts.read-write-scheduling-policies.inter-class">inter-class sheduling policy</link>
will be used; however, like all read/write mutex models,
<classname>timed_read_write_mutex</classname> leaves the
<link linkend="thread.concepts.read-write-scheduling-policies.intra-class">intra-class sheduling policy</link> as
<link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
</para>
<note>Self-deadlock is virtually guaranteed if a thread tries to
lock the same <classname>timed_read_write_mutex</classname> multiple times
unless all locks are read-locks (but see below)</note>
</description>
<typedef name="scoped_read_write_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_try_read_write_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_timed_read_write_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_read_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_try_read_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_timed_read_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_write_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_try_write_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_timed_write_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<constructor>
<parameter name="count">
<paramtype>boost::read_write_scheduling_policy</paramtype>
</parameter>
<effects>Constructs a <classname>timed_read_write_mutex</classname> object.
</effects>
<postconditions><code>*this</code> is in an unlocked state.
</postconditions>
</constructor>
<destructor>
<effects>Destroys a <classname>timed_read_write_mutex</classname> object.</effects>
<requires><code>*this</code> is in an unlocked state.</requires>
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
locked mutex is a serious programming error resulting in undefined
behavior such as a program crash.</notes>
</destructor>
</class>
</namespace>
</header>

306
doc/recursive_mutex-ref.xml Normal file
View File

@@ -0,0 +1,306 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/recursive_mutex.hpp"
last-revision="$Date$">
<namespace name="boost">
<class name="recursive_mutex">
<purpose>
<para>The <classname>recursive_mutex</classname> class is a model of the
<link linkend="thread.concepts.Mutex">Mutex</link> concept.</para>
</purpose>
<description>
<para>The <classname>recursive_mutex</classname> class is a model of the
<link linkend="thread.concepts.Mutex">Mutex</link> concept.
It should be used to synchronize access to shared resources using
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
locking mechanics.</para>
<para>For classes that model related mutex concepts, see
<classname>recursive_try_mutex</classname> and <classname>recursive_timed_mutex</classname>.</para>
<para>For <link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
locking mechanics, see <classname>mutex</classname>,
<classname>try_mutex</classname>, and <classname>timed_mutex</classname>.
</para>
<para>The <classname>recursive_mutex</classname> class supplies the following typedef,
which models the specified locking strategy:
<table>
<title>Supported Lock Types</title>
<tgroup cols="2" align="left">
<thead>
<row>
<entry>Lock Name</entry>
<entry>Lock Concept</entry>
</row>
</thead>
<tbody>
<row>
<entry>scoped_lock</entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>The <classname>recursive_mutex</classname> class uses a
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
locking strategy, so attempts to recursively lock a
<classname>recursive_mutex</classname> object
succeed and an internal "lock count" is maintained.
Attempts to unlock a <classname>recursive_mutex</classname> object
by threads that don't own a lock on it result in
<emphasis role="bold">undefined behavior</emphasis>.</para>
<para>Like all
<link linkend="thread.concepts.mutex-models">mutex models</link>
in &Boost.Thread;, <classname>recursive_mutex</classname> leaves the
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
Programmers should make no assumptions about the order in which
waiting threads acquire a lock.</para>
</description>
<inherit access="private">
<type><classname>boost::noncopyable</classname></type>
<purpose>Exposition only</purpose>
</inherit>
<typedef name="scoped_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<constructor>
<effects>Constructs a <classname>recursive_mutex</classname> object.
</effects>
<postconditions><code>*this</code> is in an unlocked state.
</postconditions>
</constructor>
<destructor>
<effects>Destroys a <classname>recursive_mutex</classname> object.</effects>
<requires><code>*this</code> is in an unlocked state.</requires>
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
locked mutex is a serious programming error resulting in undefined
behavior such as a program crash.</notes>
</destructor>
</class>
<class name="recursive_try_mutex">
<purpose>
<para>The <classname>recursive_try_mutex</classname> class is a model of the
<link linkend="thread.concepts.TryMutex">TryMutex</link> concept.</para>
</purpose>
<description>
<para>The <classname>recursive_try_mutex</classname> class is a model of the
<link linkend="thread.concepts.TryMutex">TryMutex</link> concept.
It should be used to synchronize access to shared resources using
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
locking mechanics.</para>
<para>For classes that model related mutex concepts, see
<classname>recursive_mutex</classname> and <classname>recursive_timed_mutex</classname>.</para>
<para>For <link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
locking mechanics, see <classname>mutex</classname>,
<classname>try_mutex</classname>, and <classname>timed_mutex</classname>.
</para>
<para>The <classname>recursive_try_mutex</classname> class supplies the following typedefs,
which model the specified locking strategies:
<table>
<title>Supported Lock Types</title>
<tgroup cols="2" align="left">
<thead>
<row>
<entry>Lock Name</entry>
<entry>Lock Concept</entry>
</row>
</thead>
<tbody>
<row>
<entry>scoped_lock</entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
<row>
<entry>scoped_try_lock</entry>
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>The <classname>recursive_try_mutex</classname> class uses a
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
locking strategy, so attempts to recursively lock a
<classname>recursive_try_mutex</classname> object
succeed and an internal "lock count" is maintained.
Attempts to unlock a <classname>recursive_mutex</classname> object
by threads that don't own a lock on it result in
<emphasis role="bold">undefined behavior</emphasis>.</para>
<para>Like all
<link linkend="thread.concepts.mutex-models">mutex models</link>
in &Boost.Thread;, <classname>recursive_try_mutex</classname> leaves the
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
Programmers should make no assumptions about the order in which
waiting threads acquire a lock.</para>
</description>
<inherit access="private">
<type><classname>boost::noncopyable</classname></type>
<purpose>Exposition only</purpose>
</inherit>
<typedef name="scoped_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_try_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<constructor>
<effects>Constructs a <classname>recursive_try_mutex</classname> object.
</effects>
<postconditions><code>*this</code> is in an unlocked state.
</postconditions>
</constructor>
<destructor>
<effects>Destroys a <classname>recursive_try_mutex</classname> object.
</effects>
<requires><code>*this</code> is in an unlocked state.</requires>
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
locked mutex is a serious programming error resulting in undefined
behavior such as a program crash.</notes>
</destructor>
</class>
<class name="recursive_timed_mutex">
<purpose>
<para>The <classname>recursive_timed_mutex</classname> class is a model of the
<link linkend="thread.concepts.TimedMutex">TimedMutex</link> concept.</para>
</purpose>
<description>
<para>The <classname>recursive_timed_mutex</classname> class is a model of the
<link linkend="thread.concepts.TimedMutex">TimedMutex</link> concept.
It should be used to synchronize access to shared resources using
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
locking mechanics.</para>
<para>For classes that model related mutex concepts, see
<classname>recursive_mutex</classname> and <classname>recursive_try_mutex</classname>.</para>
<para>For <link linkend="thread.concepts.unspecified-locking-strategy">Unspecified</link>
locking mechanics, see <classname>mutex</classname>,
<classname>try_mutex</classname>, and <classname>timed_mutex</classname>.
</para>
<para>The <classname>recursive_timed_mutex</classname> class supplies the following typedefs,
which model the specified locking strategies:
<table>
<title>Supported Lock Types</title>
<tgroup cols="2" align="left">
<thead>
<row>
<entry>Lock Name</entry>
<entry>Lock Concept</entry>
</row>
</thead>
<tbody>
<row>
<entry>scoped_lock</entry>
<entry><link linkend="thread.concepts.ScopedLock">ScopedLock</link></entry>
</row>
<row>
<entry>scoped_try_lock</entry>
<entry><link linkend="thread.concepts.ScopedTryLock">ScopedTryLock</link></entry>
</row>
<row>
<entry>scoped_timed_lock</entry>
<entry><link linkend="thread.concepts.ScopedTimedLock">ScopedTimedLock</link></entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>The <classname>recursive_timed_mutex</classname> class uses a
<link linkend="thread.concepts.recursive-locking-strategy">Recursive</link>
locking strategy, so attempts to recursively lock a
<classname>recursive_timed_mutex</classname> object
succeed and an internal "lock count" is maintained.
Attempts to unlock a <classname>recursive_mutex</classname> object
by threads that don't own a lock on it result in
<emphasis role="bold">undefined behavior</emphasis>.</para>
<para>Like all
<link linkend="thread.concepts.mutex-models">mutex models</link>
in &Boost.Thread;, <classname>recursive_timed_mutex</classname> leaves the
<link linkend="thread.concepts.sheduling-policies">scheduling policy</link>
as <link linkend="thread.concepts.unspecified-scheduling-policy">Unspecified</link>.
Programmers should make no assumptions about the order in which
waiting threads acquire a lock.</para>
</description>
<inherit access="private">
<type><classname>boost::noncopyable</classname></type>
<purpose>Exposition only</purpose>
</inherit>
<typedef name="scoped_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_try_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<typedef name="scoped_timed_lock">
<type><emphasis>implementation-defined</emphasis></type>
</typedef>
<constructor>
<effects>Constructs a <classname>recursive_timed_mutex</classname> object.
</effects>
<postconditions><code>*this</code> is in an unlocked state.
</postconditions>
</constructor>
<destructor>
<effects>Destroys a <classname>recursive_timed_mutex</classname> object.</effects>
<requires><code>*this</code> is in an unlocked state.</requires>
<notes><emphasis role="bold">Danger:</emphasis> Destruction of a
locked mutex is a serious programming error resulting in undefined
behavior such as a program crash.</notes>
</destructor>
</class>
</namespace>
</header>

View File

@@ -1,368 +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 summary="header" 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 &quot;internal
synchronization&quot; 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>
<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 summary="lock types" 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 &quot;lock
count&quot; 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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>

30
doc/reference.xml Normal file
View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<library-reference id="thread.reference"
last-revision="$Date$"
xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="barrier-ref.xml"/>
<xi:include href="condition-ref.xml"/>
<xi:include href="exceptions-ref.xml"/>
<xi:include href="mutex-ref.xml"/>
<xi:include href="once-ref.xml"/>
<xi:include href="recursive_mutex-ref.xml"/>
<!--
The read_write_mutex is held back from release, since the
implementation suffers from a serious, yet unresolved bug.
The implementation is likely to appear in a reworked
form in the next release.
-->
<xi:include href="read_write_mutex-ref.xml"/>
<xi:include href="thread-ref.xml"/>
<xi:include href="tss-ref.xml"/>
<xi:include href="xtime-ref.xml"/>
</library-reference>

204
doc/release_notes.xml Normal file
View File

@@ -0,0 +1,204 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<section id="thread.release_notes" last-revision="$Date$">
<title>Release Notes</title>
<section id="thread.release_notes.boost_1_34_0">
<title>Boost 1.34.0</title>
<section id="thread.release_notes.boost_1_34_0.change_log.maintainance">
<title>New team of maintainers</title>
<para>
Since the original author William E. Kempf no longer is available to
maintain the &Boost.Thread; library, a new team has been formed
in an attempt to continue the work on &Boost.Thread;.
Fortunately William E. Kempf has given
<ulink url="http://lists.boost.org/Archives/boost/2006/09/110143.php">
permission </ulink>
to use his work under the boost license.
</para>
<para>
The team currently consists of
<itemizedlist>
<listitem>
Anthony Williams, for the Win32 platform,
</listitem>
<listitem>
Roland Schwarz, for the linux platform, and various "housekeeping" tasks.
</listitem>
</itemizedlist>
Volunteers for other platforms are welcome!
</para>
<para>
As the &Boost.Thread; was kind of orphaned over the last release, this release
attempts to fix the known bugs. Upcoming releases will bring in new things.
</para>
</section>
<section id="thread.release_notes.boost_1_34_0.change_log.read_write_mutex">
<title>read_write_mutex still broken</title>
<para>
<note>
It has been decided not to release the Read/Write Mutex, since the current
implementation suffers from a serious bug. The documentation of the concepts
has been included though, giving the interested reader an opportunity to study the
original concepts. Please refer to the following links if you are interested
which problems led to the decision to held back this mutex type.The issue
has been discovered before 1.33 was released and the code has
been omitted from that release. A reworked mutex is expected to appear in 1.35.
Also see:
<ulink url="http://lists.boost.org/Archives/boost/2005/08/92307.php">
read_write_mutex bug</ulink>
and
<ulink url="http://lists.boost.org/Archives/boost/2005/09/93180.php">
read_write_mutex fundamentally broken in 1.33</ulink>
</note>
</para>
</section>
</section>
<section id="thread.release_notes.boost_1_32_0">
<title>Boost 1.32.0</title>
<section id="thread.release_notes.boost_1_32_0.change_log.documentation">
<title>Documentation converted to BoostBook</title>
<para>The documentation was converted to BoostBook format,
and a number of errors and inconsistencies were
fixed in the process.
Since this was a fairly large task, there are likely to be
more errors and inconsistencies remaining. If you find any,
please report them!</para>
</section>
<section id="thread.release_notes.boost_1_32_0.change_log.static_link">
<title>Statically-link build option added</title>
<para>The option to link &Boost.Thread; as a static
library has been added (with some limitations on Win32 platforms).
This feature was originally removed from an earlier version
of Boost because <classname>boost::thread_specific_ptr</classname>
required that &Boost.Thread; be dynamically linked in order
for its cleanup functionality to work on Win32 platforms.
Because this limitation never applied to non-Win32 platforms,
because significant progress has been made in removing
the limitation on Win32 platforms (many thanks to
Aaron LaFramboise and Roland Scwarz!), and because the lack
of static linking is one of the most common complaints of
&Boost.Thread; users, this decision was reversed.</para>
<para>On non-Win32 platforms:
To choose the dynamically linked version of &Boost.Thread;
using Boost's auto-linking feature, #define BOOST_THREAD_USE_DLL;
to choose the statically linked version,
#define BOOST_THREAD_USE_LIB.
If neither symbols is #defined, the default will be chosen.
Currently the default is the statically linked version.</para>
<para>On Win32 platforms using VC++:
Use the same #defines as for non-Win32 platforms
(BOOST_THREAD_USE_DLL and BOOST_THREAD_USE_LIB).
If neither is #defined, the default will be chosen.
Currently the default is the statically linked version
if the VC++ run-time library is set to
"Multi-threaded" or "Multi-threaded Debug", and
the dynamically linked version
if the VC++ run-time library is set to
"Multi-threaded DLL" or "Multi-threaded Debug DLL".</para>
<para>On Win32 platforms using compilers other than VC++:
Use the same #defines as for non-Win32 platforms
(BOOST_THREAD_USE_DLL and BOOST_THREAD_USE_LIB).
If neither is #defined, the default will be chosen.
Currently the default is the dynamically linked version
because it has not yet been possible to implement automatic
tss cleanup in the statically linked version for compilers
other than VC++, although it is hoped that this will be
possible in a future version of &Boost.Thread;.
Note for advanced users: &Boost.Thread; provides several "hook"
functions to allow users to experiment with the statically
linked version on Win32 with compilers other than VC++.
These functions are on_process_enter(), on_process_exit(),
on_thread_enter(), and on_thread_exit(), and are defined
in tls_hooks.cpp. See the comments in that file for more
information.</para>
</section>
<section id="thread.release_notes.boost_1_32_0.change_log.barrier">
<title>Barrier functionality added</title>
<para>A new class, <classname>boost::barrier</classname>, was added.</para>
</section>
<section id="thread.release_notes.boost_1_32_0.change_log.read_write_mutex">
<title>Read/write mutex functionality added</title>
<para>New classes,
<classname>boost::read_write_mutex</classname>,
<classname>boost::try_read_write_mutex</classname>, and
<classname>boost::timed_read_write_mutex</classname>
were added.
<note>Since the read/write mutex and related classes are new,
both interface and implementation are liable to change
in future releases of &Boost.Thread;.
The lock concepts and lock promotion in particular are
still under discussion and very likely to change.</note>
</para>
</section>
<section id="thread.release_notes.boost_1_32_0.change_log.thread_specific_ptr">
<title>Thread-specific pointer functionality changed</title>
<para>The <classname>boost::thread_specific_ptr</classname>
constructor now takes an optional pointer to a cleanup function that
is called to release the thread-specific data that is being pointed
to by <classname>boost::thread_specific_ptr</classname> objects.</para>
<para>Fixed: the number of available thread-specific storage "slots"
is too small on some platforms.</para>
<para>Fixed: <functionname>thread_specific_ptr::reset()</functionname>
doesn't check error returned by <functionname>tss::set()</functionname>
(the <functionname>tss::set()</functionname> function now throws
if it fails instead of returning an error code).</para>
<para>Fixed: calling
<functionname>boost::thread_specific_ptr::reset()</functionname> or
<functionname>boost::thread_specific_ptr::release()</functionname>
causes double-delete: once when
<functionname>boost::thread_specific_ptr::reset()</functionname> or
<functionname>boost::thread_specific_ptr::release()</functionname>
is called and once when
<functionname>boost::thread_specific_ptr::~thread_specific_ptr()</functionname>
is called.</para>
</section>
<section id="thread.release_notes.boost_1_32_0.change_log.mutex">
<title>Mutex implementation changed for Win32</title>
<para>On Win32, <classname>boost::mutex</classname>,
<classname>boost::try_mutex</classname>, <classname>boost::recursive_mutex</classname>,
and <classname>boost::recursive_try_mutex</classname> now use a Win32 critical section
whenever possible; otherwise they use a Win32 mutex. As before,
<classname>boost::timed_mutex</classname> and
<classname>boost::recursive_timed_mutex</classname> use a Win32 mutex.</para>
</section>
<section id="thread.release_notes.boost_1_32_0.change_log.wince">
<title>Windows CE support improved</title>
<para>Minor changes were made to make Boost.Thread work on Windows CE.</para>
</section>
</section>
</section>

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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</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,227 +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 summary="header" 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 summary="lock effects" 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>
<p><b>Postcondition:</b> locked()</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>
<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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,267 +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 summary="header" 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 summary="lock effects" 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>
<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 -->November 05, 2001<!--webbot bot="Timestamp" endspan i-checksum="39585" --></p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,305 +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 summary="header" 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 summary="lock effects" 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 summary="try_lock effects" 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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>

View File

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

270
doc/thread-ref.xml Normal file
View File

@@ -0,0 +1,270 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/thread.hpp"
last-revision="$Date$">
<namespace name="boost">
<class name="thread">
<purpose>
<para>The <classname>thread</classname> class represents threads of
execution, and provides the functionality to create and manage
threads within the &Boost.Thread; library. See
<xref linkend="thread.glossary"/> for a precise description of
<link linkend="thread.glossary.thread">thread of execution</link>,
and for definitions of threading-related terms and of thread states such as
<link linkend="thread.glossary.thread-state">blocked</link>.</para>
</purpose>
<description>
<para>A <link linkend="thread.glossary.thread">thread of execution</link>
has an initial function. For the program's initial thread, the initial
function is <code>main()</code>. For other threads, the initial
function is <code>operator()</code> of the function object passed to
the <classname>thread</classname> object's constructor.</para>
<para>A thread of execution is said to be &quot;finished&quot;
or to have &quot;finished execution&quot; 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.</para>
<para>A thread object has an associated state which is either
&quot;joinable&quot; or &quot;non-joinable&quot;.</para>
<para>Except as described below, the policy used by an implementation
of &Boost.Thread; to schedule transitions between thread states is
unspecified.</para>
<para><note>Just as the lifetime of a file may be different from the
lifetime of an <code>iostream</code> object which represents the file, the lifetime
of a thread of execution may be different from the
<classname>thread</classname> 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
<classname>thread</classname> object continues to exist until the
end of its normal lifetime. The converse is also possible; if
a <classname>thread</classname> object is destroyed without
<code>join()</code> first having been called, the thread of execution
continues until its initial function completes.</note></para>
</description>
<inherit access="private">
<type><classname>boost::noncopyable</classname></type>
<purpose>Exposition only</purpose>
</inherit>
<constructor>
<effects>Constructs a <classname>thread</classname> object
representing the current thread of execution.</effects>
<postconditions><code>*this</code> is non-joinable.</postconditions>
<notes><emphasis role="bold">Danger:</emphasis>
<code>*this</code> is valid only within the current thread.</notes>
</constructor>
<constructor specifiers="explicit">
<parameter name="threadfunc">
<paramtype>const boost::function0&lt;void&gt;&amp;</paramtype>
</parameter>
<effects>
Starts a new thread of execution and constructs a
<classname>thread</classname> 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.
</effects>
<postconditions><code>*this</code> is joinable.</postconditions>
<throws><code>boost::thread_resource_error</code> if a new thread
of execution cannot be started.</throws>
</constructor>
<destructor>
<effects>Destroys <code>*this</code>. The actual thread of
execution may continue to execute after the
<classname>thread</classname> object has been destroyed.
</effects>
<notes>If <code>*this</code> is joinable the actual thread
of execution becomes &quot;detached&quot;. 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 <classname>thread</classname> object is destroyed, call
<code>join()</code>.</notes>
</destructor>
<method-group name="comparison">
<method name="operator==" cv="const">
<type>bool</type>
<parameter name="rhs">
<type>const thread&amp;</type>
</parameter>
<requires>The thread is non-terminated or <code>*this</code>
is joinable.</requires>
<returns><code>true</code> if <code>*this</code> and
<code>rhs</code> represent the same thread of
execution.</returns>
</method>
<method name="operator!=" cv="const">
<type>bool</type>
<parameter name="rhs">
<type>const thread&amp;</type>
</parameter>
<requires>The thread is non-terminated or <code>*this</code>
is joinable.</requires>
<returns><code>!(*this==rhs)</code>.</returns>
</method>
</method-group>
<method-group name="modifier">
<method name="join">
<type>void</type>
<requires><code>*this</code> is joinable.</requires>
<effects>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.</effects>
<postcondition><code>*this</code> is non-joinable.</postcondition>
<notes>If <code>*this == thread()</code> the result is
implementation-defined. If the implementation doesn't
detect this the result will be
<link linkend="thread.glossary.deadlock">deadlock</link>.
</notes>
</method>
</method-group>
<method-group name="static">
<method name="sleep" specifiers="static">
<type>void</type>
<parameter name="xt">
<paramtype>const <classname>xtime</classname>&amp;</paramtype>
</parameter>
<effects>The current thread of execution blocks until
<code>xt</code> is reached.</effects>
</method>
<method name="yield" specifiers="static">
<type>void</type>
<effects>The current thread of execution is placed in the
<link linkend="thread.glossary.thread-state">ready</link>
state.</effects>
<notes>
<simpara>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.</simpara>
</notes>
</method>
</method-group>
</class>
<class name="thread_group">
<purpose>
The <classname>thread_group</classname> class provides a container
for easy grouping of threads to simplify several common thread
creation and management idioms.
</purpose>
<inherit access="private">
<type><classname>boost::noncopyable</classname></type>
<purpose>Exposition only</purpose>
</inherit>
<constructor>
<effects>Constructs an empty <classname>thread_group</classname>
container.</effects>
</constructor>
<destructor>
<effects>Destroys each contained thread object. Destroys <code>*this</code>.</effects>
<notes>Behavior is undefined if another thread references
<code>*this </code> during the execution of the destructor.
</notes>
</destructor>
<method-group name="modifier">
<method name="create_thread">
<type><classname>thread</classname>*</type>
<parameter name="threadfunc">
<paramtype>const boost::function0&lt;void&gt;&amp;</paramtype>
</parameter>
<effects>Creates a new <classname>thread</classname> object
that executes <code>threadfunc</code> and adds it to the
<code>thread_group</code> container object's list of managed
<classname>thread</classname> objects.</effects>
<returns>Pointer to the newly created
<classname>thread</classname> object.</returns>
</method>
<method name="add_thread">
<type>void</type>
<parameter name="thrd">
<paramtype><classname>thread</classname>*</paramtype>
</parameter>
<effects>Adds <code>thrd</code> to the
<classname>thread_group</classname> object's list of managed
<classname>thread</classname> objects. The <code>thrd</code>
object must have been allocated via <code>operator new</code> and will
be deleted when the group is destroyed.</effects>
</method>
<method name="remove_thread">
<type>void</type>
<parameter name="thrd">
<paramtype><classname>thread</classname>*</paramtype>
</parameter>
<effects>Removes <code>thread</code> from <code>*this</code>'s
list of managed <classname>thread</classname> objects.</effects>
<throws><emphasis role="bold">???</emphasis> if
<code>thrd</code> is not in <code>*this</code>'s list
of managed <classname>thread</classname> objects.</throws>
</method>
<method name="join_all">
<type>void</type>
<effects>Calls <code>join()</code> on each of the managed
<classname>thread</classname> objects.</effects>
</method>
</method-group>
</class>
</namespace>
</header>

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, 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 summary="header" 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 &quot;thread of
execution&quot;, and for definitions of threading related terms and of
thread states such as &quot;blocked&quot;.</p>
<p>A thread of execution has an initial function. For the program&#39;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 &quot;finished&quot; or
&quot;finished execution&quot; 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
&quot;joinable&quot; or &quot;non-joinable&quot;.</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 &quot;detached&quot;. 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> If <code>*this == thread()</code> the result is
implementation defined. If the implementation doesn&#39;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
&quot;ready&quot; 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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>

48
doc/thread.xml Normal file
View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<library name="Thread" dirname="thread" id="thread"
last-revision="$Date$"
xmlns:xi="http://www.w3.org/2001/XInclude">
<libraryinfo>
<author>
<firstname>William</firstname>
<othername>E.</othername>
<surname>Kempf</surname>
</author>
<copyright>
<year>2001</year>
<year>2002</year>
<year>2003</year>
<holder>William E. Kempf</holder>
</copyright>
<legalnotice>
<para>Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)</para>
</legalnotice>
<librarypurpose>Portable C++ multi-threading</librarypurpose>
<librarycategory name="category:concurrent" />
<title>Boost.Thread</title>
</libraryinfo>
<title>Boost.Thread</title>
<xi:include href="overview.xml"/>
<xi:include href="design.xml"/>
<xi:include href="concepts.xml"/>
<xi:include href="rationale.xml"/>
<xi:include href="reference.xml"/>
<xi:include href="faq.xml"/>
<xi:include href="configuration.xml"/>
<xi:include href="build.xml"/>
<xi:include href="implementation_notes.xml"/>
<xi:include href="release_notes.xml"/>
<xi:include href="glossary.xml"/>
<xi:include href="acknowledgements.xml"/>
<xi:include href="bibliography.xml"/>
</library>

View File

@@ -1,182 +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 summary="header" 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. 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&#39;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&#39;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>&#39;s list of managed
<tt>thread</tt> objects.</p>
<p><b>Throws:</b> ? if <tt>thrd</tt> is not it <code>*this</code>&#39;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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,78 +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 summary="header" 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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>

View File

@@ -1,223 +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 summary="header" 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&#39;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&#39;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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>

206
doc/tss-ref.xml Normal file
View File

@@ -0,0 +1,206 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/tss.hpp"
last-revision="$Date$">
<namespace name="boost">
<class name="thread_specific_ptr">
<purpose>
The <classname>thread_specific_ptr</classname> class defines
an interface for using thread specific storage.
</purpose>
<description>
<para>Thread specific storage is data associated with
individual threads and is often used to make operations
that rely on global data
<link linkend="thread.glossary.thread-safe">thread-safe</link>.
</para>
<para>Template <classname>thread_specific_ptr</classname>
stores a pointer to an object obtained on a thread-by-thread
basis and calls a specified cleanup handler on the contained
pointer when the thread terminates. The cleanup handlers are
called in the reverse order of construction of the
<classname>thread_specific_ptr</classname>s, and for the
initial thread are called by the destructor, providing the
same ordering guarantees as for normal declarations. Each
thread initially stores the null pointer in each
<classname>thread_specific_ptr</classname> instance.</para>
<para>The template <classname>thread_specific_ptr</classname>
is useful in the following cases:
<itemizedlist>
<listitem>An interface was originally written assuming
a single thread of control and it is being ported to a
multithreaded environment.</listitem>
<listitem>Each thread of control invokes sequences of
methods that share data that are physically unique
for each thread, but must be logically accessed
through a globally visible access point instead of
being explicitly passed.</listitem>
</itemizedlist>
</para>
</description>
<inherit access="private">
<type><classname>boost::noncopyable</classname></type>
<purpose>Exposition only</purpose>
</inherit>
<constructor>
<requires>The expression <code>delete get()</code> is well
formed.</requires>
<effects>A thread-specific data key is allocated and visible to
all threads in the process. Upon creation, the value
<code>NULL</code> will be associated with the new key in all
active threads. A cleanup method is registered with the key
that will call <code>delete</code> on the value associated
with the key for a thread when it exits. When a thread exits,
if a key has a registered cleanup method and the thread has a
non-<code>NULL</code> value associated with that key, the value
of the key is set to <code>NULL</code> and then the cleanup
method is called with the previously associated value as its
sole argument. The order in which registered cleanup methods
are called when a thread exits is undefined. If after all the
cleanup methods have been called for all non-<code>NULL</code>
values, there are still some non-<code>NULL</code> values
with associated cleanup handlers the result is undefined
behavior.</effects>
<throws><classname>boost::thread_resource_error</classname> if
the necessary resources can not be obtained.</throws>
<notes>There may be an implementation specific limit to the
number of thread specific storage objects that can be created,
and this limit may be small.</notes>
<rationale>The most common need for cleanup will be to call
<code>delete</code> on the associated value. If other forms
of cleanup are required the overloaded constructor should be
called instead.</rationale>
</constructor>
<constructor>
<parameter name="cleanup">
<paramtype>void (*cleanup)(void*)</paramtype>
</parameter>
<effects>A thread-specific data key is allocated and visible to
all threads in the process. Upon creation, the value
<code>NULL</code> will be associated with the new key in all
active threads. The <code>cleanup</code> method is registered
with the key and will be called for a thread with the value
associated with the key for that thread when it exits. When a
thread exits, if a key has a registered cleanup method and the
thread has a non-<code>NULL</code> value associated with that
key, the value of the key is set to <code>NULL</code> and then
the cleanup method is called with the previously associated
value as its sole argument. The order in which registered
cleanup methods are called when a thread exits is undefined.
If after all the cleanup methods have been called for all
non-<code>NULL</code> values, there are still some
non-<code>NULL</code> values with associated cleanup handlers
the result is undefined behavior.</effects>
<throws><classname>boost::thread_resource_error</classname> if
the necessary resources can not be obtained.</throws>
<notes>There may be an implementation specific limit to the
number of thread specific storage objects that can be created,
and this limit may be small.</notes>
<rationale>There is the occasional need to register
specialized cleanup methods, or to register no cleanup method
at all (done by passing <code>NULL</code> to this constructor.
</rationale>
</constructor>
<destructor>
<effects>Deletes the thread-specific data key allocated by the
constructor. The thread-specific data values associated with
the key need not be <code>NULL</code>. It is the responsibility
of the application to perform any cleanup actions for data
associated with the key.</effects>
<notes>Does not destroy any data that may be stored in any
thread's thread specific storage. For this reason you should
not destroy a <classname>thread_specific_ptr</classname> object
until you are certain there are no threads running that have
made use of its thread specific storage.</notes>
<rationale>Associated data is not cleaned up because registered
cleanup methods need to be run in the thread that allocated the
associated data to be guarranteed to work correctly. There's no
safe way to inject the call into another thread's execution
path, making it impossible to call the cleanup methods safely.
</rationale>
</destructor>
<method-group name="modifier functions">
<method name="release">
<type>T*</type>
<postconditions><code>*this</code> holds the null pointer
for the current thread.</postconditions>
<returns><code>this-&gt;get()</code> prior to the call.</returns>
<rationale>This method provides a mechanism for the user to
relinquish control of the data associated with the
thread-specific key.</rationale>
</method>
<method name="reset">
<type>void</type>
<parameter name="p">
<paramtype>T*</paramtype>
<default>0</default>
</parameter>
<effects>If <code>this-&gt;get() != p &amp;&amp;
this-&gt;get() != NULL</code> then call the
associated cleanup function.</effects>
<postconditions><code>*this</code> holds the pointer
<code>p</code> for the current thread.</postconditions>
</method>
</method-group>
<method-group name="observer functions">
<method name="get" cv="const">
<type>T*</type>
<returns>The object stored in thread specific storage for
the current thread for <code>*this</code>.</returns>
<notes>Each thread initially returns 0.</notes>
</method>
<method name="operator-&gt;" cv="const">
<type>T*</type>
<returns><code>this-&gt;get()</code>.</returns>
</method>
<method name="operator*()" cv="const">
<type>T&amp;</type>
<requires><code>this-&gt;get() != 0</code></requires>
<returns><code>this-&gt;get()</code>.</returns>
</method>
</method-group>
</class>
</namespace>
</header>

82
doc/xtime-ref.xml Normal file
View File

@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
<!ENTITY % thread.entities SYSTEM "entities.xml">
%thread.entities;
]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)
-->
<header name="boost/thread/xtime.hpp"
last-revision="$Date$">
<namespace name="boost">
<enum name="xtime_clock_types">
<enumvalue name="TIME_UTC" />
<purpose>
<para>Specifies the clock type to use when creating
an object of type <classname>xtime</classname>.</para>
</purpose>
<description>
<para>The only clock type supported by &Boost.Thread; is
<code>TIME_UTC</code>. The epoch for <code>TIME_UTC</code>
is 1970-01-01 00:00:00.</para>
</description>
</enum>
<struct name="xtime">
<purpose>
<simpara>An object of type <classname>xtime</classname>
defines a time that is used to perform high-resolution time operations.
This is a temporary solution that will be replaced by a more robust time
library once available in Boost.</simpara>
</purpose>
<description>
<simpara>The <classname>xtime</classname> type is used to represent a point on
some time scale or a duration in time. This type may be proposed for the C standard by
Markus Kuhn. &Boost.Thread; provides only a very minimal implementation of this
proposal; it is expected that a full implementation (or some other time
library) will be provided in Boost as a separate library, at which time &Boost.Thread;
will deprecate its own implementation.</simpara>
<simpara><emphasis role="bold">Note</emphasis> that 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.</simpara>
</description>
<free-function-group name="creation">
<function name="xtime_get">
<type>int</type>
<parameter name="xtp">
<paramtype><classname>xtime</classname>*</paramtype>
</parameter>
<parameter name="clock_type">
<paramtype>int</paramtype>
</parameter>
<postconditions>
<simpara><code>xtp</code> represents the current point in
time as a duration since the epoch specified by
<code>clock_type</code>.</simpara>
</postconditions>
<returns>
<simpara><code>clock_type</code> if successful, otherwise 0.</simpara>
</returns>
</function>
</free-function-group>
<data-member name="sec">
<type><emphasis>platform-specific-type</emphasis></type>
</data-member>
</struct>
</namespace>
</header>

View File

@@ -1,147 +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 summary="header" 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&#39;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></p>
<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>
<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 -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001 all rights reserved.</i></p>
</body>
</html>

2
example/.cvsignore Normal file
View File

@@ -0,0 +1,2 @@
bin
*.pdb

View File

@@ -1,66 +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. monitor, an example program.
# 2. starvephil, an example program.
# 3. tennis, an example program.
# declare the location of this subproject relative to the root
subproject libs/thread/example ;
# Do some OS-specific setup
if $(NT)
{
BOOST_THREADMON_LIB = <lib>../build/libboost_threadmon ;
}
else
{
BOOST_THREADMON_LIB = ;
}
#######################
#
# Declare the Boost.Threads monitor example program.
#
exe monitor : monitor/monitor.cpp
<lib>../build/libboost_thread
$(BOOST_THREADMON_LIB)
# requirements
: <include>$(BOOST_ROOT)
<threading>multi
: debug release ;
#######################
#
# Declare the Boost.Threads starvephil example program.
#
exe starvephil : starvephil/starvephil.cpp
<lib>../build/libboost_thread
$(BOOST_THREADMON_LIB)
# requirements
: <include>$(BOOST_ROOT)
<threading>multi
: debug release ;
#######################
#
# Declare the Boost.Threads tennis example program.
#
exe tennis : tennis/tennis.cpp
<lib>../build/libboost_thread
$(BOOST_THREADMON_LIB)
# requirements
: <include>$(BOOST_ROOT)
<threading>multi
: debug release ;

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 ;

74
example/condition.cpp Normal file
View File

@@ -0,0 +1,74 @@
// 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);
void sender() {
int n = 0;
while (n < 100) {
buf.send(n);
std::cout << "sent: " << n << std::endl;
++n;
}
buf.send(-1);
}
void receiver() {
int n;
do {
n = buf.receive();
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,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 <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/thread.hpp>
@@ -5,8 +11,8 @@
#include <iostream>
#if defined(BOOST_HAS_WINTHREADS)
# include <windows.h>
# include <process.h>
# include <windows.h>
# include <process.h>
#endif
enum game_state
@@ -49,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);
}
@@ -60,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);
@@ -74,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
}

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

@@ -0,0 +1,19 @@
// 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)
#if !defined(BOOST_THREAD_WEK01082003_HPP)
#define BOOST_THREAD_WEK01082003_HPP
#include <boost/thread/thread.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/once.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/tss.hpp>
#include <boost/thread/xtime.hpp>
#endif

View File

@@ -0,0 +1,44 @@
// Copyright (C) 2002-2003
// David Moore, 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_BARRIER_JDM030602_HPP
#define BOOST_BARRIER_JDM030602_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
namespace boost {
class BOOST_THREAD_DECL barrier
{
public:
barrier(unsigned int count);
~barrier();
bool wait();
private:
mutex m_mutex;
// disable warnings about non dll import
// see: http://www.boost.org/more/separate_compilation.html#dlls
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4251 4231 4660 4275)
#endif
condition m_cond;
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
unsigned int m_threshold;
unsigned int m_count;
unsigned int m_generation;
};
} // namespace boost
#endif

View File

@@ -1,21 +1,13 @@
// Copyright (C) 2001
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_CONDITION_WEK070601_HPP
#define BOOST_CONDITION_WEK070601_HPP
#include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS
# error Thread support is unavailable!
#endif
#include <boost/thread/detail/config.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/utility.hpp>
@@ -23,20 +15,74 @@
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
#elif defined(BOOST_HAS_MPTASKS)
# include "scoped_critical_region.hpp"
#endif
namespace boost {
struct xtime;
// disable warnings about non dll import
// see: http://www.boost.org/more/separate_compilation.html#dlls
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4251 4231 4660 4275)
#endif
namespace detail {
class BOOST_THREAD_DECL condition_impl : private noncopyable
{
friend class condition;
public:
condition_impl();
~condition_impl();
void notify_one();
void notify_all();
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
void enter_wait();
void do_wait();
bool do_timed_wait(const xtime& xt);
#elif defined(BOOST_HAS_PTHREADS)
void do_wait(pthread_mutex_t* pmutex);
bool do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex);
#endif
#if defined(BOOST_HAS_WINTHREADS)
void* m_gate;
void* m_queue;
void* m_mutex;
unsigned m_gone; // # threads that timed out and never made it to m_queue
unsigned long m_blocked; // # threads blocked on the condition
unsigned m_waiting; // # threads no longer waiting for the condition but
// still waiting to be removed from m_queue
#elif defined(BOOST_HAS_PTHREADS)
pthread_cond_t m_condition;
#elif defined(BOOST_HAS_MPTASKS)
MPSemaphoreID m_gate;
MPSemaphoreID m_queue;
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
unsigned m_gone; // # threads that timed out and never made it to m_queue
unsigned long m_blocked; // # threads blocked on the condition
unsigned m_waiting; // # threads no longer waiting for the condition but
// still waiting to be removed from m_queue
#endif
};
} // namespace detail
class condition : private noncopyable
{
public:
condition();
~condition();
condition() { }
~condition() { }
void notify_one();
void notify_all();
void notify_one() { m_impl.notify_one(); }
void notify_all() { m_impl.notify_all(); }
template <typename L>
void wait(L& lock)
@@ -82,78 +128,74 @@ public:
}
private:
detail::condition_impl m_impl;
template <typename M>
void do_wait(M& mutex)
{
#if defined(BOOST_HAS_WINTHREADS)
enter_wait();
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
m_impl.enter_wait();
#endif
typedef typename detail::thread::lock_ops<M> lock_ops;
lock_ops::lock_state state;
typedef detail::thread::lock_ops<M>
#if defined(__HP_aCC) && __HP_aCC <= 33900 && !defined(BOOST_STRICT_CONFIG)
# define lock_ops lock_ops_ // HP confuses lock_ops witht the template
#endif
lock_ops;
typename lock_ops::lock_state state;
lock_ops::unlock(mutex, state);
#if defined(BOOST_HAS_PTHREADS)
do_wait(state.pmutex);
#elif defined(BOOST_HAS_WINTHREADS)
do_wait();
m_impl.do_wait(state.pmutex);
#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
m_impl.do_wait();
#endif
lock_ops::lock(mutex, state);
#undef lock_ops
}
template <typename M>
bool do_timed_wait(M& mutex, const xtime& xt)
{
#if defined(BOOST_HAS_WINTHREADS)
enter_wait();
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
m_impl.enter_wait();
#endif
typedef typename detail::thread::lock_ops<M> lock_ops;
lock_ops::lock_state state;
typedef detail::thread::lock_ops<M>
#if defined(__HP_aCC) && __HP_aCC <= 33900 && !defined(BOOST_STRICT_CONFIG)
# define lock_ops lock_ops_ // HP confuses lock_ops witht the template
#endif
lock_ops;
typename lock_ops::lock_state state;
lock_ops::unlock(mutex, state);
bool ret = false;
#if defined(BOOST_HAS_PTHREADS)
ret = do_timed_wait(xt, state.pmutex);
#elif defined(BOOST_HAS_WINTHREADS)
ret = do_timed_wait(xt);
ret = m_impl.do_timed_wait(xt, state.pmutex);
#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
ret = m_impl.do_timed_wait(xt);
#endif
lock_ops::lock(mutex, state);
#undef lock_ops
return ret;
}
#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)
void* m_gate;
void* m_queue;
void* 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
};
#ifdef BOOST_MSVC
# pragma warning(pop)
#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.
// 23 May 01 WEKEMPF Removed "duration" timed_waits, as they are too
// difficult to use with spurious wakeups.
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
#endif // BOOST_CONDITION_WEK070601_HPP

View File

@@ -1,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,95 @@
// 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
// insist on threading support being available:
#include <boost/config/requires_threads.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_HAS_WINTHREADS)
# if defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)
//For compilers supporting auto-tss cleanup
//with Boost.Threads lib, use Boost.Threads lib
# define BOOST_THREAD_USE_LIB
# else
//For compilers not yet supporting auto-tss cleanup
//with Boost.Threads lib, use Boost.Threads dll
# define BOOST_THREAD_USE_DLL
# endif
# else
# define BOOST_THREAD_USE_LIB
# endif
#endif
#if defined(BOOST_HAS_DECLSPEC)
# if defined(BOOST_THREAD_BUILD_DLL) //Build dll
# define BOOST_THREAD_DECL __declspec(dllexport)
# elif defined(BOOST_THREAD_USE_DLL) //Use dll
# define BOOST_THREAD_DECL __declspec(dllimport)
# else
# define BOOST_THREAD_DECL
# endif
#else
# define BOOST_THREAD_DECL
#endif // BOOST_HAS_DECLSPEC
//
// Automatically link to the correct build variant where possible.
//
#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_THREAD_NO_LIB) && !defined(BOOST_THREAD_BUILD_DLL) && !defined(BOOST_THREAD_BUILD_LIB)
//
// Tell the autolink to link dynamically, this will get undef'ed by auto_link.hpp
// once it's done with it:
//
#if defined(BOOST_THREAD_USE_DLL)
# define BOOST_DYN_LINK
#endif
//
// Set the name of our library, this will get undef'ed by auto_link.hpp
// once it's done with it:
//
#if defined(BOOST_THREAD_LIB_NAME)
# define BOOST_LIB_NAME BOOST_THREAD_LIB_NAME
#else
# define BOOST_LIB_NAME boost_thread
#endif
//
// If we're importing code from a dll, then tell auto_link.hpp about it:
//
// And include the header that does the work:
//
#include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
#endif // BOOST_THREAD_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,17 +1,14 @@
// Copyright (C) 2001
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_XLOCK_WEK070601_HPP
#define BOOST_XLOCK_WEK070601_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/utility.hpp>
#include <boost/thread/exceptions.hpp>
@@ -20,188 +17,193 @@ namespace boost {
class condition;
struct xtime;
namespace detail { namespace thread {
namespace detail { namespace thread {
template <typename Mutex>
class lock_ops : private noncopyable
template <typename Mutex>
class lock_ops : private noncopyable
{
private:
lock_ops() { }
public:
typedef typename Mutex::cv_state lock_state;
static void lock(Mutex& m)
{
private:
lock_ops() { }
public:
typedef typename Mutex::cv_state lock_state;
static void lock(Mutex& m)
{
m.do_lock();
}
static bool trylock(Mutex& m)
{
return m.do_trylock();
}
static bool timedlock(Mutex& m, const xtime& xt)
{
return m.do_timedlock(xt);
}
static void unlock(Mutex& m)
{
m.do_unlock();
}
static void lock(Mutex& m, lock_state& state)
{
m.do_lock(state);
}
static void unlock(Mutex& m, lock_state& state)
{
m.do_unlock(state);
}
};
template <typename Mutex>
class scoped_lock : private noncopyable
m.do_lock();
}
static bool trylock(Mutex& m)
{
public:
typedef Mutex mutex_type;
explicit scoped_lock(Mutex& mx, bool initially_locked=true)
: m_mutex(mx), m_locked(false)
{
if (initially_locked) lock();
}
~scoped_lock()
{
if (m_locked) unlock();
}
void lock()
{
if (m_locked) throw lock_error();
lock_ops<Mutex>::lock(m_mutex);
m_locked = true;
}
void unlock()
{
if (!m_locked) throw lock_error();
lock_ops<Mutex>::unlock(m_mutex);
m_locked = false;
}
bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; }
private:
friend class boost::condition;
Mutex& m_mutex;
bool m_locked;
};
template <typename TryMutex>
class scoped_try_lock : private noncopyable
return m.do_trylock();
}
static bool timedlock(Mutex& m, const xtime& xt)
{
public:
typedef TryMutex mutex_type;
explicit scoped_try_lock(TryMutex& mx)
: m_mutex(mx), m_locked(false)
{
try_lock();
}
scoped_try_lock(TryMutex& mx, bool initially_locked)
: m_mutex(mx), m_locked(false)
{
if (initially_locked) lock();
}
~scoped_try_lock()
{
if (m_locked) unlock();
}
void lock()
{
if (m_locked) throw lock_error();
lock_ops<TryMutex>::lock(m_mutex);
m_locked = true;
}
bool try_lock()
{
if (m_locked) throw lock_error();
return (m_locked = lock_ops<TryMutex>::trylock(m_mutex));
}
void unlock()
{
if (!m_locked) throw lock_error();
lock_ops<TryMutex>::unlock(m_mutex);
m_locked = false;
}
bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; }
private:
friend class boost::condition;
TryMutex& m_mutex;
bool m_locked;
};
template <typename TimedMutex>
class scoped_timed_lock : private noncopyable
return m.do_timedlock(xt);
}
static void unlock(Mutex& m)
{
public:
typedef TimedMutex mutex_type;
m.do_unlock();
}
static void lock(Mutex& m, lock_state& state)
{
m.do_lock(state);
}
static void unlock(Mutex& m, lock_state& state)
{
m.do_unlock(state);
}
};
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();
}
template <typename Mutex>
class scoped_lock : private noncopyable
{
public:
typedef Mutex mutex_type;
void lock()
{
if (m_locked) throw lock_error();
lock_ops<TimedMutex>::lock(m_mutex);
m_locked = true;
}
bool timed_lock(const xtime& xt)
{
if (m_locked) throw lock_error();
return (m_locked = lock_ops<TimedMutex>::timedlock(m_mutex, xt));
}
void unlock()
{
if (!m_locked) throw lock_error();
lock_ops<TimedMutex>::unlock(m_mutex);
m_locked = false;
}
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();
}
bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; }
void lock()
{
if (m_locked) throw lock_error();
lock_ops<Mutex>::lock(m_mutex);
m_locked = true;
}
void unlock()
{
if (!m_locked) throw lock_error();
lock_ops<Mutex>::unlock(m_mutex);
m_locked = false;
}
private:
friend class boost::condition;
bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; }
TimedMutex& m_mutex;
bool m_locked;
};
private:
friend class boost::condition;
} // namespace thread
} // namespace detail
Mutex& m_mutex;
bool m_locked;
};
template <typename TryMutex>
class scoped_try_lock : private noncopyable
{
public:
typedef TryMutex mutex_type;
explicit scoped_try_lock(TryMutex& mx)
: m_mutex(mx), m_locked(false)
{
try_lock();
}
scoped_try_lock(TryMutex& mx, bool initially_locked)
: m_mutex(mx), m_locked(false)
{
if (initially_locked) lock();
}
~scoped_try_lock()
{
if (m_locked) unlock();
}
void lock()
{
if (m_locked) throw lock_error();
lock_ops<TryMutex>::lock(m_mutex);
m_locked = true;
}
bool try_lock()
{
if (m_locked) throw lock_error();
return (m_locked = lock_ops<TryMutex>::trylock(m_mutex));
}
void unlock()
{
if (!m_locked) throw lock_error();
lock_ops<TryMutex>::unlock(m_mutex);
m_locked = false;
}
bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; }
private:
friend class boost::condition;
TryMutex& m_mutex;
bool m_locked;
};
template <typename TimedMutex>
class scoped_timed_lock : private noncopyable
{
public:
typedef TimedMutex mutex_type;
scoped_timed_lock(TimedMutex& mx, const xtime& xt)
: m_mutex(mx), m_locked(false)
{
timed_lock(xt);
}
scoped_timed_lock(TimedMutex& mx, bool initially_locked)
: m_mutex(mx), m_locked(false)
{
if (initially_locked) lock();
}
~scoped_timed_lock()
{
if (m_locked) unlock();
}
void lock()
{
if (m_locked) throw lock_error();
lock_ops<TimedMutex>::lock(m_mutex);
m_locked = true;
}
bool try_lock()
{
if (m_locked) throw lock_error();
return (m_locked = lock_ops<TimedMutex>::trylock(m_mutex));
}
bool timed_lock(const xtime& xt)
{
if (m_locked) throw lock_error();
return (m_locked = lock_ops<TimedMutex>::timedlock(m_mutex, xt));
}
void unlock()
{
if (!m_locked) throw lock_error();
lock_ops<TimedMutex>::unlock(m_mutex);
m_locked = false;
}
bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; }
private:
friend class boost::condition;
TimedMutex& m_mutex;
bool m_locked;
};
} // namespace thread
} // namespace detail
} // namespace boost
#endif // BOOST_XLOCK_WEK070601_HPP
// Change Log:
// 8 Feb 01 WEKEMPF Initial version.
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
// 30 Jul 01 WEKEMPF Moved lock types into boost::detail::thread. Renamed some types.
// Added locked() methods.
#endif // BOOST_XLOCK_WEK070601_HPP
// 30 Jul 01 WEKEMPF Moved lock types into boost::detail::thread. Renamed
// some types. Added locked() methods.

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@@ -1,39 +1,94 @@
// Copyright (C) 2001
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_THREAD_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 {
class lock_error : public std::runtime_error
class BOOST_THREAD_DECL thread_exception : public std::exception
{
protected:
thread_exception();
thread_exception(int sys_err_code);
public:
~thread_exception() throw();
int native_error() const;
private:
int m_sys_err;
};
class BOOST_THREAD_DECL lock_error : public thread_exception
{
public:
lock_error();
lock_error(int sys_err_code);
~lock_error() throw();
virtual const char* what() const throw();
};
class thread_resource_error : public std::runtime_error
class BOOST_THREAD_DECL thread_resource_error : public thread_exception
{
public:
thread_resource_error();
thread_resource_error(int sys_err_code);
~thread_resource_error() throw();
virtual const char* what() const throw();
};
class BOOST_THREAD_DECL unsupported_thread_option : public thread_exception
{
public:
unsupported_thread_option();
unsupported_thread_option(int sys_err_code);
~unsupported_thread_option() throw();
virtual const char* what() const throw();
};
class BOOST_THREAD_DECL invalid_thread_argument : public thread_exception
{
public:
invalid_thread_argument();
invalid_thread_argument(int sys_err_code);
~invalid_thread_argument() throw();
virtual const char* what() const throw();
};
class BOOST_THREAD_DECL thread_permission_error : public thread_exception
{
public:
thread_permission_error();
thread_permission_error(int sys_err_code);
~thread_permission_error() throw();
virtual const char* what() const throw();
};
} // namespace boost
#endif // BOOST_THREAD_CONFIG_PDM070801_H
// Change log:
// 3 Jan 03 WEKEMPF Modified for DLL implementation.

View File

@@ -1,21 +1,13 @@
// Copyright (C) 2001
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MUTEX_WEK070601_HPP
#define BOOST_MUTEX_WEK070601_HPP
#include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS
# error Thread support is unavailable!
#endif
#include <boost/thread/detail/config.hpp>
#include <boost/utility.hpp>
#include <boost/thread/detail/lock.hpp>
@@ -24,11 +16,22 @@
# include <pthread.h>
#endif
#if defined(BOOST_HAS_MPTASKS)
# include "scoped_critical_region.hpp"
#endif
namespace boost {
struct xtime;
// disable warnings about non dll import
// see: http://www.boost.org/more/separate_compilation.html#dlls
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4251 4231 4660 4275)
#endif
class mutex : private noncopyable
class BOOST_THREAD_DECL mutex
: private noncopyable
{
public:
friend class detail::thread::lock_ops<mutex>;
@@ -46,6 +49,10 @@ private:
{
pthread_mutex_t* pmutex;
};
#elif defined(BOOST_HAS_MPTASKS)
struct cv_state
{
};
#endif
void do_lock();
void do_unlock();
@@ -54,12 +61,17 @@ private:
#if defined(BOOST_HAS_WINTHREADS)
void* m_mutex;
bool m_critical_section;
#elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex;
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
#endif
};
class try_mutex : private noncopyable
class BOOST_THREAD_DECL try_mutex
: private noncopyable
{
public:
friend class detail::thread::lock_ops<try_mutex>;
@@ -78,6 +90,10 @@ private:
{
pthread_mutex_t* pmutex;
};
#elif defined(BOOST_HAS_MPTASKS)
struct cv_state
{
};
#endif
void do_lock();
bool do_trylock();
@@ -87,12 +103,17 @@ private:
#if defined(BOOST_HAS_WINTHREADS)
void* m_mutex;
bool m_critical_section;
#elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex;
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
#endif
};
class timed_mutex : private noncopyable
class BOOST_THREAD_DECL timed_mutex
: private noncopyable
{
public:
friend class detail::thread::lock_ops<timed_mutex>;
@@ -112,6 +133,10 @@ private:
{
pthread_mutex_t* pmutex;
};
#elif defined(BOOST_HAS_MPTASKS)
struct cv_state
{
};
#endif
void do_lock();
bool do_trylock();
@@ -126,14 +151,20 @@ private:
pthread_mutex_t m_mutex;
pthread_cond_t m_condition;
bool m_locked;
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
#endif
};
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
} // namespace boost
// Change Log:
// 8 Feb 01 WEKEMPF Initial version.
// 22 May 01 WEKEMPF Modified to use xtime for time outs. Factored out
// to three classes, mutex, try_mutex and timed_mutex.
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
#endif // BOOST_MUTEX_WEK070601_HPP

View File

@@ -1,21 +1,13 @@
// Copyright (C) 2001
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_ONCE_WEK080101_HPP
#define BOOST_ONCE_WEK080101_HPP
#include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS
# error Thread support is unavailable!
#endif
#include <boost/thread/detail/config.hpp>
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
@@ -28,14 +20,14 @@ namespace boost {
typedef pthread_once_t once_flag;
#define BOOST_ONCE_INIT PTHREAD_ONCE_INIT
#elif defined(BOOST_HAS_WINTHREADS)
#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
typedef bool once_flag;
#define BOOST_ONCE_INIT false
typedef long once_flag;
#define BOOST_ONCE_INIT 0
#endif
void call_once(void (*func)(), once_flag& flag);
void BOOST_THREAD_DECL call_once(void (*func)(), once_flag& flag);
} // namespace boost

View File

@@ -1,21 +1,13 @@
// Copyright (C) 2001
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_RECURSIVE_MUTEX_WEK070601_HPP
#define BOOST_RECURSIVE_MUTEX_WEK070601_HPP
#include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS
# error Thread support is unavailable!
#endif
#include <boost/thread/detail/config.hpp>
#include <boost/utility.hpp>
#include <boost/thread/detail/lock.hpp>
@@ -24,11 +16,21 @@
# include <pthread.h>
#endif
#if defined(BOOST_HAS_MPTASKS)
# include "scoped_critical_region.hpp"
#endif
namespace boost {
struct xtime;
class recursive_mutex : private noncopyable
// disable warnings about non dll import
// see: http://www.boost.org/more/separate_compilation.html#dlls
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4251 4231 4660 4275)
#endif
class BOOST_THREAD_DECL recursive_mutex
: private noncopyable
{
public:
friend class detail::thread::lock_ops<recursive_mutex>;
@@ -39,7 +41,7 @@ public:
~recursive_mutex();
private:
#if defined(BOOST_HAS_WINTHREADS)
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
typedef std::size_t cv_state;
#elif defined(BOOST_HAS_PTHREADS)
struct cv_state
@@ -55,6 +57,7 @@ private:
#if defined(BOOST_HAS_WINTHREADS)
void* m_mutex;
bool m_critical_section;
unsigned long m_count;
#elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex;
@@ -64,22 +67,28 @@ private:
pthread_t m_thread_id;
bool m_valid_id;
# endif
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
std::size_t m_count;
#endif
};
class recursive_try_mutex : private noncopyable
class BOOST_THREAD_DECL recursive_try_mutex
: private noncopyable
{
public:
friend class detail::thread::lock_ops<recursive_try_mutex>;
typedef detail::thread::scoped_lock<recursive_try_mutex> scoped_lock;
typedef detail::thread::scoped_try_lock<recursive_try_mutex> scoped_try_lock;
typedef detail::thread::scoped_try_lock<
recursive_try_mutex> scoped_try_lock;
recursive_try_mutex();
~recursive_try_mutex();
private:
#if defined(BOOST_HAS_WINTHREADS)
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
typedef std::size_t cv_state;
#elif defined(BOOST_HAS_PTHREADS)
struct cv_state
@@ -96,6 +105,7 @@ private:
#if defined(BOOST_HAS_WINTHREADS)
void* m_mutex;
bool m_critical_section;
unsigned long m_count;
#elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex;
@@ -105,23 +115,30 @@ private:
pthread_t m_thread_id;
bool m_valid_id;
# endif
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
std::size_t m_count;
#endif
};
class recursive_timed_mutex : private noncopyable
class BOOST_THREAD_DECL recursive_timed_mutex
: private noncopyable
{
public:
friend class detail::thread::lock_ops<recursive_timed_mutex>;
typedef detail::thread::scoped_lock<recursive_timed_mutex> scoped_lock;
typedef detail::thread::scoped_try_lock<recursive_timed_mutex> scoped_try_lock;
typedef detail::thread::scoped_timed_lock<recursive_timed_mutex> scoped_timed_lock;
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)
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
typedef std::size_t cv_state;
#elif defined(BOOST_HAS_PTHREADS)
struct cv_state
@@ -146,15 +163,22 @@ private:
pthread_t m_thread_id;
bool m_valid_id;
unsigned m_count;
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
std::size_t m_count;
#endif
};
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
} // namespace boost
#endif // BOOST_RECURSIVE_MUTEX_WEK070601_HPP
// Change Log:
// 8 Feb 01 WEKEMPF Initial version.
// 1 Jun 01 WEKEMPF Modified to use xtime for time outs. Factored out
// to three classes, mutex, try_mutex and timed_mutex.
// 11 Jun 01 WEKEMPF Modified to use PTHREAD_MUTEX_RECURSIVE if available.
#endif // BOOST_RECURSIVE_MUTEX_WEK070601_HPP
// 3 Jan 03 WEKEMPF Modified for DLL implementation.

View File

@@ -1,21 +1,13 @@
// Copyright (C) 2001
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_THREAD_WEK070601_HPP
#define BOOST_THREAD_WEK070601_HPP
#include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS
# error Thread support is unavailable!
#endif
#include <boost/thread/detail/config.hpp>
#include <boost/utility.hpp>
#include <boost/function.hpp>
@@ -26,13 +18,20 @@
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
# include <boost/thread/condition.hpp>
#elif defined(BOOST_HAS_MPTASKS)
# include <Multiprocessing.h>
#endif
namespace boost {
struct xtime;
class thread : private noncopyable
// disable warnings about non dll import
// see: http://www.boost.org/more/separate_compilation.html#dlls
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable: 4251 4231 4660 4275)
#endif
class BOOST_THREAD_DECL thread : private noncopyable
{
public:
thread();
@@ -54,11 +53,14 @@ private:
#elif defined(BOOST_HAS_PTHREADS)
private:
pthread_t m_thread;
#elif defined(BOOST_HAS_MPTASKS)
MPQueueID m_pJoinQueueID;
MPTaskID m_pTaskID;
#endif
bool m_joinable;
};
class thread_group : private noncopyable
class BOOST_THREAD_DECL thread_group : private noncopyable
{
public:
thread_group();
@@ -68,12 +70,15 @@ public:
void add_thread(thread* thrd);
void remove_thread(thread* thrd);
void join_all();
int size();
private:
std::list<thread*> m_threads;
mutex m_mutex;
};
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
} // namespace boost
// Change Log:

View File

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

View File

@@ -1,50 +1,54 @@
// Copyright (C) 2001
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_XTIME_WEK070601_HPP
#define BOOST_XTIME_WEK070601_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/cstdint.hpp>
#include <boost/config.hpp>
namespace boost {
enum
enum xtime_clock_types
{
TIME_UTC=1,
TIME_TAI,
TIME_MONOTONIC,
TIME_PROCESS,
TIME_THREAD,
TIME_LOCAL,
TIME_SYNC,
TIME_RESOLUTION
TIME_UTC=1
// TIME_TAI,
// TIME_MONOTONIC,
// TIME_PROCESS,
// TIME_THREAD,
// TIME_LOCAL,
// TIME_SYNC,
// TIME_RESOLUTION
};
struct xtime
{
#if defined(BOOST_NO_INT64_T)
int_fast32_t sec;
typedef int_fast32_t xtime_sec_t; //INT_FAST32_MIN <= sec <= INT_FAST32_MAX
#else
int_fast64_t sec;
typedef int_fast64_t xtime_sec_t; //INT_FAST64_MIN <= sec <= INT_FAST64_MAX
#endif
int_fast32_t nsec;
typedef int_fast32_t xtime_nsec_t; //0 <= xtime.nsec < NANOSECONDS_PER_SECOND
xtime_sec_t sec;
xtime_nsec_t nsec;
};
int xtime_get(struct xtime* xtp, int clock_type);
int BOOST_THREAD_DECL xtime_get(struct xtime* xtp, int clock_type);
inline int xtime_cmp(const xtime& xt1, const xtime& xt2)
{
if (xt1.sec == xt2.sec)
return (int)(xt1.nsec - xt2.nsec);
else
return (xt1.sec > xt2.sec) ? 1 : -1;
}
} // namespace boost
// Change Log:
// 8 Feb 01 WEKEMPF Initial version.
#endif // BOOST_XTIME_WEK070601_HPP
#endif //BOOST_XTIME_WEK070601_HPP

13
index.html Normal file
View File

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

42
src/barrier.cpp Normal file
View File

@@ -0,0 +1,42 @@
// Copyright (C) 2002-2003
// David Moore, 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/detail/config.hpp>
#include <boost/thread/barrier.hpp>
#include <string> // see http://article.gmane.org/gmane.comp.lib.boost.devel/106981
namespace boost {
barrier::barrier(unsigned int count)
: m_threshold(count), m_count(count), m_generation(0)
{
if (count == 0)
throw std::invalid_argument("count cannot be zero.");
}
barrier::~barrier()
{
}
bool barrier::wait()
{
boost::mutex::scoped_lock lock(m_mutex);
unsigned int gen = m_generation;
if (--m_count == 0)
{
m_generation++;
m_count = m_threshold;
m_cond.notify_all();
return true;
}
while (gen == m_generation)
m_cond.wait(lock);
return false;
}
} // namespace boost

View File

@@ -1,13 +1,10 @@
// Copyright (C) 2001
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/config.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/xtime.hpp>
@@ -18,20 +15,35 @@
#include "timeconv.inl"
#if defined(BOOST_HAS_WINTHREADS)
# define NOMINMAX
# ifndef NOMINMAX
# define NOMINMAX
# endif
# include <windows.h>
#elif defined(BOOST_HAS_PTHREADS)
# include <errno.h>
#elif defined(BOOST_HAS_MPTASKS)
# include <MacErrors.h>
# include "mac/init.hpp"
# include "mac/safe.hpp"
#endif
// The following include can be removed after the bug on QNX
// has been tracked down. I need this only for debugging
//#if !defined(NDEBUG) && defined(BOOST_HAS_PTHREADS)
#include <iostream>
//#endif
namespace boost {
namespace detail {
#if defined(BOOST_HAS_WINTHREADS)
condition::condition()
condition_impl::condition_impl()
: m_gone(0), m_blocked(0), m_waiting(0)
{
m_gate = reinterpret_cast<void*>(CreateSemaphore(0, 1, 1, 0));
m_queue = reinterpret_cast<void*>(CreateSemaphore(0, 0, std::numeric_limits<long>::max(), 0));
m_queue = reinterpret_cast<void*>(
CreateSemaphore(0, 0, (std::numeric_limits<long>::max)(), 0));
m_mutex = reinterpret_cast<void*>(CreateMutex(0, 0, 0));
if (!m_gate || !m_queue || !m_mutex)
@@ -57,7 +69,7 @@ condition::condition()
}
}
condition::~condition()
condition_impl::~condition_impl()
{
int res = 0;
res = CloseHandle(reinterpret_cast<HANDLE>(m_gate));
@@ -68,7 +80,7 @@ condition::~condition()
assert(res);
}
void condition::notify_one()
void condition_impl::notify_one()
{
unsigned signals = 0;
@@ -87,6 +99,7 @@ void condition::notify_one()
++m_waiting;
--m_blocked;
signals = 1;
}
else
{
@@ -107,19 +120,19 @@ void condition::notify_one()
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
assert(res);
}
}
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
if (signals)
{
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0);
assert(res);
if (signals)
{
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0);
assert(res);
}
}
}
void condition::notify_all()
void condition_impl::notify_all()
{
unsigned signals = 0;
@@ -158,19 +171,19 @@ void condition::notify_all()
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
assert(res);
}
}
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
if (signals)
{
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0);
assert(res);
if (signals)
{
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0);
assert(res);
}
}
}
void condition::enter_wait()
void condition_impl::enter_wait()
{
int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
@@ -180,7 +193,7 @@ void condition::enter_wait()
assert(res);
}
void condition::do_wait()
void condition_impl::do_wait()
{
int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), INFINITE);
@@ -199,7 +212,8 @@ void condition::do_wait()
{
if (m_blocked != 0)
{
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0); // open m_gate
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1,
0); // open m_gate
assert(res);
was_waiting = 0;
}
@@ -207,7 +221,7 @@ void condition::do_wait()
m_gone = 0;
}
}
else if (++m_gone == (std::numeric_limits<unsigned>::max() / 2))
else if (++m_gone == ((std::numeric_limits<unsigned>::max)() / 2))
{
// timeout occured, normalize the m_gone count
// this may occur if many calls to wait with a timeout are made and
@@ -227,7 +241,8 @@ void condition::do_wait()
for (/**/ ; was_gone; --was_gone)
{
// better now than spurious later
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), INFINITE);
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue),
INFINITE);
assert(res == WAIT_OBJECT_0);
}
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
@@ -235,16 +250,31 @@ void condition::do_wait()
}
}
bool condition::do_timed_wait(const xtime& xt)
bool condition_impl::do_timed_wait(const xtime& xt)
{
unsigned milliseconds;
to_duration(xt, milliseconds);
bool ret = false;
unsigned int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), milliseconds);
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
bool ret = (res == WAIT_OBJECT_0);
for (;;)
{
int milliseconds;
to_duration(xt, milliseconds);
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue),
milliseconds);
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
ret = (res == WAIT_OBJECT_0);
if (res == WAIT_TIMEOUT)
{
xtime cur;
xtime_get(&cur, TIME_UTC);
if (xtime_cmp(xt, cur) > 0)
continue;
}
break;
}
unsigned was_waiting=0;
unsigned was_gone=0;
@@ -266,7 +296,8 @@ bool condition::do_timed_wait(const xtime& xt)
{
if (m_blocked != 0)
{
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0); // open m_gate
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1,
0); // open m_gate
assert(res);
was_waiting = 0;
}
@@ -274,7 +305,7 @@ bool condition::do_timed_wait(const xtime& xt)
m_gone = 0;
}
}
else if (++m_gone == (std::numeric_limits<unsigned>::max() / 2))
else if (++m_gone == ((std::numeric_limits<unsigned>::max)() / 2))
{
// timeout occured, normalize the m_gone count
// this may occur if many calls to wait with a timeout are made and
@@ -294,7 +325,8 @@ bool condition::do_timed_wait(const xtime& xt)
for (/**/ ; was_gone; --was_gone)
{
// better now than spurious later
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), INFINITE);
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue),
INFINITE);
assert(res == WAIT_OBJECT_0);
}
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
@@ -304,7 +336,7 @@ bool condition::do_timed_wait(const xtime& xt)
return ret;
}
#elif defined(BOOST_HAS_PTHREADS)
condition::condition()
condition_impl::condition_impl()
{
int res = 0;
res = pthread_cond_init(&m_condition, 0);
@@ -312,49 +344,349 @@ condition::condition()
throw thread_resource_error();
}
condition::~condition()
condition_impl::~condition_impl()
{
int res = 0;
res = pthread_cond_destroy(&m_condition);
assert(res == 0);
}
void condition::notify_one()
void condition_impl::notify_one()
{
int res = 0;
res = pthread_cond_signal(&m_condition);
assert(res == 0);
}
void condition::notify_all()
void condition_impl::notify_all()
{
int res = 0;
res = pthread_cond_broadcast(&m_condition);
assert(res == 0);
}
void condition::do_wait(pthread_mutex_t* pmutex)
void condition_impl::do_wait(pthread_mutex_t* pmutex)
{
int res = 0;
res = pthread_cond_wait(&m_condition, pmutex);
assert(res == 0);
}
bool condition::do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex)
bool condition_impl::do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex)
{
timespec ts;
to_timespec(xt, ts);
int res = 0;
res = pthread_cond_timedwait(&m_condition, pmutex, &ts);
// Test code for QNX debugging, to get information during regressions
#ifndef NDEBUG
if (res == EINVAL) {
boost::xtime now;
boost::xtime_get(&now, boost::TIME_UTC);
std::cerr << "now: " << now.sec << " " << now.nsec << std::endl;
std::cerr << "time: " << time(0) << std::endl;
std::cerr << "xtime: " << xt.sec << " " << xt.nsec << std::endl;
std::cerr << "ts: " << ts.tv_sec << " " << ts.tv_nsec << std::endl;
std::cerr << "pmutex: " << pmutex << std::endl;
std::cerr << "condition: " << &m_condition << std::endl;
assert(res != EINVAL);
}
#endif
assert(res == 0 || res == ETIMEDOUT);
return res != ETIMEDOUT;
}
#elif defined(BOOST_HAS_MPTASKS)
using threads::mac::detail::safe_enter_critical_region;
using threads::mac::detail::safe_wait_on_semaphore;
condition_impl::condition_impl()
: m_gone(0), m_blocked(0), m_waiting(0)
{
threads::mac::detail::thread_init();
OSStatus lStatus = noErr;
lStatus = MPCreateSemaphore(1, 1, &m_gate);
if(lStatus == noErr)
lStatus = MPCreateSemaphore(ULONG_MAX, 0, &m_queue);
if(lStatus != noErr || !m_gate || !m_queue)
{
if (m_gate)
{
lStatus = MPDeleteSemaphore(m_gate);
assert(lStatus == noErr);
}
if (m_queue)
{
lStatus = MPDeleteSemaphore(m_queue);
assert(lStatus == noErr);
}
throw thread_resource_error();
}
}
condition_impl::~condition_impl()
{
OSStatus lStatus = noErr;
lStatus = MPDeleteSemaphore(m_gate);
assert(lStatus == noErr);
lStatus = MPDeleteSemaphore(m_queue);
assert(lStatus == noErr);
}
void condition_impl::notify_one()
{
unsigned signals = 0;
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
m_mutex_mutex);
assert(lStatus == noErr);
if (m_waiting != 0) // the m_gate is already closed
{
if (m_blocked == 0)
{
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
return;
}
++m_waiting;
--m_blocked;
}
else
{
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
assert(lStatus == noErr);
if (m_blocked > m_gone)
{
if (m_gone != 0)
{
m_blocked -= m_gone;
m_gone = 0;
}
signals = m_waiting = 1;
--m_blocked;
}
else
{
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
}
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
while (signals)
{
lStatus = MPSignalSemaphore(m_queue);
assert(lStatus == noErr);
--signals;
}
}
}
void condition_impl::notify_all()
{
unsigned signals = 0;
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
m_mutex_mutex);
assert(lStatus == noErr);
if (m_waiting != 0) // the m_gate is already closed
{
if (m_blocked == 0)
{
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
return;
}
m_waiting += (signals = m_blocked);
m_blocked = 0;
}
else
{
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
assert(lStatus == noErr);
if (m_blocked > m_gone)
{
if (m_gone != 0)
{
m_blocked -= m_gone;
m_gone = 0;
}
signals = m_waiting = m_blocked;
m_blocked = 0;
}
else
{
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
}
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
while (signals)
{
lStatus = MPSignalSemaphore(m_queue);
assert(lStatus == noErr);
--signals;
}
}
}
void condition_impl::enter_wait()
{
OSStatus lStatus = noErr;
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
assert(lStatus == noErr);
++m_blocked;
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
}
void condition_impl::do_wait()
{
OSStatus lStatus = noErr;
lStatus = safe_wait_on_semaphore(m_queue, kDurationForever);
assert(lStatus == noErr);
unsigned was_waiting=0;
unsigned was_gone=0;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
m_mutex_mutex);
assert(lStatus == noErr);
was_waiting = m_waiting;
was_gone = m_gone;
if (was_waiting != 0)
{
if (--m_waiting == 0)
{
if (m_blocked != 0)
{
lStatus = MPSignalSemaphore(m_gate); // open m_gate
assert(lStatus == noErr);
was_waiting = 0;
}
else if (m_gone != 0)
m_gone = 0;
}
}
else if (++m_gone == ((std::numeric_limits<unsigned>::max)() / 2))
{
// timeout occured, normalize the m_gone count
// this may occur if many calls to wait with a timeout are made and
// no call to notify_* is made
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
assert(lStatus == noErr);
m_blocked -= m_gone;
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
m_gone = 0;
}
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
if (was_waiting == 1)
{
for (/**/ ; was_gone; --was_gone)
{
// better now than spurious later
lStatus = safe_wait_on_semaphore(m_queue, kDurationForever);
assert(lStatus == noErr);
}
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
}
}
bool condition_impl::do_timed_wait(const xtime& xt)
{
int milliseconds;
to_duration(xt, milliseconds);
OSStatus lStatus = noErr;
lStatus = safe_wait_on_semaphore(m_queue, milliseconds);
assert(lStatus == noErr || lStatus == kMPTimeoutErr);
bool ret = (lStatus == noErr);
unsigned was_waiting=0;
unsigned was_gone=0;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
m_mutex_mutex);
assert(lStatus == noErr);
was_waiting = m_waiting;
was_gone = m_gone;
if (was_waiting != 0)
{
if (!ret) // timeout
{
if (m_blocked != 0)
--m_blocked;
else
++m_gone; // count spurious wakeups
}
if (--m_waiting == 0)
{
if (m_blocked != 0)
{
lStatus = MPSignalSemaphore(m_gate); // open m_gate
assert(lStatus == noErr);
was_waiting = 0;
}
else if (m_gone != 0)
m_gone = 0;
}
}
else if (++m_gone == ((std::numeric_limits<unsigned>::max)() / 2))
{
// timeout occured, normalize the m_gone count
// this may occur if many calls to wait with a timeout are made and
// no call to notify_* is made
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
assert(lStatus == noErr);
m_blocked -= m_gone;
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
m_gone = 0;
}
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
if (was_waiting == 1)
{
for (/**/ ; was_gone; --was_gone)
{
// better now than spurious later
lStatus = safe_wait_on_semaphore(m_queue, kDurationForever);
assert(lStatus == noErr);
}
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
}
return ret;
}
#endif
} // namespace detail
} // namespace boost
// Change Log:
// 8 Feb 01 WEKEMPF Initial version.
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
// 3 Jan 03 WEKEMPF Modified for DLL implementation.

View File

@@ -1,25 +1,124 @@
// Copyright (C) 2001
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/config.hpp>
#include <boost/thread/exceptions.hpp>
#include <cstring>
#include <string>
namespace boost {
lock_error::lock_error() : std::runtime_error("thread lock error")
thread_exception::thread_exception()
: m_sys_err(0)
{
}
thread_resource_error::thread_resource_error() : std::runtime_error("thread resource error")
thread_exception::thread_exception(int sys_err_code)
: m_sys_err(sys_err_code)
{
}
thread_exception::~thread_exception() throw()
{
}
int thread_exception::native_error() const
{
return m_sys_err;
}
lock_error::lock_error()
{
}
lock_error::lock_error(int sys_err_code)
: thread_exception(sys_err_code)
{
}
lock_error::~lock_error() throw()
{
}
const char* lock_error::what() const throw()
{
return "boost::lock_error";
}
thread_resource_error::thread_resource_error()
{
}
thread_resource_error::thread_resource_error(int sys_err_code)
: thread_exception(sys_err_code)
{
}
thread_resource_error::~thread_resource_error() throw()
{
}
const char* thread_resource_error::what() const throw()
{
return "boost::thread_resource_error";
}
unsupported_thread_option::unsupported_thread_option()
{
}
unsupported_thread_option::unsupported_thread_option(int sys_err_code)
: thread_exception(sys_err_code)
{
}
unsupported_thread_option::~unsupported_thread_option() throw()
{
}
const char* unsupported_thread_option::what() const throw()
{
return "boost::unsupported_thread_option";
}
invalid_thread_argument::invalid_thread_argument()
{
}
invalid_thread_argument::invalid_thread_argument(int sys_err_code)
: thread_exception(sys_err_code)
{
}
invalid_thread_argument::~invalid_thread_argument() throw()
{
}
const char* invalid_thread_argument::what() const throw()
{
return "boost::invalid_thread_argument";
}
thread_permission_error::thread_permission_error()
{
}
thread_permission_error::thread_permission_error(int sys_err_code)
: thread_exception(sys_err_code)
{
}
thread_permission_error::~thread_permission_error() throw()
{
}
const char* thread_permission_error::what() const throw()
{
return "boost::thread_permission_error";
}
} // namespace boost

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

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

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

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

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

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

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

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

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

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

View File

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

View File

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

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

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

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

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

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