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

Compare commits

..

38 Commits

Author SHA1 Message Date
nobody
f25e80b47c This commit was manufactured by cvs2svn to create branch
'python-v2-dev'.

[SVN r14785]
2002-08-12 13:35:54 +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
109 changed files with 7708 additions and 5956 deletions

2
build/.cvsignore Normal file
View File

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

View File

@@ -3,47 +3,68 @@
# in all copies. This software is provided "as is" without express or implied # 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. # warranty, and with no claim as to its suitability for any purpose.
# #
# Boost.Threads build and test Jamfile # Boost.Threads build Jamfile
# #
# Declares the following targets: # Declares the following targets:
# 1. libboost_thread, a static link library. # 1. libboost_thread, a static link library.
# 1a. On Win32, a dynamic link library libboost_threadmon, # 1a. On Win32 (when PTW32 is not defined), a dynamic link library
# which must be used in conjunction with libboost_thread. # boost_threadmon, which must be used in conjunction with
# libboost_thread. Note that this DLL *must* be used through static
# linking to the import library. Dynamic loading will cause undefined
# behavior.
# Additional configuration variables used:
# 1. PTW32 may be used on Win32 platforms to specify that the pthreads-win32
# library should be used instead of "native" threads. This feature is
# mostly used for testing and it's generally recommended you use the
# native threading libraries instead. PTW32 should be set to be a list
# of two strings, the first specifying the installation path of the
# pthreads-win32 library and the second specifying which library
# variant to link against (see the pthreads-win32 documentation).
# Example: jam -sPTW32="c:\pthreads-win32 pthreadVCE.lib"
# declare the location of this subproject relative to the root # Declare the location of this subproject relative to the root.
subproject libs/thread/build ; subproject libs/thread/build ;
# Include threads.jam for Boost.Threads global build information.
# This greatly simplifies the Jam code needed to configure the build
# for the various Win32 build types.
SEARCH on <module@>threads.jam = $(SUBDIR) ;
include <module@>threads.jam ;
####################### #######################
# Conditionally declare the Boost.Threads dynamic link library boost_threadmon.
# if $(NT) && ! $(PTW32)
# 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) dll boost_threadmon
{ : ../src/threadmon.cpp
PTW32_REQUIREMENTS = <define>BOOST_HAS_PTHREADS <define>PtW32NoCatchWarn ; : <sysinclude>$(BOOST_ROOT)
} <threading>multi
else : debug release <runtime-link>static/dynamic
{ ;
dll libboost_threadmon : ../src/threadmon.cpp
# requirements
: <include>$(BOOST_ROOT)
<threading>multi
: debug release ;
}
} }
# Base names of the source files for libboost_thread #######################
# Declare the Boost.Threads static link library libboost_thread.
# Base names of the source files for libboost_thread.
CPP_SOURCES = CPP_SOURCES =
condition mutex recursive_mutex thread tss xtime once exceptions ; condition mutex recursive_mutex thread tss xtime once exceptions ;
lib libboost_thread : ../src/$(CPP_SOURCES).cpp lib boost_thread
# requirements : ../src/$(CPP_SOURCES).cpp
: <include>$(BOOST_ROOT) : <sysinclude>$(BOOST_ROOT)
$(PTW32_REQUIREMENTS) <threading>multi
<threading>multi $(pthreads-win32)
: debug release ; : debug release <runtime-link>static/dynamic
;
#######################
# Stage the generated targets.
#stage bin-stage
# : <lib>boost_thread $(threadmon)
# : <tag><runtime-link-static>"s"
# <tag><debug>"d"
# : debug release <runtime-link>static/dynamic
#;

23
build/threads.jam Normal file
View File

@@ -0,0 +1,23 @@
# Do some OS-specific setup
threadmon = ;
pthreads-win32 = ;
if $(NT)
{
if $(PTW32)
{
local install-path = $(PTW32[1]) ;
local lib = $(PTW32[2]) ;
pthreads-win32 =
<define>BOOST_HAS_PTHREADS
<define>PtW32NoCatchWarn
<include>$(install-path)/pre-built/include
<library-file>$(install-path)/pre-built/lib/$(lib)
;
}
else
{
threadmon = <dll>../build/boost_threadmon ;
}
}

BIN
build/threads.mcp Normal file

Binary file not shown.

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>

69
doc/acknowledgments.html Normal file
View File

@@ -0,0 +1,69 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../../../boost.css">
<title>Boost.Threads - Acknowledgments</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Acknowledgments</h2>
</td>
</tr>
</table>
<hr>
<p><a href="../../../people/william_kempf.htm">William E. Kempf</a> was the architect,
designer, and implementor of <b>Boost.Threads</b>.</p>
<p>Mac OS Carbon implementation written by <a href="../../../people/mac_murrett.htm">Mac
Murrett</a>.</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),
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).</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><i>&copy; Copyright <a href="mailto:wekempf@cox.net">William E. Kempf</a> 2001-2002.
All Rights Reserved.</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>
</html>

View File

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

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>

View File

@@ -1,253 +1,205 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content= <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
"text/html; charset=iso-8859-1"> <link rel="stylesheet" type="text/css" href="../../../boost.css">
<meta name="keywords" content="threads, BTL, thread library, C++"> <title>Boost.Threads - Header &lt;boost/thread/condition.hpp&gt;</title>
<link rel="stylesheet" type="text/css" href="styles.css"> </head>
<body link="#0000ff" vlink="#800080">
<title>Boost.Threads, condition</title> <table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
</head> "header">
<tr>
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080" text="#000000"> <td valign="top" width="300">
<table summary="header" border="0" cellpadding="7" cellspacing="0" <h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
width="100%"> </td>
<tr> <td valign="top">
<td valign="top" width="300"> <h1 align="center">Boost.Threads</h1>
<h3><img height="86" alt="C++ Boost" src= <h2 align="center">Header &lt;<a href="../../../boost/thread/condition.hpp">boost/thread/condition.hpp</a>&gt;</h2>
"../../../c++boost.gif" width="277"></h3> </td>
</td> </tr>
</table>
<td valign="top"> <hr>
<h1 align="center">Boost.Threads</h1> <h2>Contents</h2>
<dl class="page-index">
<h2 align="center">condition</h2> <dt><a href="#introduction">Introduction</a></dt>
</td> <dt><a href="#classes">Classes</a></dt>
</tr> <dl class="page-index">
</table> <dt><a href="#class-condition">Class <code>condition</code></a></dt>
<hr> <dl class="page-index">
<dt><a href="#class-condition-synopsis">Class <code>condition</code> synopsis</a></dt>
<p><a href="#Introduction">Introduction</a><br> <dt><a href="#class-condition-ctors">Class <code>condition</code> constructors
<a href="#Header">Header</a><br> and destructor</a></dt>
<a href="#Synopsis">Synopsis</a><br> <dt><a href="#class-condition-modifiers">Class <code>condition</code> modifier
<a href="#Members">Members</a><br> functions</a></dt>
<a href="#Example">Example</a></p> </dl>
</dl>
<h2><a name="Introduction">Introduction</a></h2> <dt><a href="#examples">Example(s)</a></dt>
</dl>
<p>An object of class <code>condition</code> is a synchronization <hr>
primitive used to cause a thread to wait until a particular shared-data <h2><a name="introduction"></a>Introduction</h2>
condition (or time) is met. A <code>condition</code> object is always <p>Include the header &lt;<a href="../../../boost/thread/condition.hpp">boost/thread/condition.hpp</a>&gt;
used in conjunction with a mutex object modeling a <a href= to define the class condition.</p>
"mutex_concept.html">Mutex Concept</a>. The mutex must be locked prior <h2><a name="classes"></a>Classes</h2>
to waiting on the <code>condition</code>, which is ensured by passing a <h3><a name="class-condition"></a>Class <code>condition</code></h3>
lock object modeling a <a href="lock_concept.html">Lock Concept</a> to <p>An object of class <code>condition</code> is a synchronization primitive used
the <code>condition</code> object&#39;s <code>wait</code> functions. to cause a thread to wait until a particular shared-data condition (or time)
While the thread is waiting on the <code>condition</code> object, the is met. A <code>condition</code> object is always used in conjunction with a
mutex associated with the lock is unlocked. When the thread returns mutex object (an object whose type is a model of <a href="mutex_concept.html">Mutex</a>
from a call to one of the <code>condition</code> object&#39;s <code> or one of its refinements). The mutex object must be locked prior to waiting
wait</code> functions, the mutex is again locked. The tricky on the <code>condition</code>, which is verified by passing a lock object (an
lock/unlock/lock sequence is performed automatically by the <code> object whose type is a model of <a href="lock_concept.html">Lock</a> or one
condition</code> object&#39;s <code>wait</code> functions.</p> of its refinements) to the <code>condition</code> object&#39;s <code>wait</code>
functions. Upon blocking on the condition object, the thread unlocks the mutex
<p>The <code>condition</code> type is often used to implement the <i> object. When the thread returns from a call to one of the condition object's
Monitor Object</i> and other important patterns. See <a href= wait functions the mutex object is again locked. The tricky unlock/lock sequence
"bibliography.html#Schmidt-00">[Schmidt-00]</a> and <a href= is performed automatically by the <code> condition</code> object&#39;s <code>wait</code>
"bibliography.html#Hoare-74">[Hoare 74]</a>. Monitors are one of the functions.</p>
most important patterns for creating reliable multithreaded <p>The <code>condition</code> type is often used to implement the <i> Monitor
programs.</p> 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
<p>See <a href="definitions.html">Formal Definitions</a> for one of the most important patterns for creating reliable multithreaded programs.</p>
definitions of thread states <a href="definitions.html#state"> <p>See <a href="definitions.html">Formal Definitions</a> for definitions of thread
blocked</a> and <a href="definitions.html#state">ready</a>. Note that states <a href="definitions.html#state"> blocked</a> and <a href="definitions.html#state">ready</a>.
&quot;waiting&quot; is a synonym for blocked.</p> Note that &quot;waiting&quot; is a synonym for blocked.</p>
<h4><a name="class-condition-synopsis"></a>Class <code>condition</code> synopsis</h4>
<h2><a name="Header">Header</a></h2>
<pre> <pre>
#include <a href= namespace boost
"../../../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: class condition : private <a href="../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
condition(); // Class condition meets the <a href="overview.html#non-copyable">NonCopyable</a> requirement.
~condition(); {
public:
condition();
~condition();
void notify_one(); void notify_one();
void notify_all(); void notify_all();
template &lt;typename <a href="scoped_lock.html">ScopedLock</a>&gt; template &lt;typename <a href="lock_concept.html#Lock-concept">Lock</a>&gt;
void wait(<a href="scoped_lock.html">ScopedLock</a>&amp; lock); void wait(<a href="lock_concept.html#Lock-concept">Lock</a>&amp; lock);
template &lt;typename <a href="scoped_lock.html">ScopedLock</a>, typename <a template &lt;typename <a href="lock_concept.html#Lock-concept">Lock</a>, typename <a href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a>&gt;
href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a>&gt; void wait(<a href="lock_concept.html#Lock-concept">Lock</a>&amp; lock, <a href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a> pred);
void wait(<a href="scoped_lock.html">ScopedLock</a>&amp; lock, <a href= template &lt;typename <a href="lock_concept.html#Lock-concept">Lock</a>&gt;
"http://www.sgi.com/tech/stl/Predicate.html">Predicate</a> pred); bool timed_wait(<a href="lock_concept.html#Lock-concept">Lock</a>&amp; lock, const xtime&amp; xt);
template &lt;typename <a href="scoped_lock.html">ScopedLock</a>&gt; template &lt;typename <a href="lock_concept.html#Lock-concept">Lock</a>, typename <a href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a>&gt;
bool timed_wait(<a href= bool timed_wait(<a href="lock_concept.html#Lock-concept">Lock</a>&amp; lock, const xtime&amp; XT, <a href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a> pred);
"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> </pre>
<h4><a name="class-condition-ctors"></a>Class <code>condition</code> constructors
<h2><a name="Members">Members</a></h2> and destructor</h4>
<hr>
<h3>Constructor</h3>
<pre> <pre>
condition(); condition();
</pre> </pre>
<dl class="function-semantics">
<p><b>Effects:</b> Constructs a <code>condition</code>.</p> <dt><b>Effects:</b> Constructs a <code>condition</code> object.</dt>
<hr> </dl>
<h3>Destructor</h3>
<pre> <pre>
~condition(); ~condition();
</pre> </pre>
<dl class="function-semantics">
<p><b>Effects:</b> Destroys <code>*this</code>.</p> <dt><b>Effects:</b> Destroys <code>*this</code>.</dt>
<hr> </dl>
<h4><a name="class-condition-modifiers"></a>Class <code>condition</code> modifier
<h3>notify_one</h3> functions</h4>
<pre> <pre>
void notify_one(); void notify_one();
</pre> </pre>
<dl class="function-semantics">
<p><b>Effects:</b> If there is a thread waiting on <code>*this</code>, <dt><b>Effects:</b> If there is a thread waiting on <code>*this</code>, change
change that thread&#39;s state to ready. Otherwise there is no that thread&#39;s state to ready. Otherwise there is no effect.</dt>
effect.</p> <dt><b>Note:</b> If more than one thread is waiting on the condition, it is
unspecified which is made ready. After returning to a ready state the notified
<p><b>Notes:</b> If more that one thread is waiting on the condition, thread must still acquire the mutex again (which occurs within the call to
it is unspecified which is made ready.</p> one of the <code>condition</code> object's wait functions).</dt>
<hr> </dl>
<h3>notify_all</h3>
<pre> <pre>
void notify_all(); void notify_all();
</pre> </pre>
<dl class="function-semantics">
<p><b>Effects:</b> Change the state of all threads waiting on <code> <dt><b>Effects:</b> Change the state of all threads waiting on <code> *this</code>
*this</code> to ready. If there are no waiting threads, <code> to ready. If there are no waiting threads, <code> notify_all()</code> has
notify_all()</code> has no effect.</p> no effect.</dt>
<hr> </dl>
<h3>wait</h3>
<pre> <pre>
template &lt;typename ScopedLock&gt; template &lt;typename ScopedLock&gt;
void wait(ScopedLock&amp; lock); void wait(ScopedLock&amp; lock);
</pre> </pre>
<dl class="function-semantics">
<p><b>Requires:</b> ScopedLock meets the <a href= <dt><b>Requires:</b> <code>ScopedLock</code> meets the <a href="lock_concept.html#ScopedLock">ScopedLock</a>
"lock_concept.html#ScopedLock">ScopedLock</a> requirements.</p> requirements.</dt>
<dt><b>Effects:</b> Releases the lock on the <a href="mutex_concept.html">mutex
<p><b>Effects:</b> Releases the lock on the <a href= model</a> associated with <code>lock</code>, blocks the current thread of
"mutex_concept.html">mutex model</a> associated with <code>lock</code>, execution until readied by a call to <code>this-&gt;notify_one()</code> or
blocks the current thread of execution until readied by a call to <code> this-&gt;notify_all()</code>, and then reacquires the lock.</dt>
<code>this-&gt;notify_one()</code> or <code> <dt><b>Throws:</b> <code><a href="exceptions.html#class-lock_error">lock_error</a></code>
this-&gt;notify_all()</code>, and then reacquires the lock. All effects if <code>!lock.locked()</code></dt>
occur in an atomic fashion.</p> <dt><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
<p><b>Throws:</b> <code><a href="lock_error.html">lock_error</a></code> true. Without the loop, race conditions can ensue due to possible &quot;spurious
if <code>!lock.locked()</code></p> wake ups&quot;. The second version encapsulates this loop idiom internally
and is generally the preferred method.</dt>
<p><b>Danger:</b> This version should always be used within a loop </dl>
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> <pre>
template &lt;typename ScopedLock, typename Pr&gt; Template&lt;typename ScopedLock, typename Pr&gt;
void wait(ScopedLock&amp; lock, Pr pred); void wait(ScopedLock&amp; lock, Pr pred);
</pre> </pre>
<dl class="function-semantics">
<p><b>Requires:</b> ScopedLock meets the <a href= <dt><b>Requires:</b> <code>ScopedLock</code> meets the <a href="lock_concept.html#ScopedLock">ScopedLock</a>
"lock_concept.html#ScopedLock">ScopedLock</a> requirements, return from requirements, return from <code>pred()</code> convertible to bool.</dt>
<code>pred()</code> convertible to bool.</p> <dt><b>Effects:</b> As if: <code>while (!pred()) wait(lock)</code></dt>
<dt><b>Throws:</b> <code><a href="exceptions.html#class-lock_error">lock_error</a></code>
<p><b>Effects:</b> As if:</p> if <code>!lock.locked()</code></dt>
<code>&nbsp;&nbsp;&nbsp;while (!pred()) wait(lock)</code> </dl>
<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> <pre>
template &lt;typename ScopedLock&gt; template &lt;typename ScopedLock&gt;
bool timed_wait(ScopedLock&amp; lock, const <a href= bool timed_wait(ScopedLock&amp; lock, const <a href="xtime.html">xtime</a>&amp; XT);
"xtime.html">xtime</a>&amp; xt);
</pre> </pre>
<dl class="function-semantics">
<p><b>Requires:</b> ScopedLock meets the <a href= <dt><b>Requires:</b> <code>ScopedLock</code> meets the <a href="lock_concept.html#ScopedLock">ScopedLock</a>
"lock_concept.html#ScopedLock">ScopedLock</a> requirements.</dt>
requirements.</p> <dt><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
<p><b>Effects:</b> Releases the lock on the <a href= of execution until readied by a call to <code>this-&gt;notify_one()</code>
"mutex_concept.html">mutex model</a> associated with the <code> or <code> this-&gt;notify_all()</code>, or until <code>XT</code>, and then
lock</code>, blocks the current thread of execution until readied by a reacquires the lock.</dt>
call to <code>this-&gt;notify_one()</code> or <code> <dt><b>Returns:</b> <code>false</code> if <code>XT</code> is reached, otherwise
this-&gt;notify_all()</code>, or until <code>xt</code>, and then <code>true</code>.</dt>
reacquires the lock. All effects occur in an atomic fashion.</p> <dt><b>Throws:</b> <code><a href="exceptions.html#class-lock_error">lock_error</a></code>
if <code>!lock.locked()</code></dt>
<p><b>Throws:</b> <code><a href="lock_error.html">lock_error</a></code> <dt><b>Danger:</b> This version should always be used within a loop checking
if <code>!lock.locked()</code></p> 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
<p><b>Danger:</b> This version should always be used within a loop ups&quot;. The second version encapsulates this loop idiom internally and
checking that the state logically associated with the <code> is generally the preferred method.</dt>
condition</code> has become true. Without the loop, race conditions can </dl>
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> <pre>
template &lt;typename ScopedLock, typename Pr&gt; Template&lt;typename ScopedLock, typename Pr&gt;
bool timed_wait(ScopedLock&amp; lock, const <a href= bool timed_wait(ScopedLock&amp; lock, const <a href="xtime.html">xtime</a>&amp; XT, Pr pred);
"xtime.html">xtime</a>&amp; xt, Pr pred);
</pre> </pre>
<dl class="function-semantics">
<p><b>Requires:</b> ScopedLock meets the <a href= <dt><b>Requires:</b> <code>ScopedLock</code> meets the <a href="lock_concept.html#ScopedLock">ScopedLock</a>
"lock_concept.html#ScopedLock">ScopedLock</a> requirements, requirements, return from <code>pred()</code> convertible to bool.</dt>
return from <code>pred()</code> convertible to bool.</p> <dt><b>Effects:</b> As if:<br>
<pre>
<p><b>Effects:</b> As if:</p> while (!pred())
<code>&nbsp;&nbsp;&nbsp;while (!pred())<br> {
&nbsp;&nbsp;&nbsp;{<br> if (!timed_wait(lock, XT))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!timed_wait(lock, xt))<br> return false;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return }
false;<br> return true;
&nbsp;&nbsp;&nbsp;}</code> </pre>
</dt>
<p><b>Throws:</b> <code><a href="lock_error.html">lock_error</a></code> <dt><b>Returns:</b> <code>false</code> if <code>XT</code> is reached, otherwise
if <code>!lock.locked()</code></p> <code>true</code>.</dt>
<dt><b>Throws:</b> <code><a href="exceptions.html#class-lock_error">lock_error</a></code>
<p><b>Returns:</b> <code>false</code> if <code>xt</code> is reached, if <code>!lock.locked()</code></dt>
otherwise <code>true</code>.</p> </dl>
<hr> <h2><a name="examples"></a>Example(s)</h2>
<h2><a name="Example">Example Usage</a></h2>
<pre> <pre>
#include &lt;iostream&gt; #include &lt;iostream&gt;
#include &lt;vector&gt; #include &lt;vector&gt;
#include <a href="../../../boost/utility.hpp">&lt;boost/utility.hpp&gt;</a> #include <a href="../../../boost/utility.hpp">&lt;boost/utility.hpp&gt;</a>
#include <a href= #include <a href="../../../boost/thread/condition.hpp">&lt;boost/thread/condition.hpp&gt;</a>
"../../../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>
#include <a href=
"../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
class bounded_buffer : private boost::noncopyable class bounded_buffer : private boost::noncopyable
{ {
@@ -312,8 +264,7 @@ int main(int, char*[])
return 0; return 0;
} }
</pre> </pre>
<p>Typical output (dependent on scheduling policies) is:</p>
<p>Typical output (dependent on scheduling policies) is:</p>
<pre> <pre>
sent: 0 sent: 0
sent: 1 sent: 1
@@ -326,13 +277,18 @@ received: 3
sent: 4 sent: 4
received: 4 received: 4
</pre> </pre>
<hr> <p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
<p>Revised 05 November, 2001
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p> <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com"> <p><i>&copy; Copyright <a href="mailto:wekempf@cox.net">William E. Kempf</a> 2001-2002.
William E. Kempf</a> 2001 all rights reserved.</i></p> All Rights Reserved.</i></p>
</body> <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>
</html> </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>

94
doc/configuration.html Normal file
View File

@@ -0,0 +1,94 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../../../boost.css">
<title>Boost.Threads - Configuration</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Configuration</h2>
</td>
</tr>
</table>
<hr>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#lib-defined-public">Public Library Defined Macros</a></dt>
<dt><a href="#lib-defined-impl">Library Defined Implementation Macros</a></dt>
</dl>
<h2><a name="introduction"></a>Introduction</h2>
<p><b>Boost.Threads</b> uses several configuration macros in <a href="../../config/config.htm">&lt;boost/config.hpp&gt;</a>,
as well as configuration macros meant to be supplied by the application. These
macros are documented here.</p>
<h2><a name="lib-defined-public"></a>Public Library Defined Macros</h2>
<p>These macros are defined by <b>Boost.Threads</b> but are expected to be used
by application code.</p>
<table summary="public library defined macros" cellspacing="10" width="100%">
<tr>
<td><b>Macro</b></td>
<td><b>Meaning</b></td>
</tr>
<tr>
<td>BOOST_HAS_THREADS</td>
<td>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 multithreading runtimes
(often determined by the compiler predefining the macro _MT) the BOOST_HAS_THREADS
macro remains undefined.</td>
</tr>
</table>
<h2><a name="lib-defined-impl"></a>Library Defined Implementation Macros</h2>
<p>These macros are defined by <b>Boost.Threads</b> and are implementation details
of interest only to implementors.</p>
<table summary="library defined implementation macros" cellspacing="10" width="100%">
<tr>
<td><b>Macro</b></td>
<td><b>Meaning</b></td>
</tr>
<tr>
<td>BOOST_HAS_WINTHREADS</td>
<td>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>BOOST_HAS_PTHREADS</td>
<td>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>BOOST_HAS_FTIME</td>
<td>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>BOOST_HAS_GETTTIMEOFDAY</td>
<td>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:wekempf@cox.net">William E. Kempf</a> 2001-2002.
All Rights Reserved.</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>
</html>

View File

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

110
doc/exceptions.html Normal file
View File

@@ -0,0 +1,110 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../../../boost.css">
<title>Boost.Threads - Header &lt;boost/thread/exceptions.hpp&gt;</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Header &lt;<a href="../../../boost/thread/exceptions.hpp">boost/thread/exceptions.hpp</a>&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#classes">Classes</a></dt>
<dl class="page-index">
<dt><a href="#class-lock_error">Class <code>lock_error</code></a></dt>
<dl class="page-index">
<dt><a href="#class-lock_error-synopsis">Class <code>lock_error</code> synopsis</a></dt>
<dt><a href="#class-lock_error-ctors">Class <code>lock_error</code> constructors
and destructor</a></dt>
</dl>
<dt><a href="#class-thread_resource_error">Class <code>thread_resource_error</code></a></dt>
<dl class="page-index">
<dt><a href="#class-thread_resource_error-synopsis">Class <code>thread_resource_error</code>
synopsis</a></dt>
<dt><a href="#class-thread_resource_error-ctors">Class <code>thread_resource_error</code>
constructors and destructor</a></dt>
</dl>
</dl>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p>Include the header &lt;<a href="../../../boost/thread/exceptions.hpp">boost/thread/exceptions.hpp</a>&gt;
to define the exception types that may be thrown by <b>Boost.Threads</b> classes.</p>
<h2><a name="classes"></a>Classes</h2>
<h3><a name="class-lock_error"></a>Class <code>lock_error</code></h3>
<p>The lock_error 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>
<h4><a name="class-lock_error-synopsis"></a>Class <code>lock_error</code> synopsis</h4>
<pre>
namespace boost
{
class lock_error : public std::logical_error
{
public:
lock_error();
};
};
</pre>
<h4><a name="class-lock_error-ctors"></a>Class <code>lock_error</code> constructors
and destructor</h4>
<pre>
lock_error();
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Constructs a <code>lock_error</code> object.</dt>
</dl>
<h3><a name="class-thread_resource_error"></a>Class <code>thread_resource_error</code></h3>
<p>The thread_resource_error class defines an exception type that is thrown by
constructors in the Boost.Threads library when thread related resources can
not be acquired. This does not include memory allocation failures which instead
throw std::bad_alloc. </p>
<h4><a name="class-thread_resource_error-synopsis"></a>Class <code>thread_resource_error</code>
synopsis</h4>
<pre>
namespace boost
{
class thread_resource_error : public std::runtime_error
{
public:
thread_resource_error();
};
};
</pre>
<h4><a name="class-thread_resource_error-ctors"></a>Class <code>thread_resource_error</code>
constructors and destructor</h4>
<pre>
thread_resource_error();
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Constructs a <code>thread_resource_error</code> object.</dt>
</dl>
<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:wekempf@cox.net">William E. Kempf</a> 2001-2002.
All Rights Reserved.</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>
</html>

View File

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

View File

@@ -1,138 +1,155 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content= <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
"text/html; charset=iso-8859-1"> <link rel="stylesheet" type="text/css" href="../../../boost.css">
<meta name="keywords" content="threads, BTL, thread library, C++"> <title>Boost.Threads</title>
</head>
<title>Boost.Threads, Index</title> <body link="#0000ff" vlink="#800080">
</head> <table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080"> <tr>
<table summary="header" border="0" cellpadding="7" cellspacing="0" <td valign="top" width="300">
width="100%"> <h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
<tr> </td>
<td valign="top" width="300"> <td valign="top">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width= <h1 align="center">Boost.Threads</h1>
"277" height="86"></h3> <h2 align="center">Index</h2>
</td> </td>
</tr>
<td valign="top"> </table>
<h1 align="center">Boost.Threads</h1> <hr>
<h2>Contents</h2>
<h2 align="center">Documentation Map</h2> <dl class="index">
</td> <dt><a href="overview.html">Overview</a></dt>
</tr> <dt><a href="mutex_concept.html">Mutex Concepts</a></dt>
</table> <dl class="index">
<hr> <dt><a href="mutex_concept.html#Mutex">Mutex</a></dt>
<dt><a href="mutex_concept.html#TryMutex">TryMutex</a></dt>
<h2>Contents</h2> <dt><a href="mutex_concept.html#TimedMutex">TimedMutex</a></dt>
</dl>
<ul> <dt><a href="lock_concept.html">Lock Concepts</a></dt>
<li><a href="overview.html">Overview</a></li> <dl class="index">
<dt><a href="lock_concept.html#Lock">Lock</a></dt>
<li> <dt><a href="lock_concept.html#ScopedLock">ScopedLock</a></dt>
<a href="mutex_concept.html">Mutex Concepts</a> <dt><a href="lock_concept.html#ScopedTryLock">ScopedTryLock</a></dt>
<dt><a href="lock_concept.html#ScopedTimedLock">ScopedTimedLock</a></dt>
<ul> </dl>
<li><a href="mutex_concept.html#Mutex">Mutex</a></li> <dt>Reference</dt>
<dl class="index">
<li><a href="mutex_concept.html#TryMutex">TryMutex</a></li> <dt><a href="condition.html"><code>&lt;boost/thread/condition.hpp&gt;</code></a></dt>
<dl class="index">
<li><a href="mutex_concept.html#TimedMutex"> <dt><a href="condition.html#classes">Classes</a></dt>
TimedMutex</a></li> <dl class="index">
</ul> <dt><a href="condition.html#class-condition"><code>condition</code></a></dt>
</li> </dl>
</dl>
<li> </dl>
Mutex Classes <dl class="index">
<dt><a href="exceptions.html"><code>&lt;boost/thread/exceptions.hpp&gt;</code></a></dt>
<ul> <dl class="index">
<li><a href="mutex.html">mutex / try_mutex / <dt><a href="exceptions.html#classes">Classes</a></dt>
timed_mutex</a></li> <dl class="index">
<dt><a href="exceptions.html#class-lock_error"><code>lock_error</code></a></dt>
<li><a href="recursive_mutex.html">recursive_mutex / <dt><a href="exceptions.html#class-thread_resource_error"><code>thread_resource_error</code></a></dt>
recursive_try_mutex / recursive_timed_mutex</a></li> </dl>
</ul> </dl>
</li> </dl>
<dl class="index">
<li> <dt><a href="mutex.html"><code>&lt;boost/thread/mutex.hpp&gt;</code></a></dt>
<a href="lock_concept.html">Lock Concepts</a> <dl class="index">
<dt><a href="mutex.html#classes">Classes</a></dt>
<ul> <dl class="index">
<li><a href="lock_concept.html#Lock">Lock</a></li> <dt><a href="mutex.html#class-mutex"><code>mutex</code></a></dt>
<dt><a href="mutex.html#class-try_mutex"><code>try_mutex</code></a></dt>
<li><a href="lock_concept.html#ScopedLock"> <dt><a href="mutex.html#class-timed_mutex"><code>timed_mutex</code></a></dt>
ScopedLock</a></li> </dl>
</dl>
<li><a href="lock_concept.html#ScopedTryLock"> </dl>
ScopedTryLock</a></li> <dl class="index">
<dt><a href="once.html"><code>&lt;boost/thread/once.hpp&gt;</code></a></dt>
<li><a href="lock_concept.html#ScopedTimedLock"> <dl class="index">
ScopedTimedLock</a></li> <dt><a href="once.html#macros">Macros</a></dt>
</ul> <dl class="index">
</li> <dt><a href="once.html#macro-BOOST_ONCE_INIT"><code>BOOST_ONCE_INIT</code></a></dt>
</dl>
<li> <dt><a href="once.html#types">Types</a></dt>
Lock Classes <dl class="index">
<dt><a href="once.html#type-once_flag"><code>once_flag</code></a></dt>
<ul> </dl>
<li><a href="scoped_lock.html">scoped_lock</a></li> <dt><a href="once.html#functions">Functions</a></dt>
<dl class="index">
<li><a href="scoped_try_lock.html">scoped_try_lock</a></li> <dt><a href="once.html#function-call_once"><code>call_once</code></a></dt>
</dl>
<li><a href="scoped_timed_lock.html"> </dl>
scoped_timed_lock</a></li> </dl>
</ul> <dl class="index">
</li> <dt><a href="recursive_mutex.html"><code>&lt;boost/thread/recursive_mutex.hpp&gt;</code></a></dt>
<dl class="index">
<li>Class <a href="condition.html">condition</a></li> <dt><a href="recursive_mutex.html#classes">Classes</a></dt>
<dl class="index">
<li>Class <a href="thread_specific_ptr.html"> <dt><a href="recursive_mutex.html#class-recursive_mutex"><code>recursive_mutex</code></a></dt>
thread_specific_ptr</a></li> <dt><a href="recursive_mutex.html#class-recursive_try_mutex"><code>recursive_try_mutex</code></a></dt>
<dt><a href="recursive_mutex.html#class-recursive_timed_mutex"><code>recursive_timed_mutex</code></a></dt>
<li>Class <a href="thread.html">thread</a></li> </dl>
</dl>
<li>Class <a href="thread_group.html">thread_group</a></li> </dl>
<dl class="index">
<li>Class <a href="xtime.html">xtime</a></li> <dt><a href="thread.html"><code>&lt;boost/thread/thread.hpp&gt;</code></a></dt>
<dl class="index">
<li>Class <a href="lock_error.html">lock_error</a></li> <dt><a href="thread.html#classes">Classes</a></dt>
<dl class="index">
<li>Class <a href="thread_resource_error.html"> <dt><a href="thread.html#class-thread"><code>thread</code></a></dt>
thread_resource_error</a></li> <dt><a href="thread.html#class-thread_group"><code>thread_group</code></a></dt>
</dl>
<li>Routine <a href="call_once.html">call_once</a></li> </dl>
</dl>
<li><a href="config.html">Configuration Information</a></li> <dl class="index">
<dt><a href="tss.html"><code>&lt;boost/thread/tss.hpp&gt;</code></a></dt>
<li><a href="introduction.html">Introduction to design</a></li> <dl class="index">
<dt><a href="tss.html#classes">Classes</a></dt>
<li><a href="rationale.html">Rationale for design <dl class="index">
decisions</a></li> <dt><a href="tss.html#class-thread_specific_ptr"><code>thread_specific_ptr</code></a></dt>
</dl>
<li><a href="definitions.html">Definitions</a></li> </dl>
</dl>
<li><a href="faq.html">Frequently Asked Questions</a></li> <dl class="index">
<dt><a href="xtime.html"><code>&lt;boost/thread/xtime.hpp&gt;</code></a></dt>
<li><a href="bibliography.html">Bibliography</a></li> <dl class="index">
<dt><a href="xtime.html#values">Values</a></dt>
<li><a href="acknowledgements.html">Acknowledgements</a></li> <dl class="page-index">
</ul> <dt><a href="xtime.html#value-spec"><code>TIME_UTC</code></a></dt>
<hr> </dl>
<dt><a href="xtime.html#classes">Classes</a></dt>
<p>Revised <dl class="page-index">
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p> <dt><a href="xtime.html#class-xtime"><code>xtime</code></a></dt>
</dl>
<p>&copy; <i>Copyright <a href="mailto:williamkempf@hotmail.com"> <dt><a href="xtime.html#functions">Functions</a></dt>
William E. Kempf</a> 2001</i></p> <dl class="page-index">
<dt><a href="xtime.html#function-xtime_get"><code>xtime_get</code></a></dt>
<p>Permission to use, copy, modify, distribute and sell this software </dl>
and its documentation for any purpose is hereby granted without fee, </dl>
provided that the above copyright notice appear in all copies and that </dl>
both that copyright notice and this permission notice appear in <dt><a href="configuration.html">Configuration Information</a></dt>
supporting documentation. William E. Kempf makes no representations <dt><a href="introduction.html">Introduction to Design</a></dt>
about the suitability of this software for any purpose. It is provided <dt><a href="rationale.html">Rationale</a></dt>
&quot;as is&quot; without express or implied warranty.</p> <dt><a href="definitions.html">Definitions</a></dt>
</body> <dt><a href="faq.html">Frequently Asked Questions (FAQs)</a></dt>
<dt><a href="bibliography.html">Bibliography</a></dt>
<dt><a href="acknowledgments.html">Acknowledgments</a></dt>
</dl>
<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:wekempf@cox.net">William E. Kempf</a> 2001-2002.
All Rights Reserved.</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>
</html> </html>

View File

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

View File

@@ -1,300 +1,194 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content= <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
"text/html; charset=iso-8859-1"> <link rel="stylesheet" type="text/css" href="../../../boost.css">
<meta name="keywords" content="threads, BTL, thread library, C++"> <title>Boost.Threads - ScopedLock Concept</title>
</head>
<title>Boost.Threads, Lock Concept</title> <body link="#0000ff" vlink="#800080">
</head> <table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080"> <tr>
<table summary="header" border="0" cellpadding="7" cellspacing="0" <td valign="top" width="300">
width="100%"> <h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
<tr> </td>
<td valign="top" width="300"> <td valign="top">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width= <h1 align="center">Boost.Threads</h1>
"277" height="86"></h3> <h2 align="center">ScopedLock Concept</h2>
</td> </td>
</tr>
<td valign="top"> </table>
<h1 align="center">Boost.Threads</h1> <hr>
<dl class="page-index">
<h2 align="center">Lock Concepts</h2> <dt><a href="#introduction">Introduction</a></dt>
</td> <dt><a href="#concept-requirements">Concept Requirements</a></dt>
</tr> <dl class="page-index">
</table> <dt><a href="#Lock-concept">Lock Concept</a></dt>
<hr> <dt><a href="#ScopedLock-concept">ScopedLock Concept</a></dt>
<dt><a href="#ScopedTryLock-concept">ScopedTryLock Concept</a></dt>
<p><a href="#Introduction">Introduction</a><br> <dt><a href="#ScopedTimedLock-concept">ScopedTimedLock Concept</a></dt>
<a href="#Requirements">Concept Requirements</a><br> </dl>
<a href="#Lock">Lock Concept</a><br> </dl>
<a href="#ScopedLock">ScopedLock Concept</a><br> <h2><a name="introduction"></a>Introduction</h2>
<a href="#ScopedTryLock">ScopedTryLock Concept</a><br> <p>A lock object provides a safe means for locking and unlocking a mutex object
<a href="#ScopedTimedLock">ScopedTimedLock Concept</a><br> (an object whose type is a model of <a href="mutex_concept.html">Mutex</a> or
<a href="#Models">Models</a></p> one of its refinements). In other words they are an implementation of the <i>Scoped
Locking</i> <a href="bibliography.html#Schmidt-00">[Schmidt 00]</a> pattern.
<h2><a name="Introduction">Introduction</a></h2> The <a href="#ScopedLock-concept">ScopedLock</a> concept, with <a href="#ScopedTryLock-concept">ScopedTryLock</a>
and <a href="#ScopedTimedLock-concept">ScopedTimedLock</a> refinements, formalize
<p>The lock concepts provide exception safe means for locking and the requirements.</p>
unlocking a <a href="mutex_concept.html">mutex model</a>. In other <p>Lock objects are constructed with a reference to a mutex object and typically
words they are an implementation of the <i>Scoped Locking</i> <a href= acquire ownership of the mutex object by setting its state to locked. They also
"bibliography.html#Schmidt 00">[Schmidt 00]</a> pattern. The <a href= ensure ownership is relinquished in the destructor. Lock objects also expose
"#ScopedLock">ScopedLock</a> concept, with <a href="#ScopedTryLock"> functions to query the lock status and to manually lock and unlock the mutex
ScopedTryLock</a> and <a href="#ScopedTimedLock">ScopedTimedLock</a> object.</p>
refinements, formalize the requirements.</p> <p>Lock objects are meant to be short lived, expected to be used at block scope
only. The lock objects are not <a href="definitions.html#definition-thread-safe">thread-safe</a>.
<p>Lock models are constructed with a reference to a <a href= Lock objects must maintain state to indicate whether or not they&#39;ve been
"mutex_concept.html">mutex model</a> and typically acquire ownership of locked and this state is not protected by any synchronization concepts. For
the <a href="mutex_concept.html">mutex model</a> by setting its state this reason a lock object should never be shared between multiple threads.</p>
to locked. They also ensure ownership is relinquished in the <h2><a name="concept-requirements"></a>Concept Requirements</h2>
destructor. Lock models also expose functions to query the lock status <h3><a name="Lock-concept"></a>Lock Concept</h3>
and to manually lock and unlock the <a href="mutex_concept.html">mutex <p>For a Lock type <code>L</code> and an object <code>lk</code> and const object
model</a>.</p> <code>clk</code> of that type, the following expressions must be well-formed
and have the indicated effects.</p>
<p>Instances of lock models are meant to be short lived, expected to be <table summary="Lock expressions" border="1" cellpadding="5">
used at block scope only. The lock models are not <a href= <tr>
"definitions.html#Thread-safe">thread-safe</a>. Lock models must <td><b>Expression</b></td>
maintain state to indicate whether or not they&#39;ve been locked and <td><b>Effects</b></td>
this state is not protected by any synchronization concepts. For this </tr>
reason an instance of a lock model should never be shared between <tr>
multiple threads.</p> <td valign="top"><code>(&amp;lk)-&gt;~L();</code></td>
<td><code>if (locked()) unlock();</code></td>
<h2>Concept <a name="Requirements">Requirements</a></h2> </tr>
<tr>
<p>[For documentation purposes, portions of the concept requirements <td valign="top"><code>(&amp;clk)-&gt;operator const void*()</code></td>
are repeated in the documentation for specific lock classes. Those <td>Returns type void*, non-zero if if the associated mutex object has been
copies need to be kept in sync with the requirements here.]</p> locked by <code>clk</code>, otherwise 0.</td>
</tr>
<h3><a name="Lock">Lock</a> Concept</h3> <tr>
<td valign="top"><code>clk.locked()</code></td>
<p>For a <a href="#ScopedLock">ScopedLock</a>, <a href= <td>Returns a <code>bool</code>, <code>(&amp;clk)-&gt;operator const void*()
"#ScopedTryLock">ScopedTryLock</a>, or <a href="#ScopedTimedLock"> != 0</code></td>
ScopedTimedLock</a> type <code>L</code> and an object <code>lk</code> </tr>
and const object <code>clk</code> of that type, the following <tr>
expressions must be well-formed and have the indicated effects.</p> <td valign="top"><code>lk.lock()</code></td>
<td>Throws <code>lock_error</code> if <code>locked()</code>. If the associated
<p>The Lock concept is used as a base for the <a href="#ScopedLock"> mutex object is already locked by some other thread, places the current
ScopedLock</a>, <a href="#ScopedTryLock">ScopedTryLock</a>, and <a thread in the <a href="definitions.html#State">Blocked</a> state until the
href="#ScopedTimedLock">ScopedTimedLock</a> refinements. The associated associated mutex is unlocked, after which the current thread is placed in
mutex type is as specified for each of those refinements the <a href="definitions.html#State"> Ready</a> state, eventually to be
respectively.</p> returned to the <a href="definitions.html#State">Running</a> state. If the
associated mutex object is already locked by the same thread the behavior
<table summary="Lock expressions" border="1" cellpadding="5"> is dependent on the <a href="mutex_concept.html#locking-strategies">locking
<tr> strategy</a> of the associated mutex object.<br>
<td><b>Expression</b></td> Postcondition: <code>locked() == true</code></td>
</tr>
<td><b>Effects</b></td> <tr>
</tr> <td valign="top"><code>lk.unlock()</code></td>
<td>If <code>!locked()</code>, throws <code>lock_error</code>, otherwise unlocks
<tr> the associated mutex.<br>
<td valign="top"><code>(&amp;lk)-&gt;~L();</code></td> Postcondition: <code>!locked()</code></td>
</tr>
<td><code>if (locked()) unlock();</code></td> </table>
</tr> <h3><a name="ScopedLock-concept"></a>ScopedLock Concept</h3>
<p>A ScopedLock is a refinement of <a href="#Lock">Lock</a>. For a ScopedLock
<tr> type <code>L</code> and an object <code>lk</code> of that type, and an object
<td valign="top"><code>(&amp;clk)-&gt;operator const <code>m</code> of a type meeting the <a href="mutex_concept.html#Mutex-concept">Mutex</a>
void*()</code></td> 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>
<td>Returns type void*, non-zero if if the associated mutex has <table summary="ScopedLock expressions" border="1" cellpadding="5">
been locked by <code>clk</code>, otherwise 0.</td> <tr>
</tr> <td><b>Expression</b></td>
<td><b>Effects</b></td>
<tr> </tr>
<td valign="top"><code>clk.locked()</code></td> <tr>
<td valign="top"><code>L lk(m);</code></td>
<td>Returns a <code>bool</code>, <code>(&amp;clk)-&gt;operator <td>Constructs an object <code>lk</code>, and associates mutex object <code>m</code>
const void*() != 0</code></td> with it, then calls <code>lock()</code></td>
</tr> </tr>
<tr>
<tr> <td valign="top"><code>L lk(m,b);</code></td>
<td valign="top"><code>lk.lock()</code></td> <td>Constructs an object <code>lk</code>, and associates mutex object <code>m</code>
with it, then if <code>b</code>, calls <code>lock()</code></td>
<td>Throws lock_error if locked(). If the associated mutex is </tr>
already locked by some other thread, places the current thread </table>
in the <a href="definitions.html#State">Blocked</a> state until <h3><a name="ScopedTryLock-concept"></a>ScopedTryLock Concept</h3>
the associated mutex is unlocked, after which the current <p>A ScopedTryLock is a refinement of <a href="#Lock-concept">Lock</a>. For a
thread is placed in the <a href="definitions.html#State"> ScopedTryLock type <code>L</code> and an object <code>lk</code> of that type,
Ready</a> state, eventually to be returned to the <a href= and an object <code>m</code> of a type meeting the <a href="mutex_concept.html#TryMutex-concept">TryMutex</a>
"definitions.html#State">Running</a> state.<br> requirements, and an object <code>b</code> of type <code>bool</code>, the following
Postcondition: locked()</td> expressions must be well-formed and have the indicated effects.</p>
</tr> <table summary="ScopedTryLock expressions" border="1" cellpadding="5">
<tr>
<tr> <td><b>Expression</b></td>
<td valign="top"><code>lk.unlock()</code></td> <td><b>Effects</b></td>
</tr>
<td>If !locked(), throws lock_error, otherwise unlocks the <tr>
associated mutex.<br> <td valign="top"><code>L lk(m);</code></td>
Postcondition: !locked()</td> <td>Constructs an object <code>lk</code>, and associates mutex object <code>m</code>
</tr> with it, then calls <code>try_lock()</code></td>
</table> </tr>
<tr>
<h3><a name="ScopedLock">ScopedLock</a> Concept</h3> <td valign="top"><code>L lk(m,b);</code></td>
<td>Constructs an object <code>lk</code>, and associates mutex object <code>m</code>
<p>A ScopedLock must meet the <a href="#Lock">Lock</a> requirements. with it, then if <code>b</code>, calls <code> lock()</code></td>
For a ScopedLock type <code>L</code> and an object <code>lk</code> of </tr>
that type, and an object <code>m</code> of a type meeting the <a href= <tr>
"mutex_concept.html#Mutex">Mutex</a> requirements, and an object <code> <td valign="top"><code>lk.try_lock()</code></td>
b</code> of type <code>bool</code>, the following expressions must be <td>If locked(), throws <code>lock_error</code>. Makes a non-blocking attempt
well-formed and have the indicated effects.</p> to lock the associated mutex object, returning <code>true</code> if the
lock attempt is successful, otherwise <code>false</code>. If the associated
<table summary="ScopedLock expressions" border="1" cellpadding="5"> mutex object is already locked by the same thread the behavior is dependent
<tr> on the <a href="mutex_concept.html#locking-strategies">locking strategy</a>
<td><b>Expression</b></td> of the associated mutex object.</td>
</tr>
<td><b>Effects</b></td> </table>
</tr> <h3><a name="ScopedTimedLock-concept"></a>ScopedTimedLock Concept</h3>
<p>A ScopedTimedLock is a refinement of <a href="#Lock">Lock</a>. For a ScopedTimedLock
<tr> type <code>L</code> and an object <code>lk</code> of that type, and an object
<td valign="top"><code>L lk(m);</code></td> <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
<td>Constructs an object <code>lk</code>, and associates mutex object <code>t</code> of type <code><a href="xtime.html"> xtime</a></code>,
<code>m</code> with it, then calls <code>lock()</code></td> the following expressions must be well-formed and have the indicated effects.</p>
</tr> <table summary="ScopedTimedLock expressions" border="1" cellpadding=
<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"> "5">
<tr> <tr>
<td><b>Expression</b></td> <td><b>Expression</b></td>
<td><b>Effects</b></td>
<td><b>Effects</b></td> </tr>
</tr> <tr>
<td valign="top"><code>L lk(m,t);</code></td>
<tr> <td>Constructs an object <code>lk</code>, and associates mutex object <code>m</code>
<td valign="top"><code>L lk(m,t);</code></td> with it, then calls <code> timed_lock(t)</code></td>
</tr>
<td>Constructs an object <code>lk</code>, and associates mutex <tr>
<code>m</code> with it, then calls <code> <td valign="top"><code>L lk(m,b);</code></td>
timed_lock(t)</code></td> <td>Constructs an object <code>lk</code>, and associates mutex object <code>m</code>
</tr> with it, then if <code>b</code>, calls <code> lock()</code></td>
</tr>
<tr> <tr>
<td valign="top"><code>L lk(m,b);</code></td> <td valign="top"><code>lk.timed_lock(t)</code></td>
<td>If locked(), throws lock_error. Makes a blocking attempt to lock the associated
<td>Constructs an object <code>lk</code>, and associates mutex mutex object, and returns <code>true</code> if successful within the specified
<code>m</code> with it, then if <code>b</code>, calls <code> time <code>t</code>, otherwise <code>false</code>. If the associated mutex
lock()</code></td> object is already locked by the same thread the behavior is dependent on
</tr> the <a href="mutex_concept.html#locking-strategies">locking strategy</a>
of the associated mutex object.</td>
<tr> </tr>
<td valign="top"><code>lk.timed_lock(t)</code></td> </table>
<hr>
<td>If locked(), throws lock_error. Makes a blocking attempt to <p>Revised
lock the associated mutex, and returns <code>true</code> if <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
successful within the specified time <code>t</code>, otherwise 05 November, 2001
<code>false</code>.</td> <!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</tr> </p>
</table> <p><i>&copy; Copyright <a href="mailto:wekempf@cox.net">William E. Kempf</a> 2001-2002.
All Rights Reserved.</i></p>
<h2><a name="Models">Models</a></h2> <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
<p><b>Boost.Threads</b> currently supplies three classes which model above copyright notice appear in all copies and that both that copyright notice
lock concepts.</p> and this permission notice appear in supporting documentation. William E. Kempf
makes no representations about the suitability of this software for any purpose.
<p>These classes are normally accessed via typedefs of the same name It is provided &quot;as is&quot; without express or implied warranty.</p>
supplied by a <a href="mutex_concept.html">mutex model</a>.</p> </body>
<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> </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>

View File

@@ -1,298 +1,222 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content= <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
"text/html; charset=iso-8859-1"> <link rel="stylesheet" type="text/css" href="../../../boost.css">
<meta name="keywords" content="threads, BTL, thread library, C++"> <title>Boost.Threads - Header &lt;boost/thread/mutex.hpp&gt;</title>
<link rel="stylesheet" type="text/css" href="styles.css"> </head>
<body link="#0000ff" vlink="#800080">
<title>Boost.Threads, mutex</title> <table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
</head> "header">
<tr>
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080"> <td valign="top" width="300">
<table summary="header" border="0" cellpadding="7" cellspacing="0" <h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
width="100%"> </td>
<tr> <td valign="top">
<td valign="top" width="300"> <h1 align="center">Boost.Threads</h1>
<h3><img alt="C++ Boost" src="../../../c++boost.gif" width= <h2 align="center">Header &lt;<a href="../../../boost/thread/mutex.hpp">boost/thread/mutex.hpp</a>&gt;</h2>
"277" height="86"></h3> </td>
</td> </tr>
</table>
<td valign="top"> <hr>
<h1 align="center">Boost.Threads</h1> <h2>Contents</h2>
<dl class="page-index">
<h2 align="center">mutex<br> <dt><a href="#introduction">Introduction</a></dt>
try_mutex<br> <dt><a href="#classes">Classes</a></dt>
timed_mutex</h2> <dl class="page-index">
</td> <dt><a href="#class-mutex">Class <code>mutex</code></a></dt>
</tr> <dl class="page-index">
</table> <dt><a href="#class-mutex-synopsis">Class <code>mutex</code> synopsis</a></dt>
<hr> <dt><a href="#class-mutex-ctors">Class <code>mutex</code> constructors and
destructor</a></dt>
<p><a href="#Introduction">Introduction</a><br> </dl>
<a href="#Header">Header</a><br> </dl>
<a href="#mutex Synopsis">Class mutex Synopsis</a><br> <dl class="page-index">
<a href="#mutex Members">Class mutex Members</a><br> <dt><a href="#class-try_mutex">Class <code>try_mutex</code></a></dt>
<a href="#try_mutex Synopsis">Class try_mutex Synopsis</a><br> <dl class="page-index">
<a href="#try_mutex Members">Class try_mutex Members</a><br> <dt><a href="#class-try_mutex-synopsis">Class <code>try_mutex</code> synopsis</a></dt>
<a href="#timed_mutex Synopsis">Class timed_mutex Synopsis</a><br> <dt><a href="#class-try_mutex-ctors">Class <code>try_mutex</code> constructors
<a href="#timed_mutex Members">Class timed_mutex Members</a><br> and destructor</a></dt>
<a href="#Example">Example</a></p> </dl>
</dl>
<h2><a name="Introduction">Introduction</a></h2> <dl class="page-index">
<dt><a href="#class-timed_mutex">Class <code>timed_mutex</code></a></dt>
<p>The <tt><a href="#mutex Synopsis">mutex</a></tt>, <tt><a href= <dl class="page-index">
"#try_mutex Synopsis">try_mutex</a></tt> and <tt><a href= <dt><a href="#class-timed_mutex-synopsis">Class <code>timed_mutex</code>
"#timed_mutex Synopsis">timed_mutex</a></tt> classes define full synopsis</a></dt>
featured models of the <a href="mutex_concept.html#Mutex">Mutex</a>, <a <dt><a href="#class-timed_mutex-ctors">Class <code>timed_mutex</code> constructors
href="mutex_concept.html#TryMutex">TryMutex</a>, and <a href= and destructor</a></dt>
"mutex_concept.html#TimedMutex">TimedMutex</a> concepts. These types </dl>
should be used to non-recursively synchronize access to shared </dl>
resources. For recursive locking mechanics, see <a href= <dt><a href="#examples">Example(s)</a></dt>
"recursive_mutex.html">recursive mutexes</a>.</p> </dl>
<hr>
<p>Each class supplies one or more typedefs for lock types which model <h2><a name="introduction"></a>Introduction</h2>
matching lock concepts. For the best possible performance you should <p>Include the header &lt;<a href="../../../boost/thread/mutex.hpp">boost/thread/mutex.hpp</a>&gt;
use the mutex class that supports the minimum set of lock types that to define the <code><a href="#mutex Synopsis">mutex</a></code>, <code><a href=
you need.</p> "#try_mutex Synopsis">try_mutex</a></code> and <code><a href=
"#timed_mutex Synopsis">timed_mutex</a></code> classes.</p>
<table summary="lock types" border="1" cellpadding="5"> <p>The <code><a href="#mutex Synopsis">mutex</a></code>, <code><a href=
<tr> "#try_mutex Synopsis">try_mutex</a></code> and <code><a href=
<td><b>Mutex Class</b></td> "#timed_mutex Synopsis">timed_mutex</a></code> classes are models of <a href="mutex_concept.html#Mutex-concept">Mutex</a>,
<a href="mutex_concept.html#TryMutex-concept">TryMutex</a>, and <a href="mutex_concept.html#TimedMutex-concept">TimedMutex</a>
<td><b>Lock name</b></td> respectively. These types should be used to non-recursively synchronize access
to shared resources. For recursive locking mechanics, see the <a href="recursive_mutex.html">recursive
<td><b>Implementation defined Lock Type</b></td> mutexes</a> supplied by <b>Boost.Threads</b>.</p>
<p>Each class supplies one or more typedefs for lock types which model matching
<td><b>Lock Concept</b></td> lock concepts. For the best possible performance you should use the mutex class
</tr> that supports the minimum set of lock types that you need.</p>
<table summary="lock types" border="1" cellpadding="5">
<tr> <tr>
<td valign="top"><a href="#mutex Synopsis"><code> <td><b>Mutex Class</b></td>
mutex</code></a></td> <td><b>Lock name</b></td>
<td><b>Lock Concept</b></td>
<td valign="middle"><code>scoped_lock</code></td> </tr>
<tr>
<td valign="middle"><code><a href="scoped_lock.html"> <td valign="top"><a href="#mutex Synopsis"><code> mutex</code></a></td>
boost::</a></code><a href= <td valign="middle"><code>scoped_lock</code></td>
"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>
<td valign="middle"><a href="lock_concept.html#ScopedLock"> <tr>
ScopedLock</a></td> <td valign="top"><code><a href="#try_mutex Synopsis"> try_mutex</a></code>
</tr> </td>
<td valign="middle"><code>scoped_lock<br>
<tr> scoped_try_lock</code></td>
<td valign="top"><tt><a href="#try_mutex Synopsis"> <td valign="middle"><a href="lock_concept.html#ScopedLock"> ScopedLock</a><br>
try_mutex</a></tt> </td> <a href="lock_concept.html#ScopedTryLock"> ScopedTryLock</a></td>
</tr>
<td valign="middle"><code>scoped_lock<br> <tr>
scoped_try_lock</code></td> <td valign="top"><code><a href="#timed_mutex Synopsis"> timed_mutex</a></code>
</td>
<td valign="middle"><code><a href="scoped_lock.html"> <td valign="middle"><code>scoped_lock<br>
boost::</a></code><a href= scoped_try_lock<br>
"scoped_lock.html"><code>detail::thread::scoped_lock&lt;try_mutex&gt;<br> scoped_timed_lock</code></td>
<td valign="middle"><a href="lock_concept.html#ScopedLock"> ScopedLock</a><br>
</code></a> <code><a href="scoped_try_lock.html"> <a href="lock_concept.html#ScopedTryLock"> ScopedTryLock</a><br>
boost::detail::thread::scoped_try_lock&lt;try_mutex&gt;</a></code></td> <a href="lock_concept.html#ScopedTimedLock"> ScopedTimedLock</a></td>
</tr>
<td valign="middle"><a href="lock_concept.html#ScopedLock"> </table>
ScopedLock</a><br> <p>The <code>mutex</code>, <code>try_mutex</code> and <code>timed_mutex</code>
<a href="lock_concept.html#ScopedTryLock"> classes use an <code>Unspecified</code> <a href="mutex_concept.html#LockingStrategies">locking
ScopedTryLock</a></td> strategy</a>, so attempts to recursively lock them or attempts to unlock them
</tr> 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
<tr> platform. It is, however, recommended that implementations include debugging
<td valign="top"><code><a href="#timed_mutex Synopsis"> support to detect misuse when <code>NDEBUG</code> is not defined.</p>
timed_mutex</a></code> </td> <p>Like all the <b>Boost.Threads</b> <a href="mutex_concept.html">mutex models</a>,
the <code>mutex</code>, <code>try_mutex</code> and <code> timed_mutex</code>
<td valign="middle"><code>scoped_lock<br> leave the <a href="mutex_concept.html#SchedulingPolicies">scheduling policy</a>
scoped_try_lock<br> as <code> Unspecified</code>. Programmers should make no assumptions about the
scoped_timed_lock</code></td> order in which waiting threads acquire a lock.</p>
<h2><a name="classes"></a>Classes</h2>
<td valign="middle"><code><a href="scoped_lock.html"> <h3><a name="class-mutex"></a>Class <code>mutex</code></h3>
boost::</a></code><a href= <p>The <code>mutex</code> class is a model of <a href="mutex_concept.html#Mutex-concept">Mutex</a>
"scoped_lock.html"><code>detail::thread::scoped_lock&lt;timed_mutex&gt;</code></a><br> and <a href="overview.html#non-copyable">NonCopyable</a>, and provides no additional
facilities beyond the requirements of these concepts.</p>
<code><a href="scoped_try_lock.html">boost::</a></code><a <h4><a name="class-mutex-synopsis"></a>Class <code>mutex</code> synopsis</h4>
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> <pre>
namespace boost namespace boost
{ {
class mutex : private <a href= class mutex : private <a href="../../utility/utility.htm">boost::noncopyable</a> // Exposition only.
"../../utility/utility.htm">boost::noncopyable</a> // Exposition only. // Class mutex meets the <a href="overview.html#non-copyable">NonCopyable</a> requirement.
// Class mutex meets the <a href=
"overview.html#NonCopyable">NonCopyable</a> requirement.
{ {
public: public:
typedef <i>[implementation defined; see <a href= typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_lock;
"#Introduction">Introduction</a>]</i> scoped_lock;
mutex(); mutex();
~mutex(); ~mutex();
}; };
} };
</pre> </pre>
<h4><a name="class-mutex-ctors"></a>Class <code>mutex</code> constructors and
<h2>Class <a name="mutex Members">mutex Members</a></h2> destructor</h4>
<hr>
<h3>Constructor</h3>
<pre> <pre>
mutex(); mutex();
</pre> </pre>
<dl class="function-semantics">
<p><b>Postconditions:</b> <code>*this</code> is in the unlocked <dt><b>Postconditions:</b> <code>*this</code> is in an unlocked state.</dt>
state.</p> </dl>
<hr>
<h3>Destructor</h3>
<pre> <pre>
~mutex(); ~mutex();
</pre> </pre>
<dl class="function-semantics">
<p><b>Requires:</b> <code>*this</code> is in the unlocked state.</p> <dt><b>Requires:</b> <code>*this</code> is in an unlocked sate.</dt>
<dt><b>Danger:</b> Destruction of a locked mutex is a serious programming error
<p><b>Effects:</b> Destroys <code>*this</code>.</p> resulting in undefined behavior such as a program crash.</dt>
</dl>
<p><b>Dangers:</b> Destruction of a locked mutex is a serious <h3><a name="class-try_mutex"></a>Class <code>try_mutex</code></h3>
programming error resulting in undefined behavior such as a program <p>The <code>try_mutex</code> class is a model of <a href="mutex_concept.html#TryMutex-concept">TryMutex</a>
crash.</p> and <a href="overview.html#non-copyable">NonCopyable</a>, and provides no additional
<hr> facilities beyond the requirements of these concepts.</p>
<h4><a name="class-try_mutex-synopsis"></a>Class <code>try_mutex</code> synopsis</h4>
<h2>Class <a name="try_mutex Synopsis">try_mutex Synopsis</a></h2>
<pre> <pre>
namespace boost namespace boost
{ {
class try_mutex : private boost::noncopyable // Exposition only. class try_mutex : private <a href="../../utility/utility.htm">boost::noncopyable</a> // Exposition only.
// Class try_mutex meets the <a href= // Class try_mutex meets the <a href="overview.html#non-copyable">NonCopyable</a> requirement.
"overview.html#NonCopyable">NonCopyable</a> requirement.
{ {
public: Public:
typedef <i>[implementation defined; see <a href= typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_lock;
"#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_try_lock;
try_mutex(); try_mutex();
~try_mutex(); ~try_mutex();
}; };
} };
</pre> </pre>
<h4><a name="class-try_mutex-ctors"></a>Class <code>try_mutex</code> constructors
<h2>Class <a name="try_mutex Members">try_mutex Members</a></h2> and destructor</h4>
<hr>
<h3>Constructor</h3>
<pre> <pre>
try_mutex(); try_mutex();
</pre> </pre>
<dl class="function-semantics">
<p><b>Postconditions:</b> <code>*this</code> is in the unlocked <dt><b>Postconditions:</b> <code>*this</code> is in an unlocked state.</dt>
state.</p> </dl>
<hr>
<h3>Destructor</h3>
<pre> <pre>
~try_mutex(); ~try_mutex();
</pre> </pre>
<dl class="function-semantics">
<p><b>Requires:</b> <code>*this</code> is in the unlocked state.</p> <dt><b>Requires:</b> <code>*this</code> is in an unlocked sate.</dt>
<dt><b>Danger:</b> Destruction of a locked mutex is a serious programming error
<p><b>Effects:</b> Destroys <code>*this</code>.</p> resulting in undefined behavior such as a program crash.</dt>
</dl>
<p><b>Dangers:</b> Destruction of a locked mutex is a serious <h3><a name="class-timed_mutex"></a>Class <code>timed_mutex</code></h3>
programming error resulting in undefined behavior such as a program <p>The <code>timed_mutex</code> class is a model of <a href="mutex_concept.html#TimedMutex-concept">TimedMutex</a>
crash.</p> and <a href="overview.html#non-copyable">NonCopyable</a>, and provides no additional
<hr> facilities beyond the requirements of these concepts.</p>
<h4><a name="class-timed_mutex-synopsis"></a>Class <code>timed_mutex</code> synopsis</h4>
<h2>Class <a name="timed_mutex Synopsis">timed_mutex Synopsis</a></h2>
<pre> <pre>
namespace boost namespace boost
{ {
class timed_mutex : private boost::noncopyable // Exposition only. class timed_mutex : private <a href="../../utility/utility.htm">boost::noncopyable</a> // Exposition only.
// Class timed_mutex meets the <a href= // Class timed_mutex meets the <a href="overview.html#non-copyable">NonCopyable</a> requirement.
"overview.html#NonCopyable">NonCopyable</a> requirement.
{ {
public: Public:
typedef <i>[implementation defined; see <a href= typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_lock;
"#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= typedef <i>[implementation defined; see <a href="#Introduction">Introduction</a>]</i> scoped_timed_lock;
"#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();
~timed_mutex(); ~timed_mutex();
}; };
} };
</pre> </pre>
<h4><a name="class-timed_mutex-ctors"></a>Class <code>timed_mutex</code> constructors
<h2>Class <a name="timed_mutex Members">timed_mutex Members</a></h2> and destructor</h4>
<hr>
<h3>Constructor</h3>
<pre> <pre>
timed_mutex(); timed_mutex();
</pre> </pre>
<dl class="function-semantics">
<p><b>Postconditions:</b> <code>*this</code> is in the unlocked <dt><b>Postconditions:</b> <code>*this</code> is in an unlocked state.</dt>
state.</p> </dl>
<hr>
<h3>Destructor</h3>
<pre> <pre>
~timed_mutex(); ~timed_mutex();
</pre> </pre>
<dl class="function-semantics">
<p><b>Requires:</b> <code>*this</code> is in the unlocked state.</p> <dt><b>Requires:</b> <code>*this</code> is in an unlocked sate.</dt>
<dt><b>Danger:</b> Destruction of a locked mutex is a serious programming error
<p><b>Effects:</b> Destroys <code>*this</code>.</p> resulting in undefined behavior such as a program crash.</dt>
</dl>
<p><b>Dangers:</b> Destruction of a locked mutex is a serious <h2><a name="examples"></a>Example(s)</h2>
programming error resulting in undefined behavior such as a program
crash.</p>
<hr>
<h2><a name="Example">Example</a> Usage</h2>
<pre> <pre>
#include <a href= #include <a href=
"../../../boost/thread/mutex.hpp">&lt;boost/thread/mutex.hpp&gt;</a> "../../../boost/thread/mutex.hpp">&lt;boost/thread/mutex.hpp&gt;</a>
@@ -320,7 +244,7 @@ private:
counter c; counter c;
void change_count(void*) void change_count()
{ {
int i = c.increment(); int i = c.increment();
boost::mutex::scoped_lock scoped_lock(io_mutex); boost::mutex::scoped_lock scoped_lock(io_mutex);
@@ -332,28 +256,33 @@ int main(int, char*[])
const int num_threads = 4; const int num_threads = 4;
boost::thread_group thrds; boost::thread_group thrds;
for (int i=0; i &lt; num_threads; ++i) for (int i=0; i &lt; num_threads; ++i)
thrds.create_thread(&amp;change_count, 0); thrds.create_thread(&amp;change_count);
thrds.join_all(); thrds.join_all();
return 0; return 0;
} }
</pre> </pre>
<p>The output is:</p>
<p>The output is:</p>
<pre> <pre>
count == 1 count == 1
count == 2 count == 2
count == 3 count == 3
count == 4 count == 4
</pre> </pre>
<hr> <hr>
<p>Revised
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p> 05 November, 2001
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com"> </p>
William E. Kempf</a> 2001 all rights reserved.</i></p> <p><i>&copy; Copyright <a href="mailto:wekempf@cox.net">William E. Kempf</a> 2001-2002.
</body> All Rights Reserved.</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>
</html> </html>

View File

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

116
doc/once.html Normal file
View File

@@ -0,0 +1,116 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../../../boost.css">
<title>Boost.Threads - Header &lt;boost/thread/once.hpp&gt;</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Header &lt;<a href="../../../boost/thread/once.hpp">boost/thread/once.hpp</a>&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#macros">Macros</a></dt>
<dl class="page-index">
<dt><a href="#macro-BOOST_ONCE_INIT">BOOST_ONCE_INIT</a></dt>
</dl>
<dt><a href="#types">Types</a></dt>
<dl class="page-index">
<dt><a href="#type-once_flag">once_flag</a></dt>
</dl>
<dt><a href="#functions">Functions</a></dt>
<dl class="page-index">
<dt><a href="#function-call_once">call_once</a></dt>
</dl>
<dt><a href="#examples">Example(s)</a></dt>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p>Include the header &lt;<a href="../../../boost/thread/once.hpp">boost/thread/once.hpp</a>&gt;
to define the <code>call_once</code> function, <code>once_flag</code> type and
<code>BOOST_ONCE_INIT</code> constant.</p>
<p>The <code>call_once</code> function and <code>once_flag</code> type (statically
initialized to <code>BOOST_ONCE_INIT</code>) 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="macros"></a>Macros</h2>
<pre>
<a name="macro-BOOST_ONCE_INIT"></a>#define BOOST_ONCE_INIT <i>implementation defined</i>
</pre>
<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>
<h2><a name="types"></a>Types</h2>
<pre>
<a name="type-once_flag"></a>typedef <i>implementation defined</i> once_flag;
</pre>
<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>BOOST_ONCE_INIT</code>.</p>
<h2><a name="functions"></a>Functions</h2>
<pre>
<a name="function-call_once"></a>void call_once(void (*func)(), once_flag& flag);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> The function <code>func</code> shall not throw exceptions.</dt>
<dt><b>Effects:</b> As if (in an atomic fashion):
<pre>
if (flag == BOOST_ONCE_INIT)
func();
</pre>
</dt>
<dt><b>Postconditions:</b> <code>flag != BOOST_ONCE_INIT</code></dt>
</dl>
<h2><a name="examples"></a>Example(s)</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:wekempf@cox.net">William E. Kempf</a> 2001-2002.
All Rights Reserved.</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>
</html>

View File

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

View File

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

View File

@@ -1,311 +1,226 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content= <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
"text/html; charset=iso-8859-1"> <link rel="stylesheet" type="text/css" href="../../../boost.css">
<meta name="keywords" content="threads, BTL, thread library, C++"> <title>Boost.Threads - Header &lt;boost/thread/recursive_mutex.hpp&gt;</title>
<link rel="stylesheet" type="text/css" href="styles.css"> </head>
<body link="#0000ff" vlink="#800080">
<title>Boost.Threads, recursive_mutex</title> <table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
</head> "header">
<tr>
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080"> <td valign="top" width="300">
<table summary="header" border="0" cellpadding="7" cellspacing="0" width="100%"> <h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
<tr> </td>
<td valign="top" width="300"> <td valign="top">
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width= <h1 align="center">Boost.Threads</h1>
"277" height="86"></h3> <h2 align="center">Header &lt;<a href="../../../boost/thread/recursive_mutex.hpp">boost/thread/recursive_mutex.hpp</a>&gt;</h2> </td>
</td> </tr>
</table>
<td valign="top"> <hr>
<h1 align="center">Boost.Threads</h1> <h2>Contents</h2>
<dl class="page-index">
<h2 align="center">recursive_mutex<br> <dt><a href="#introduction">Introduction</a></dt>
recursive_try_mutex<br> <dt><a href="#classes">Classes</a></dt>
recursive_timed_mutex</h2> <dl class="page-index">
</td> <dt><a href="#class-recursive_mutex">Class <code>recursive_mutex</code></a></dt>
</tr> <dl class="page-index">
</table> <dt><a href="#class-recursive_mutex-synopsis">Class <code>recursive_mutex</code>
<hr> synopsis</a></dt>
<dt><a href="#class-recursive_mutex-ctors">Class <code>recursive_mutex</code>
<p><a href="#Introduction">Introduction</a><br> constructors and destructor</a></dt>
<a href="#Header">Header</a><br> </dl>
<a href="#recursive_mutex Synopsis">Class recursive_mutex <dt><a href="#class-recursive_try_mutex">Class <code>recursive_try_mutex</code></a></dt>
Synopsis</a><br> <dl class="page-index">
<a href="#recursive_mutex Members">Class recursive_mutex <dt><a href="#class-recursive_try_mutex-synopsis">Class <code>recursive_try_mutex</code>
Members</a><br> synopsis</a></dt>
<a href="#recursive_try_mutex Synopsis">Class recursive_try_mutex <dt><a href="#class-recursive_try_mutex-ctors">Class <code>recursive_try_mutex</code>
Synopsis</a><br> constructors and destructor</a></dt>
<a href="#recursive_try_mutex Members">Class recursive_try_mutex </dl>
Members</a><br> <dt><a href="#class-recursive_timed_mutex">Class <code>recursive_timed_mutex</code></a></dt>
<a href="#recursive_timed_mutex Synopsis">Class recursive_timed_mutex <dl class="page-index">
Synopsis</a><br> <dt><a href="#class-recursive_timed_mutex-synopsis">Class <code>recursive_timed_mutex</code>
<a href="#recursive_timed_mutex Members">Class recursive_timed_mutex synopsis</a></dt>
Members</a><br> <dt><a href="#class-recursive_timed_mutex-ctors">Class <code>recursive_timed_mutex</code>
<a href="#Example">Example</a></p> constructors and destructor</a></dt>
</dl>
<h2><a name="Introduction">Introduction</a></h2> </dl>
<dt><a href="#examples">Example(s)</a></dt>
<p>The <code>recursive_mutex</code>, <code>recursive_try_mutex</code> </dl>
and <code>recursive_timed_mutex</code> classes define full featured <hr>
models of the <a href="mutex_concept.html#Mutex">Mutex</a>, <a href= <h2><a name="introduction"></a>Introduction</h2>
"mutex_concept.html#TryMutex">TryMutex</a> and <a href= <p>Include the header &lt;<a href="../../../boost/thread/recursive_mutex.hpp">boost/thread/recursive_mutex.hpp</a>&gt;
"mutex_concept.html#TimedMutex">TimedMutex</a> concepts with recursive to define the <a href="#class-recursive_mutex">recursive_mutex</a>, <a href="#class-recursive_try_mutex">recursive_try_mutex</a>
locking semantics. These types should be used to synchronize access to and <a href="#class-recursive_timed_mutex">recursive_timed_mutex</a> classes.</p>
shared resources when recursive locking by a single thread is likely to <p>The <a href="#class-recursive_mutex">recursive_mutex</a>, <a href="#class-recursive_try_mutex">recursive_try_mutex</a>
occur. A good example for this is when a class supplies &quot;internal and <a href="#class-recursive_timed_mutex">recursive_timed_mutex</a> classes
synchronization&quot; to ensure <a href="definitions.html#Thread-safe"> are models of <a href="mutex_concept.html#Mutex-concept">Mutex</a>, <a href="mutex_concept.html#TryMutex-concept">TryMutex</a>,
thread-safety</a> and a function of the class may have to call other and <a href="mutex_concept.html#TimedMutex-concept">TimedMutex</a> respectively.
functions of the class which also attempt to lock the mutex. For These types should be used to synchronize access to shared resources when recursive
recursive locking mechanics, see <a href="mutex.html">mutexes</a>.</p> 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">
<p>Each class supplies one or more typedefs for lock types which model thread-safety</a> and a function of the class may have to call other functions
matching lock concepts. For the best possible performance you should of the class which also attempt to lock the mutex. For recursive locking mechanics,
use the mutex class that supports the minimum set of lock types that see <a href="mutex.html">mutexes</a>.</p>
you need.</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
<table summary="lock types" border="1" cellpadding="5"> that supports the minimum set of lock types that you need.</p>
<tr> <table summary="lock types" border="1" cellpadding="5">
<td><b>Mutex Class</b></td> <tr>
<td><b>Mutex Class</b></td>
<td><b>Lock name</b></td> <td><b>Lock name</b></td>
<td><b>Lock Concept</b></td>
<td><b>Implementation defined Lock Type</b></td> </tr>
<tr>
<td><b>Lock Concept</b></td> <td valign="top"><a href="#recursive_mutex Synopsis"><code> recursive_mutex</code></a></td>
</tr> <td valign="middle"><code>scoped_lock</code></td>
<td valign="middle"><a href="lock_concept.html#ScopedLock"> ScopedLock</a></td>
<tr> </tr>
<td valign="top"><a href="#recursive_mutex Synopsis"><code> <tr>
recursive_mutex</code></a></td> <td valign="top"><code><a href="#recursive_try_mutex Synopsis"> recursive_try_mutex</a></code></td>
<td valign="middle"><code>scoped_lock<br>
<td valign="middle"><code>scoped_lock</code></td> scoped_try_lock</code></td>
<td valign="middle"><a href="lock_concept.html#ScopedLock"> ScopedLock</a><br>
<td valign="middle"><a href="scoped_lock.html"><code> <a href="lock_concept.html#ScopedTryLock"> ScopedTryLock</a></td>
detail::thread::scoped_lock&lt;recursive_mutex&gt;</code></a></td> </tr>
<tr>
<td valign="middle"><a href="lock_concept.html#ScopedLock"> <td valign="top"><code><a href=
ScopedLock</a></td> "#recursive_timed_mutex Synopsis"> recursive_timed_mutex</a></code>
</tr> </td>
<td valign="middle"><code>scoped_lock<br>
<tr> scoped_try_lock<br>
<td valign="top"><code><a href="#recursive_try_mutex Synopsis"> scoped_timed_lock</code></td>
recursive_try_mutex</a></code></td> <td valign="middle"><a href="lock_concept.html#ScopedLock"> ScopedLock</a><br>
<a href="lock_concept.html#ScopedTryLock"> ScopedTryLock</a><br>
<td valign="middle"><code>scoped_lock<br> <a href="lock_concept.html#ScopedTimedLock"> ScopedTimedLock</a></td>
scoped_try_lock</code></td> </tr>
</table>
<td valign="middle"><a href="scoped_lock.html"><code> <p>The <code>recursive_mutex</code>, <code>recursive_try_mutex</code> and <code>recursive_timed_mutex</code>
detail::thread::scoped_lock&lt;recursive_try_mutex&gt;<br> employ a <code>Recursive</code> <a href="mutex_concept.html#LockingStrategies">locking
</code></a> <code><a href="scoped_try_lock.html"> strategy</a>, so attempts to recursively lock them succeed and an internal &quot;lock
detail::thread::scoped_try_lock&lt;recursive_try_mutex&gt;</a></code></td> count&quot; is maintained. Attempts to unlock them by a thread that does not
own a lock on them will result in <b>undefined behavior</b>.</p>
<td valign="middle"><a href="lock_concept.html#ScopedLock"> <p>The <code>recursive_mutex</code>, <code>recursive_try_mutex</code> and <code>recursive_timed_mutex</code>
ScopedLock</a><br> leave the <a href=
<a href="lock_concept.html#ScopedTryLock"> "mutex_concept.html#SchedulingPolicies">scheduling policy</a> as <code>
ScopedTryLock</a></td> Unspecified</code>. Programmers should assume that threads waiting for a lock
</tr> 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>
<tr> <h2><a name="classes"></a>Classes</h2>
<td valign="top"><code><a href= <h3><a name="class-recursive_mutex"></a>Class <code>recursive_mutex</code></h3>
"#recursive_timed_mutex Synopsis"> <p>The <code>recursive_mutex</code> class is a model of <a href="mutex_concept.html#Mutex-concept">Mutex</a>
recursive_timed_mutex</a></code> </td> and <a href="overview.html#non-copyable">NonCopyable</a>, and provides no additional
facilities beyond the requirements of these concepts.</p>
<td valign="middle"><code>scoped_lock<br> <h4><a name="class-recursive_mutex-synopsis"></a>Class <code>recursive_mutex</code>
scoped_try_lock<br> synopsis</h4>
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> <pre>
namespace boost namespace boost
{ {
class recursive_mutex : private <a href= class recursive_mutex : private boost::noncopyable // Exposition only.
"../../utility/utility.htm">boost::noncopyable</a> // Exposition only. // Class recursive_mutex meets the NonCopyable requirement.
// 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: public:
typedef <i>[implementation defined; see <a href= typedef [implementation defined; see Introduction] scoped_lock;
"#Introduction">Introduction</a>]</i> scoped_lock;
typedef <i>[implementation defined; see <a href= recursive_mutex();
"#Introduction">Introduction</a>]</i> scoped_try_lock; ~recursive_mutex();
recursive_try_mutex();
~recursive_try_mutex();
}; };
} };
</pre> </pre>
<h4><a name="class-recursive_mutex-ctors"></a>Class <code>recursive_mutex</code>
<h2>Class <a name="recursive_try_mutex Members">recursive_try_mutex constructors and destructor</h4>
Members</a></h2>
<hr>
<h3>Constructor</h3>
<pre> <pre>
recursive_try_mutex(); recursive_mutex();
</pre> </pre>
<dl class="function-semantics">
<p><b>Postconditions:</b> <code>*this</code> is in the unlocked <dt><b>Postconditions:</b> <code>*this</code> is in an unlocked state.</dt>
state.</p> </dl>
<hr>
<h3>Destructor</h3>
<pre> <pre>
~recursive_try_mutex(); ~recursive_mutex();
</pre> </pre>
<dl class="function-semantics">
<p><b>Requires:</b> <code>*this</code> is in the unlocked state.</p> <dt><b>Requires:</b> <code>*this</code> is in an unlocked sate.</dt>
<dt><b>Danger:</b> Destruction of a locked mutex is a serious programming error
<p><b>Effects:</b> Destroys <code>*this</code>.</p> resulting in undefined behavior such as a program crash.</dt>
</dl>
<p><b>Dangers:</b> Destruction of a locked mutex is a serious <h3><a name="class-recursive_try_mutex"></a>Class <code>recursive_try_mutex</code></h3>
programming error resulting in undefined behavior such as a program <p>The <code>recursive_try_mutex</code> class is a model of <a href="mutex_concept.html#TryMutex-concept">TryMutex</a>
crash..</p> and <a href="overview.html#non-copyable">NonCopyable</a>, and provides no additional
<hr> facilities beyond the requirements of these concepts.</p>
<h4><a name="class-recursive_try_mutex-synopsis"></a>Class <code>recursive_try_mutex</code>
<h2>Class <a name="recursive_timed_mutex Synopsis"> synopsis</h4>
recursive_timed_mutex Synopsis</a></h2> <pre>
namespace boost
{
class recursive_mutex : private boost::noncopyable // Exposition only.
// Class recursive_mutex meets the NonCopyable requirement.
{
Public:
typedef [implementation defined; see Introduction] scoped_lock;
typedef [implementation defined; see Introduction] scoped_try_lock;
recursive_try_mutex();
~recursive_try_mutex();
};
};
</pre>
<h4><a name="class-recursive_try_mutex-ctors"></a>Class <code>recursive_try_mutex</code>
constructors and destructor</h4>
<pre>
recursive_try_mutex();
</pre>
<dl class="function-semantics">
<dt><b>Postconditions:</b> <code>*this</code> is in an unlocked state.</dt>
</dl>
<pre>
~recursive_try_mutex();
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>*this</code> is in an unlocked sate.</dt>
<dt><b>Danger:</b> Destruction of a locked mutex is a serious programming error
resulting in undefined behavior such as a program crash.</dt>
</dl>
<h3><a name="class-recursive_timed_mutex"></a>Class <code>recursive_timed_mutex</code></h3>
<p>The <code>recursive_timed_mutex</code> class is a model of <a href="mutex_concept.html#TimedMutex-concept">TimedMutex</a>
and <a href="overview.html#non-copyable">NonCopyable</a>, and provides no additional
facilities beyond the requirements of these concepts.</p>
<h4><a name="class-recursive_timed_mutex-synopsis"></a>Class <code>recursive_timed_mutex</code>
synopsis</h4>
<pre> <pre>
namespace boost namespace boost
{ {
class recursive_timed_mutex : private boost::noncopyable // Exposition only. class recursive_timed_mutex : private boost::noncopyable // Exposition only.
// Class recursive_timed_mutex meets the <a href= // Class recursive_mutex meets the NonCopyable requirement.
"overview.html#NonCopyable">NonCopyable</a> requirement.
{ {
public: Public:
typedef <i>[implementation defined; see <a href= typedef [implementation defined; see Introduction] scoped_lock;
"#Introduction">Introduction</a>]</i> scoped_lock; typedef [implementation defined; see Introduction] scoped_try_lock;
typedef <i>[implementation defined; see <a href= typedef [implementation defined; see Introduction] scoped_timed_lock;
"#Introduction">Introduction</a>]</i> scoped_try_lock;
typedef <i>[implementation defined; see <a href= recursive_timed_mutex();
"#Introduction">Introduction</a>]</i> scoped_timed_lock; ~recursive_timed_mutex();
recursive_timed_mutex();
~recursive_timed_mutex();
}; };
} };
</pre> </pre>
<h4><a name="class-recursive_timed_mutex-ctors"></a>Class <code>recursive_timed_mutex</code>
<h2>Class <a name="recursive_timed_mutex Members">recursive_timed_mutex constructors and destructor</h4>
Members</a></h2>
<hr>
<h3>Constructor</h3>
<pre> <pre>
recursive_timed_mutex(); recursive_timed_mutex();
</pre> </pre>
<dl class="function-semantics">
<p><b>Postconditions:</b> <code>*this</code> is in the unlocked <dt><b>Postconditions:</b> <code>*this</code> is in an unlocked state.</dt>
state.</p> </dl>
<hr>
<h3>Destructor</h3>
<pre> <pre>
~recursive_timed_mutex(); ~recursive_timed_mutex();
</pre> </pre>
<dl class="function-semantics">
<p><b>Requires:</b> <code>*this</code> is in the unlocked state.</p> <dt><b>Requires:</b> <code>*this</code> is in an unlocked sate.</dt>
<dt><b>Danger:</b> Destruction of a locked mutex is a serious programming error
<p><b>Effects:</b> Destroys <code>*this</code>.</p> resulting in undefined behavior such as a program crash.</dt>
</dl>
<p><b>Dangers:</b> Destruction of a locked mutex is a serious <h2><a name="examples"></a>Example(s)</h2>
programming error resulting in undefined behavior such as a program
crash..</p>
<hr>
<h2><a name="Example">Example</a> Usage</h2>
<pre> <pre>
#include <a href= #include <a href="../../../boost/thread/recursive_mutex.hpp">&lt;boost/thread/recursive_mutex.hpp&gt;</a>
"../../../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 <a href=
"../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
#include &lt;iostream&gt; #include &lt;iostream&gt;
class counter class counter
@@ -348,21 +263,26 @@ int main(int, char*[])
return 0; return 0;
} }
</pre> </pre>
<p>The output is:</p>
<p>The output is:</p>
<pre> <pre>
count == 1 count == 1
count == 2 count == 2
count == 3 count == 3
count == 4 count == 4
</pre> </pre>
<hr> <hr>
<p>Revised
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p> 05 November, 2001
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com"> </p>
William E. Kempf</a> 2001 all rights reserved.</i></p> <p><i>&copy; Copyright <a href="mailto:wekempf@cox.net">William E. Kempf</a> 2001-2002.
</body> All Rights Reserved.</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>
</html> </html>

View File

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

View File

@@ -1,92 +1,96 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content= <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
"text/html; charset=iso-8859-1"> <link rel="stylesheet" type="text/css" href="../../../boost.css">
<meta name="keywords" content= <title>Boost.Threads - &lt;boost/thread.hpp&gt;</title>
"threads, Boost.Threads, thread library, C++"> </head>
<link rel="stylesheet" type="text/css" href="styles.css"> <body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
<title>Boost.Threads, thread</title> "header">
</head> <tr>
<td valign="top" width="300">
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080"> <h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
<table summary="header" border="0" cellpadding="7" cellspacing="0" </td>
width="100%"> <td valign="top">
<tr> <h1 align="center">Boost.Threads</h1>
<td valign="top" width="300"> <h2 align="center">Header &lt;<a href="../../../boost/thread/thread.hpp">boost/thread.hpp</a>&gt;</h2>
<h3><img height="86" alt="C++ Boost" src= </td>
"../../../c++boost.gif" width="277"></h3> </tr>
</td> </table>
<hr>
<td valign="top"> <h2>Contents</h2>
<h1 align="center">Boost.Threads</h1> <dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<h2 align="center">Class thread</h2> <dt><a href="#classes">Classes</a></dt>
</td> <dl class="page-index">
</tr> <dt><a href="#class-thread">Class <code>thread</code></a></dt>
</table> <dl class="page-index">
<hr> <dt><a href="#class-thread-synopsis">Class <code>thread</code> synopsis</a></dt>
<dt><a href="#class-thread-ctors">Class <code>thread</code> constructors
<p><a href="#Introduction">Introduction</a><br> and destructor</a></dt>
<a href="#Header">Header</a><br> <dt><a href="#class-thread-comparisons">Class <code>thread</code> comparison
<a href="#Synopsis">Synopsis</a><br> functions</a></dt>
<a href="#Members">Members</a><br> <dt><a href="#class-thread-modifiers">Class <code>thread</code> modifier
<a href="#Example">Example</a></p> functions</a></dt>
<dt><a href="#class-thread-statics">Class <code>thread</code> static functions</a></dt>
<h2><a name="Introduction">Introduction</a></h2> </dl>
<dt><a href="#class-thread_group">Class <code>thread_group</code></a></dt>
<p>The <code>thread</code> class represents threads of execution, and <dl class="page-index">
provides the functionality to create and manage threads within the <b> <dt><a href="#class-thread_group-synopsis">Class <code>thread_group</code>
Boost.Threads</b> library. See <a href="definitions.html"> synopsis</a></dt>
Definitions</a> for a precise description of &quot;thread of <dt><a href="#class-thread_group-ctors">Class <code>thread_group</code>
execution&quot;, and for definitions of threading related terms and of constructors and destructor</a></dt>
thread states such as &quot;blocked&quot;.</p> <dt><a href="#class-thread_group-modifiers">Class <code>thread_group</code>
modifier functions</a></dt>
<p>A thread of execution has an initial function. For the program&#39;s </dl>
initial thread, the initial function is <code>main()</code>. For other </dl>
threads, the initial function is <code>operator()</code> of the <dt><a href="#examples">Example(s)</a></dt>
function object passed to the class <code>thread</code> <dl class="page-index">
constructor.</p> <dt><a href="#example-thread">Simple usage of <code>boost::thread</code></a></dt>
<dt><a href="#example-thread_group">Simple usage of <code>boost::thread_group</code></a></dt>
<p>A thread of execution is said to be &quot;finished&quot; or </dl>
&quot;finished execution&quot; when its initial function returns or is </dl>
terminated. This includes completion of all thread cleanup handlers, <hr>
and completion of the normal C++ function return behaviors, such as <h2><a name="introduction"></a>Introduction</h2>
destruction of automatic storage (stack) objects and releasing any <p>The header &lt;<a href="../../../boost/thread/thread.hpp">boost/thread.hpp</a>&gt;
associated implementation resources.</p> defines the classes <a href="#class-thread">thread</a> and <a href="#class-thread_group">thread_group</a>
which are used to create, observe and manage threads and groups of threads.</p>
<p>A thread object has an associated state which is either <h2><a name="classes"></a>Classes</h2>
&quot;joinable&quot; or &quot;non-joinable&quot;.</p> <h3><a name="class-thread"></a>Class <code>thread</code></h3>
<p>The <code>thread</code> class represents threads of execution, and provides
<p>Except as described below, the policy used by an implementation of the functionality to create and manage threads within the <b> Boost.Threads</b>
<b>Boost.Threads</b> to schedule transitions between thread states is library. See <a href="definitions.html"> Definitions</a> for a precise description
unspecified.</p> of &quot;thread of execution&quot;, and for definitions of threading related
terms and of thread states such as &quot;blocked&quot;.</p>
<p><b>Note:</b> Just as the lifetime of a file may be different from <p>A thread of execution has an initial function. For the program&#39;s initial
the lifetime of an iostream object which represents the file, the thread, the initial function is <code>main()</code>. For other threads, the
lifetime of a thread of execution may be different from the <code> initial function is <code>operator()</code> of the function object passed to
thread</code> object which represents the thread of execution. In the class <code>thread</code> constructor.</p>
particular, after a call to <code>join()</code>, the thread of <p>A thread of execution is said to be &quot;finished&quot; or &quot;finished
execution will no longer exist even though the <code>thread</code> execution&quot; when its initial function returns or is terminated. This includes
object continues to exist until the end of its normal lifetime. The completion of all thread cleanup handlers, and completion of the normal C++
converse is also possible; if a <code>thread</code> object is destroyed function return behaviors, such as destruction of automatic storage (stack)
without <code>join()</code> having first been called, the thread of objects and releasing any associated implementation resources.</p>
execution continues until its initial function completes.</p> <p>A thread object has an associated state which is either &quot;joinable&quot;
or &quot;non-joinable&quot;.</p>
<h2><a name="Header">Header</a></h2> <p>Except as described below, the policy used by an implementation of <b>Boost.Threads</b>
<pre> to schedule transitions between thread states is unspecified.</p>
#include <a href= <p><b>Note:</b> Just as the lifetime of a file may be different from the lifetime
"../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a> of an iostream object which represents the file, the lifetime of a thread of
</pre> 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>,
<h2><a name="Synopsis">Synopsis</a></h2> 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>
<h4><a name="class-thread-synopsis"></a>Class <code>thread</code> synopsis</h4>
<pre> <pre>
namespace boost { namespace boost {
class thread : <a href= class thread : <a href=
"../../utility/utility.htm#noncopyable">boost::noncopyable</a> // Exposition only. "../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
// Class thread meets the <a href= // Class thread meets the <a href=
"overview.html#NonCopyable">NonCopyable</a> requirement. "overview.html#non-copyable">NonCopyable</a> requirement.
{ {
public: public:
thread(); thread();
@@ -101,119 +105,185 @@ public:
static void sleep(const xtime&amp; xt); static void sleep(const xtime&amp; xt);
static void yield(); static void yield();
}; };
} // namespace boost } // namespace boost
</pre> </pre>
<h4><a name="class-thread-ctors"></a>Class <code>thread</code> constructors and
<h2><a name="Members">Members</a></h2> destructor</h4>
<hr>
<h3>Constructors</h3>
<pre> <pre>
thread(); thread();
</pre> </pre>
<dl class="function-semantics">
<p><b>Effects:</b> Constructs a <code>thread</code> object representing <dt><b>Effects:</b> Constructs a <code>thread</code> object representing the
the current thread of execution.</p> current thread of execution.</dt>
<dt><b>Postconditions:</b> <code>*this</code> is non-joinable.</dt>
<p><b>Postcondition:</b> <code>*this</code> is non-joinable.</p> <dt><b>Danger:</b> <code>*this</code> is valid only within the current thread.</dt>
</dl>
<p><b>Danger:</b> <code>*this</code> is valid only within the current
thread.</p>
<pre> <pre>
thread(const <a href= thread(const <a href="../../function/index.html">boost::function0</a>&lt;void&gt;&amp; threadfunc);
"../../function/index.html">boost::function0</a>&lt;void&gt;&amp; threadfunc);
</pre> </pre>
<dl class="function-semantics">
<p><b>Effects:</b> Starts a new thread of execution and constructs a <dt><b>Effects:</b> Starts a new thread of execution and constructs a <code>thread</code>
<code>thread</code> object representing it. Copies <code> object representing it. Copies <code> threadfunc</code> (which in turn copies
threadfunc</code> (which in turn copies the function object wrapped by the function object wrapped by <code>threadfunc</code>) to an internal location
<code>threadfunc</code>) to an internal location which persists for the which persists for the lifetime of the new thread of execution. Calls <code>operator()</code>
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
on the copy of the <code>threadfunc</code> function object in the new of execution.</dt>
thread of execution.</p> <dt><b>Postconditions:</b> <code>*this</code> is joinable.</dt>
<dt><b>Throws:</b> <code>boost::thread_resource_error</code> if a new thread
<p><b>Postcondition:</b> <code>*this</code> is joinable.</p> of execution cannot be started.</dt>
</dl>
<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> <pre>
~thread(); ~Thread();
</pre> </pre>
<dl class="function-semantics">
<p><b>Effects:</b> Destroys <code>*this</code>. The actual thread of <dt><b>Effects:</b> Destroys <code>*this</code>. The actual thread of execution
execution may continue to execute after the <code>thread</code> object may continue to execute after the <code>thread</code> object has been destroyed.</dt>
has been destroyed.</p> <dt><b>Note:</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
<p><b>Notes:</b> If <code>*this</code> is joinable the actual thread of when the thread of execution completes. To ensure such a thread of execution
execution becomes &quot;detached&quot;. Any resources used by the runs to completion before the <code> thread</code> object is destroyed, call
thread will be reclaimed when the thread of execution completes. To <code>join()</code>.</dt>
ensure such a thread of execution runs to completion before the <code> </dl>
thread</code> object is destroyed, call <code>join()</code>.</p> <h4><a name="class-thread-comparisons"></a>Class <code>thread</code> comparison
<hr> functions</h4>
<h3>Comparison Operators</h3>
<pre> <pre>
bool operator==(const thread&amp; rhs); bool operator==(const thread&amp; rhs) const;
</pre> </pre>
<dl class="function-semantics">
<p><b>Requires:</b> The thread is non-terminated or <code>*this</code> <dt><b>Requires:</b> The thread is non-terminated or <code>*this</code> is joinable.</dt>
is joinable.</p> <dt><b>Returns:</b> <code>true</code> if <code>*this</code> and <code> rhs</code>
represent the same thread of execution.</dt>
<p><b>Returns:</b> <code>true</code> if <code>*this</code> and <code> </dl>
rhs</code> represent the same thread of execution.</p>
<pre> <pre>
bool operator!=(const thread&amp; rhs); bool operator!=(const thread&amp; rhs) const;
</pre> </pre>
<dl class="function-semantics">
<p><b>Returns:</b> <code>!(*this==rhs)</code>.</p> <dt><b>Requires:</b> The thread is non-terminated or <code>*this</code> is joinable.</dt>
<hr> <dt><b>Returns:</b> <code>!(*this==rhs)</code>.</dt>
</dl>
<h3>join</h3> <h4><a name="class-thread-modifiers"></a>Class <code>thread</code> modifier functions</h4>
<pre> <pre>
void join(); void join();
</pre> </pre>
<dl class="function-semantics">
<p><b>Requires:</b> <code>*this</code> is joinable.</p> <dt><b>Requires:</b> <code>*this</code> is joinable.</dt>
<dt><b>Effects:</b> The current thread of execution blocks until the initial
<p><b>Effects:</b> The current thread of execution blocks until the function of the thread of execution represented by <code> *this</code> finishes
initial function of the thread of execution represented by <code> and all resources are reclaimed.</dt>
*this</code> finishes and all resources are reclaimed.</p> <dt><b>Postconditions:</b> <code>*this</code> is non-joinable.</dt>
<dt><b>Notes:</b> If <code>*this == thread()</code> the result is implementation
<p><b>Postcondition:</b> <code>*this</code> is non-joinable.</p> defined. If the implementation doesn&#39;t detect this the result will be
<a href="definitions.html#Deadlock"> deadlock</a>.</dt>
<p><b>Note:</b> If <code>*this == thread()</code> the result is </dl>
implementation defined. If the implementation doesn&#39;t detect this <h4><a name="class-thread-statics"></a>Class <code>thread</code> static functions</h4>
the result will be <a href="definitions.html#Deadlock">
deadlock</a>.</p>
<hr>
<h3>sleep</h3>
<pre> <pre>
static void sleep(const <a href="xtime.html">xtime</a>&amp; xt); static void sleep(const <a href="xtime.html">xtime</a>&amp; XT);
</pre> </pre>
<dl class="function-semantics">
<p><b>Effects:</b> The current thread of execution blocks until <code> <dt><b>Effects:</b> The current thread of execution blocks until <code> XT</code>
xt</code> is reached.</p> is reached.</dt>
<hr> </dl>
<h3>yield</h3>
<pre> <pre>
static void yield(); static void yield();
</pre> </pre>
<dl class="function-semantics">
<dt><b>Effects:</b> The current thread of execution is placed in the &quot;ready&quot;
state.</dt>
<dt><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.</dt>
</dl>
<h3><a name="class-thread_group"></a>Class <code>thread_group</code></h3>
<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>
<h4><a name="class-thread_group-synopsis"></a>Class <code>thread_group</code>
synopsis</h4>
<pre>
namespace boost {
class thread_group : <a href=
"../../utility/utility.htm#Class noncopyable">boost::noncopyable</a>
{
public:
thread_group();
~thread_group();
<p><b>Effects:</b> The current thread of execution is placed in the thread* create_thread(const boost::function0&lt;void&gt;&amp; threadfunc);
&quot;ready&quot; state.</p> void add_thread(thread* thrd);
void remove_thread(thread* thrd);
<p><b>Notes:</b> Allow the current thread to give up the rest of its void join_all();
time slice (or other scheduling quota) to another thread. Particularly };
useful in non-preemptive implementations.</p> } // namespace boost
<hr> </pre>
<h4><a name="class-thread_group-ctors"></a>Class <code>thread_group</code> constructors
<h2><a name="Example">Example Usage</a></h2> and destructor</h4>
<pre>
thread_group();
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Constructs an empty <code>thread_group</code> container.</dt>
</dl>
<pre>
~thread_group();
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Destroys each contained thread object. Destroys <code>*this</code>.</dt>
<dt><b>Notes:</b> Behavior is undefined if another thread references *this during
the execution of the destructor.</dt>
</dl>
<h4><a name="class-thread_group-modifiers"></a>Class <code>thread_group</code>
modifier functions</h4>
<pre>
thread* create_thread(const boost::function0&lt;void&gt;&amp; threadfunc);
</pre>
<dl class="function-semantics">
<dt><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.</dt>
<dt><b>Returns:</b> Pointer to the newly created thread.</dt>
</dl>
<pre>
void add_thread(thread* thrd);
</pre>
<dl class="function-semantics">
<dt><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.</dt>
</dl>
<pre>
Void remove_thread(thread* thrd);
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Removes <code>*this</code>&#39;s list of managed <tt>thread</tt>
objects.</dt>
<dt><b>Throws:</b> ? if <tt>thrd</tt> is not it <code>*this</code>&#39;s list
of managed <tt>thread</tt> objects.</dt>
</dl>
<pre>
Void join_all();
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Calls <code>join()</code> on each of the managed <tt>thread</tt>
objects.</dt>
</dl>
<h2><a name="functions"></a>Functions</h2>
<pre>
<a name="function-spec"></a>{{function}}
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> {{text}}</dt>
<dt><b>Effects:</b> {{text}}</dt>
<dt><b>Postconditions:</b> {{text}}</dt>
<dt><b>Returns:</b> {{text}}</dt>
<dt><b>Throws:</b> {{text}}</dt>
<dt><b>Complexity:</b> {{text}}</dt>
<dt><b>Rationale:</b> {{text}}</dt>
</dl>
<h2><a name="objects"></a>Objects</h2>
<p><a name="object-spec"></a>{{Object specifications}}</p>
<h2><a name="examples"></a>Example(s)</h2>
<h3><a name="example-thread"></a>Simple usage of <code>boost::thread</code></h3>
<pre> <pre>
#include &lt;boost/thread/thread.hpp&gt; #include &lt;boost/thread/thread.hpp&gt;
#include &lt;iostream&gt; #include &lt;iostream&gt;
@@ -223,11 +293,11 @@ struct thread_alarm
thread_alarm(int secs) : m_secs(secs) { } thread_alarm(int secs) : m_secs(secs) { }
void operator()() void operator()()
{ {
boost::xtime xt; boost::xtime XT;
boost::xtime_get(&amp;xt, boost::TIME_UTC); boost::xtime_get(&amp;XT, boost::TIME_UTC);
xt.sec += m_secs; xt.sec += m_secs;
boost::thread::sleep(xt); boost::thread::sleep(XT);
std::cout &lt;&lt; &quot;alarm sounded...&quot; &lt;&lt; std::endl; std::cout &lt;&lt; &quot;alarm sounded...&quot; &lt;&lt; std::endl;
} }
@@ -239,23 +309,64 @@ int main(int argc, char* argv[])
{ {
int secs = 5; int secs = 5;
std::cout &lt;&lt; &quot;setting alarm for 5 seconds...&quot; &lt;&lt; std::endl; std::cout &lt;&lt; &quot;setting alarm for 5 seconds...&quot; &lt;&lt; std::endl;
boost::thread thrd(thread_alarm(secs)); thread_alarm alarm(secs);
boost::thread thrd(alarm);
thrd.join(); thrd.join();
} }
</pre> </pre>
<p>The output is:</p>
<p>The output is:</p>
<pre> <pre>
setting alarm for 5 seconds... setting alarm for 5 seconds...
alarm sounded... alarm sounded...
</pre> </pre>
<hr> <h3><a name="example-thread_group"></a>Simple usage of <code>boost::thread_group</code></h3>
<pre>
#include &lt;boost/thread/thread.hpp&gt;
#include &lt;iostream&gt;
<p>Revised int count = 0;
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p> boost::mutex mutex;
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com"> void increment_count()
William E. Kempf</a> 2001 all rights reserved.</i></p> {
</body> 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:wekempf@cox.net">William E. Kempf</a> 2001-2002.
All Rights Reserved.</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>
</html> </html>

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>

200
doc/tss.html Normal file
View File

@@ -0,0 +1,200 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../../../boost.css">
<title>Boost.Threads - Header &lt;boost/thread/tss.hpp&gt;</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Header &lt;<a href="../../../boost/thread/tss.hpp">boost/thread/tss.hpp</a>&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#classes">Classes</a></dt>
<dl class="page-index">
<dt><a href="#class-thread_specific_ptr">Class <code>thread_specific_ptr</code></a></dt>
<dl class="page-index">
<dt><a href="#class-thread_specific_ptr-synopsis">Class <code>thread_specific_ptr</code>
synopsis</a></dt>
<dt><a href="#class-thread_specific_ptr-ctors">Class <code>thread_specific_ptr</code>
constructors and destructor</a></dt>
<dt><a href="#class-thread_specific_ptr-modifiers">Class <code>thread_specific_ptr</code>
modifier functions</a></dt>
<dt><a href="#class-thread_specific_ptr-observers">Class <code>thread_specific_ptr</code>
observer functions</a></dt>
</dl>
</dl>
<dt><a href="#examples">Example(s)</a></dt>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p>The header &lt;<a href="../../../boost/thread/tss.hpp">boost/thread/tss.hpp</a>&gt;
defines the class <a href="#class-thread_specific_ptr">thread_specific_ptr</a>
which is used to manage data associated with specific thread instances.</p>
<h2><a name="classes"></a>Classes</h2>
<h3><a name="class-thread_specific_ptr"></a>Class <code>thread_specific_ptr</code></h3>
<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 originally written assuming a single thread of control
and is being ported to a multithreaded 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>
<h4><a name="class-thread_specific_ptr-synopsis"></a>Class <code>thread_specific_ptr</code>
synopsis</h4>
<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#non-copyable">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);
};
};
</pre>
<h4><a name="class-thread_specific_ptr-ctors"></a>Class <code>thread_specific_ptr</code>
constructors and destructor</h4>
<pre>
thread_specific_ptr();
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> The expression <code>delete get()</code> is well formed.</dt>
<dt><b>Postconditions:</b> A thread specific storage has been reserved for use
by <code>*this</code> in all threads, with each thread initially storing a
null pointer.</dt>
<dt><b>Throws:</b> <code>boost::thread_resource_error</code> if the necessary
resources can not be obtained.</dt>
<dt><b>Note:</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.</dt>
</dl>
<pre>
~thread_specific_ptr();
</pre>
<dl class="function-semantics">
<dt><b>Note:</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.</dt>
</dl>
<h4><a name="class-thread_specific_ptr-modifiers"></a>Class <code>thread_specific_ptr</code>
modifier functions</h4>
<pre>
T* release();
</pre>
<dl class="function-semantics">
<dt><b>Postconditions:</b> <code>*this</code> holds the null pointer for the
current thread.</dt>
<dt><b>Returns:</b> <code>this-&gt;get()</code> prior to the call.</dt>
</dl>
<pre>
void reset(T* p=0);
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> If <code>this-&gt;get()!= p</code> then <code>delete this-&gt;get()</code>.
</dt>
<dt><b>Postconditions:</b> <code>*this</code> holds the pointer <code> p</code>
for the current thread.</dt>
<dt><b>Note:</b> The pointer will be deleted when the thread terminates.</dt>
</dl>
<h4><a name="class-thread_specific_ptr-observers"></a>Class <code>thread_specific_ptr</code>
observer functions</h4>
<pre>
T* get() const;
</pre>
<dl class="function-semantics">
<dt><b>Returns:</b> The object stored in thread specific storage for the current
thread for <code>*this</code>.</dt>
<dt><b>Note:</b> Each thread initially returns 0.</dt>
</dl>
<pre>
T* operator-&gt;() const;
</pre>
<dl class="function-semantics">
<dt><b>Returns:</b> <code>this-&lt;get()</code>.</dt>
</dl>
<pre>
T& operator*() const;
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>this-&lt;get() != 0</code></dt>
<dt><b>Returns:</b> <code>this-&lt;get()</code>.</dt>
</dl>
<h2><a name="examples"></a>Example(s)</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:wekempf@cox.net">William E. Kempf</a> 2001-2002.
All Rights Reserved.</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>
</html>

View File

@@ -1,147 +1,121 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content= <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
"text/html; charset=iso-8859-1"> <link rel="stylesheet" type="text/css" href="../../../boost.css">
<meta name="keywords" content= <title>Boost.Threads - Header &lt;boost/thread/xtime.hpp&gt;</title>
"threads, Boost.Threads, thread library, C++"> </head>
<link rel="stylesheet" type="text/css" href="styles.css"> <body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
<title>Boost.Threads, xtime</title> "header">
</head> <tr>
<td valign="top" width="300">
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080"> <h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
<table summary="header" border="0" cellpadding="7" cellspacing="0" </td>
width="100%"> <td valign="top">
<tr> <h1 align="center">Boost.Threads</h1>
<td valign="top" width="300"> <h2 align="center">Header &lt;<a href="../../../boost/thread/xtime.hpp">boost/thread/xtime.hpp</a>&gt;</h2>
<h3><img src="../../../c++boost.gif" alt="C++ Boost" width= </td>
"277" height="86"></h3> </tr>
</td> </table>
<hr>
<td valign="top"> <h2>Contents</h2>
<h1 align="center">Boost.Threads</h1> <dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<h2 align="center">xtime</h2> <dt><a href="#values">Values</a></dt>
</td> <dl class="page-index">
</tr> <dt><a href="#value-spec">TIME_UTC</a></dt>
</table> </dl>
<hr> <dt><a href="#classes">Classes</a></dt>
<dl class="page-index">
<p><a href="#Introduction">Introduction</a><br> <dt><a href="#class-spec">Struct <code>xtime</code></a></dt>
<a href="#Header">Header</a><br> <dl class="page-index">
<a href="#Synopsis">Synopsis</a><br> <dt><a href="#class-xtime-synopsis">Struct <code>xtime</code> synopsis</a></dt>
<a href="#Reference">Reference</a><br> </dl>
<a href="#Example">Example</a></p> </dl>
<dt><a href="#functions">Functions</a></dt>
<h2><a name="Introduction">Introduction</a></h2> <dl class="page-index">
<dt><a href="#function-xtime_get"><code>xtime_get</code></a></dt>
<p>The <code>xtime</code> type is used to represent a point on some </dl>
time scale or a duration in time. This type may be proposed for the C <dt><a href="#examples">Example(s)</a></dt>
standard by Markus Kuhn. <b>Boost.Threads</b> provides only a very </dl>
minimal implementation of this proposal and it&#39;s expected that a <hr>
full implementation will be provided in Boost as a separate library, at <h2><a name="introduction"></a>Introduction</h2>
which time <b>Boost.Threads</b> will deprecate its implementation.</p> <p>The header &lt;<a href="../../../boost/thread/xtime.hpp">boost/thread/xtime.hpp</a>&gt;
defines functions and data types used to perform high-resolution time operations.
<h2><a name="Header">Header</a></h2> This is a temporary solution that will be replaced by a more robust time library
<pre> once available in Boost.</p>
#include <a href= <h2><a name="values"></a>Values</h2>
"../../../boost/thread/xtime.hpp">&lt;boost/thread/xtime.hpp&gt;</a> <pre><a name="value-spec"></a>
</pre>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>
namespace boost {
enum enum
{ {
TIME_UTC=1, TIME_UTC
}; }
</pre>
struct xtime <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>
<h2><a name="classes"></a>Classes</h2>
<h3><a name="class-xtime"></a>Struct <code>xtime</code></h3>
<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 (or some other time
library) will be provided in Boost as a separate library, at which time <b>Boost.Threads</b>
will deprecate its implementation.</p>
<h4><a name="class-xtime-synopsis"></a>Struct <code>xtime</code> synopsis</h4>
<pre>
namespace boost
{ {
struct xtime
{
#if defined(BOOST_NO_INT64_T) #if defined(BOOST_NO_INT64_T)
int_fast32_t sec; int_fast32_t sec;
#else #else
int_fast64_t sec; int_fast64_t sec;
#endif #endif
int_fast32_t nsec; int_fast32_t nsec;
};
}; };
int xtime_get(struct xtime* xtp, int clock_type);
} // namespace boost
</pre> </pre>
<h2><a name="functions"></a>Functions</h2>
<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> <pre>
struct xtime <a name="function-xtime_get"></a>int xtime_get(struct xtime* xtp, int clock_type);
{
#if defined(BOOST_NO_INT64_T)
int_fast32_t sec;
#else
int_fast64_t sec;
#endif
int_fast32_t nsec;
};
</pre> </pre>
<dl class="function-semantics">
<p><b>sec</b> represents the whole seconds that have passed since the <dt><b>Postconditions:</b> <code>xtp</code> represents the current point in
epoch.</p> time as a duration since the epoch specified by the <code> clock_type</code>.</dt>
<dt><b>Returns:</b> <code>clock_type</code> if successful, otherwise 0.</dt>
<p><b>nsec</b> represents the nanoseconds since <code>sec.</code></p> <dt><b>Note:</b> The resolution is implementation specific. For many implementations
<hr> 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>
<h3>xtime_get</h3> may be significant. For maximum portability, avoid durations of less than
one second.</dt>
</dl>
<h2><a name="examples"></a>Example(s)</h2>
<pre> <pre>
int xtime_get(struct xtime* xtp, int clock_type); #include <a href="../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
</pre> #include <a href="../../../boost/thread/tss.hpp">&lt;boost/thread/xtime.hpp&gt;</a>
<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[]) int main(int argc, char* argv[])
{ {
boost::xtime xt; boost::xtime xt;
boost::xtime_get(&amp;xt, boost::TIME_UTC); boost::xtime_get(&amp;XT, boost::TIME_UTC);
xt.sec += 1; xt.sec += 1;
boost::thread::sleep(xt); // Sleep for 1 second boost::thread::sleep(XT); // Sleep for 1 second
} }
</pre> </pre>
<hr> <hr>
<p>Revised
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p> 05 November, 2001
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com"> </p>
William E. Kempf</a> 2001 all rights reserved.</i></p> <p><i>&copy; Copyright <a href="mailto:wekempf@cox.net">William E. Kempf</a> 2001-2002.
</body> All Rights Reserved.</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>
</html> </html>

2
example/.cvsignore Normal file
View File

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

View File

@@ -9,58 +9,60 @@
# 1. monitor, an example program. # 1. monitor, an example program.
# 2. starvephil, an example program. # 2. starvephil, an example program.
# 3. tennis, an example program. # 3. tennis, an example program.
# Additional configuration variables used:
# 1. PTW32 may be used on Win32 platforms to specify that the pthreads-win32
# library should be used instead of "native" threads. This feature is
# mostly used for testing and it's generally recommended you use the
# native threading libraries instead. PTW32 should be set to be a list
# of two strings, the first specifying the installation path of the
# pthreads-win32 library and the second specifying which library
# variant to link against (see the pthreads-win32 documentation).
# Example: jam -sPTW32="c:\pthreads-win32 pthreadVCE.lib"
# declare the location of this subproject relative to the root # Declare the location of this subproject relative to the root.
subproject libs/thread/example ; subproject libs/thread/example ;
# Do some OS-specific setup # Include threads.jam for Boost.Threads global build information.
if $(NT) # This greatly simplifies the Jam code needed to configure the build
{ # for the various Win32 build types.
BOOST_THREADMON_LIB = <lib>../build/libboost_threadmon ; SEARCH on <module@>threads.jam = $(BOOST_ROOT)/libs/thread/build ;
} include <module@>threads.jam ;
else
{
BOOST_THREADMON_LIB = ;
}
####################### #######################
# Declare the Boost.Threads example program monitor.
# exe monitor
# Declare the Boost.Threads monitor example program. : monitor/monitor.cpp
# <lib>../build/boost_thread
$(threadmon)
exe monitor : monitor/monitor.cpp : <sysinclude>$(BOOST_ROOT)
<lib>../build/libboost_thread $(pthreads-win32)
$(BOOST_THREADMON_LIB) <threading>multi
# requirements : debug release <runtime-link>static/dynamic
: <include>$(BOOST_ROOT) ;
<threading>multi
: debug release ;
####################### #######################
# Declare the Boost.Threads example program starvephil.
# exe starvephil
# Declare the Boost.Threads starvephil example program. : starvephil/starvephil.cpp
# <lib>../build/boost_thread
$(threadmon)
exe starvephil : starvephil/starvephil.cpp : <sysinclude>$(BOOST_ROOT)
<lib>../build/libboost_thread $(pthreads-win32)
$(BOOST_THREADMON_LIB) <threading>multi
# requirements : debug release <runtime-link>static/dynamic
: <include>$(BOOST_ROOT) ;
<threading>multi
: debug release ;
####################### #######################
# Declare the Boost.Threads example program tennis.
# exe tennis
# Declare the Boost.Threads tennis example program. : tennis/tennis.cpp
# <lib>../build/boost_thread
$(threadmon)
exe tennis : tennis/tennis.cpp : <sysinclude>$(BOOST_ROOT)
<lib>../build/libboost_thread $(pthreads-win32)
$(BOOST_THREADMON_LIB) <threading>multi
# requirements : debug release <runtime-link>static/dynamic
: <include>$(BOOST_ROOT) ;
<threading>multi
: debug release ;

1
example/monitor/Carbon.r Normal file
View File

@@ -0,0 +1 @@
/*

View File

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

BIN
example/monitor/monitor.mcp Normal file

Binary file not shown.

View File

@@ -0,0 +1 @@
/*

View File

@@ -7,124 +7,124 @@
namespace namespace
{ {
boost::mutex iomx; boost::mutex iomx;
}; }
class canteen class canteen
{ {
public: public:
canteen() : m_chickens(0) { } canteen() : m_chickens(0) { }
void get(int id) void get(int id)
{ {
boost::mutex::scoped_lock lock(m_mutex); boost::mutex::scoped_lock lock(m_mutex);
while (m_chickens == 0) while (m_chickens == 0)
{ {
{ {
boost::mutex::scoped_lock lock(iomx); boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << id << std::cout << "(" << clock() << ") Phil" << id <<
": wot, no chickens? I'll WAIT ..." << std::endl; ": wot, no chickens? I'll WAIT ..." << std::endl;
} }
m_condition.wait(lock); m_condition.wait(lock);
} }
{ {
boost::mutex::scoped_lock lock(iomx); boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << id << std::cout << "(" << clock() << ") Phil" << id <<
": those chickens look good ... one please ..." << std::endl; ": those chickens look good ... one please ..." << std::endl;
} }
m_chickens--; m_chickens--;
} }
void put(int value) void put(int value)
{ {
boost::mutex::scoped_lock lock(m_mutex); boost::mutex::scoped_lock lock(m_mutex);
{ {
boost::mutex::scoped_lock lock(iomx); boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << std::cout << "(" << clock() <<
") Chef: ouch ... make room ... this dish is very hot ..." << std::endl; ") Chef: ouch ... make room ... this dish is very hot ..." << std::endl;
} }
boost::xtime xt; boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC); boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 3; xt.sec += 3;
boost::thread::sleep(xt); boost::thread::sleep(xt);
m_chickens += value; m_chickens += value;
{ {
boost::mutex::scoped_lock lock(iomx); boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << std::cout << "(" << clock() <<
") Chef: more chickens ... " << m_chickens << ") Chef: more chickens ... " << m_chickens <<
" now available ... NOTIFYING ..." << std::endl; " now available ... NOTIFYING ..." << std::endl;
} }
m_condition.notify_all(); m_condition.notify_all();
} }
private: private:
boost::mutex m_mutex; boost::mutex m_mutex;
boost::condition m_condition; boost::condition m_condition;
int m_chickens; int m_chickens;
}; };
canteen g_canteen; canteen g_canteen;
void chef() void chef()
{ {
const int chickens = 4; const int chickens = 4;
{ {
boost::mutex::scoped_lock lock(iomx); boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Chef: starting ..." << std::endl; std::cout << "(" << clock() << ") Chef: starting ..." << std::endl;
} }
for (;;) for (;;)
{ {
{ {
boost::mutex::scoped_lock lock(iomx); boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Chef: cooking ..." << std::endl; std::cout << "(" << clock() << ") Chef: cooking ..." << std::endl;
} }
boost::xtime xt; boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC); boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 2; xt.sec += 2;
boost::thread::sleep(xt); boost::thread::sleep(xt);
{ {
boost::mutex::scoped_lock lock(iomx); boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Chef: " << chickens std::cout << "(" << clock() << ") Chef: " << chickens
<< " chickens, ready-to-go ..." << std::endl; << " chickens, ready-to-go ..." << std::endl;
} }
g_canteen.put(chickens); g_canteen.put(chickens);
} }
} }
struct phil struct phil
{ {
phil(int id) : m_id(id) { } phil(int id) : m_id(id) { }
void run() { void run() {
{ {
boost::mutex::scoped_lock lock(iomx); boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << m_id << ": starting ..." << std::endl; std::cout << "(" << clock() << ") Phil" << m_id << ": starting ..." << std::endl;
} }
for (;;) for (;;)
{ {
if (m_id > 0) if (m_id > 0)
{ {
boost::xtime xt; boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC); boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 3; xt.sec += 3;
boost::thread::sleep(xt); boost::thread::sleep(xt);
} }
{ {
boost::mutex::scoped_lock lock(iomx); boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << m_id std::cout << "(" << clock() << ") Phil" << m_id
<< ": gotta eat ..." << std::endl; << ": gotta eat ..." << std::endl;
} }
g_canteen.get(m_id); g_canteen.get(m_id);
{ {
boost::mutex::scoped_lock lock(iomx); boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << m_id std::cout << "(" << clock() << ") Phil" << m_id
<< ": mmm ... that's good ..." << std::endl; << ": mmm ... that's good ..." << std::endl;
} }
} }
} }
static void do_thread(void* param) { static void do_thread(void* param) {
static_cast<phil*>(param)->run(); static_cast<phil*>(param)->run();
} }
int m_id; int m_id;
}; };
struct thread_adapt struct thread_adapt

Binary file not shown.

1
example/tennis/Carbon.r Normal file
View File

@@ -0,0 +1 @@
/*

View File

@@ -5,8 +5,8 @@
#include <iostream> #include <iostream>
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
# include <windows.h> # include <windows.h>
# include <process.h> # include <process.h>
#endif #endif
enum game_state enum game_state

BIN
example/tennis/tennis.mcp Normal file

Binary file not shown.

View File

@@ -23,6 +23,8 @@
#if defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_PTHREADS)
# include <pthread.h> # include <pthread.h>
#elif defined(BOOST_HAS_MPTASKS)
# include "scoped_critical_region.hpp"
#endif #endif
namespace boost { namespace boost {
@@ -85,17 +87,17 @@ private:
template <typename M> template <typename M>
void do_wait(M& mutex) void do_wait(M& mutex)
{ {
#if defined(BOOST_HAS_WINTHREADS) #if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
enter_wait(); enter_wait();
#endif #endif
typedef typename detail::thread::lock_ops<M> lock_ops; typedef typename detail::thread::lock_ops<M> lock_ops;
lock_ops::lock_state state; typename lock_ops::lock_state state;
lock_ops::unlock(mutex, state); lock_ops::unlock(mutex, state);
#if defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_PTHREADS)
do_wait(state.pmutex); do_wait(state.pmutex);
#elif defined(BOOST_HAS_WINTHREADS) #elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
do_wait(); do_wait();
#endif #endif
@@ -105,19 +107,19 @@ private:
template <typename M> template <typename M>
bool do_timed_wait(M& mutex, const xtime& xt) bool do_timed_wait(M& mutex, const xtime& xt)
{ {
#if defined(BOOST_HAS_WINTHREADS) #if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
enter_wait(); enter_wait();
#endif #endif
typedef typename detail::thread::lock_ops<M> lock_ops; typedef typename detail::thread::lock_ops<M> lock_ops;
lock_ops::lock_state state; typename lock_ops::lock_state state;
lock_ops::unlock(mutex, state); lock_ops::unlock(mutex, state);
bool ret = false; bool ret = false;
#if defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_PTHREADS)
ret = do_timed_wait(xt, state.pmutex); ret = do_timed_wait(xt, state.pmutex);
#elif defined(BOOST_HAS_WINTHREADS) #elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
ret = do_timed_wait(xt); ret = do_timed_wait(xt);
#endif #endif
@@ -126,7 +128,7 @@ private:
return ret; return ret;
} }
#if defined(BOOST_HAS_WINTHREADS) #if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
void enter_wait(); void enter_wait();
void do_wait(); void do_wait();
bool do_timed_wait(const xtime& xt); bool do_timed_wait(const xtime& xt);
@@ -145,6 +147,15 @@ private:
// m_waiting to be removed from the m_queue // m_waiting to be removed from the m_queue
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
pthread_cond_t m_condition; 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 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
#endif #endif
}; };

View File

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

View File

@@ -0,0 +1,44 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_FORCE_CAST_MJM012402_HPP
#define BOOST_FORCE_CAST_MJM012402_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

@@ -0,0 +1,64 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_SINGLETON_MJM012402_HPP
#define BOOST_SINGLETON_MJM012402_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

@@ -22,7 +22,7 @@
namespace boost { namespace boost {
class lock_error : public std::runtime_error class lock_error : public std::logic_error
{ {
public: public:
lock_error(); lock_error();

View File

@@ -24,6 +24,10 @@
# include <pthread.h> # include <pthread.h>
#endif #endif
#if defined(BOOST_HAS_MPTASKS)
# include "scoped_critical_region.hpp"
#endif
namespace boost { namespace boost {
struct xtime; struct xtime;
@@ -46,6 +50,10 @@ private:
{ {
pthread_mutex_t* pmutex; pthread_mutex_t* pmutex;
}; };
#elif defined(BOOST_HAS_MPTASKS)
struct cv_state
{
};
#endif #endif
void do_lock(); void do_lock();
void do_unlock(); void do_unlock();
@@ -56,6 +64,9 @@ private:
void* m_mutex; void* m_mutex;
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex; 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 #endif
}; };
@@ -78,6 +89,10 @@ private:
{ {
pthread_mutex_t* pmutex; pthread_mutex_t* pmutex;
}; };
#elif defined(BOOST_HAS_MPTASKS)
struct cv_state
{
};
#endif #endif
void do_lock(); void do_lock();
bool do_trylock(); bool do_trylock();
@@ -89,6 +104,9 @@ private:
void* m_mutex; void* m_mutex;
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex; 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 #endif
}; };
@@ -112,6 +130,10 @@ private:
{ {
pthread_mutex_t* pmutex; pthread_mutex_t* pmutex;
}; };
#elif defined(BOOST_HAS_MPTASKS)
struct cv_state
{
};
#endif #endif
void do_lock(); void do_lock();
bool do_trylock(); bool do_trylock();
@@ -126,6 +148,9 @@ private:
pthread_mutex_t m_mutex; pthread_mutex_t m_mutex;
pthread_cond_t m_condition; pthread_cond_t m_condition;
bool m_locked; 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 #endif
}; };

View File

@@ -28,7 +28,7 @@ namespace boost {
typedef pthread_once_t once_flag; typedef pthread_once_t once_flag;
#define BOOST_ONCE_INIT PTHREAD_ONCE_INIT #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; typedef bool once_flag;
#define BOOST_ONCE_INIT false #define BOOST_ONCE_INIT false

View File

@@ -22,6 +22,8 @@
#if defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_PTHREADS)
# include <pthread.h> # include <pthread.h>
#elif defined(BOOST_HAS_MPTASKS)
# include "scoped_critical_region.hpp"
#endif #endif
namespace boost { namespace boost {
@@ -39,7 +41,7 @@ public:
~recursive_mutex(); ~recursive_mutex();
private: private:
#if defined(BOOST_HAS_WINTHREADS) #if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
typedef std::size_t cv_state; typedef std::size_t cv_state;
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
struct cv_state struct cv_state
@@ -64,6 +66,10 @@ private:
pthread_t m_thread_id; pthread_t m_thread_id;
bool m_valid_id; bool m_valid_id;
# endif # 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 #endif
}; };
@@ -79,7 +85,7 @@ public:
~recursive_try_mutex(); ~recursive_try_mutex();
private: private:
#if defined(BOOST_HAS_WINTHREADS) #if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
typedef std::size_t cv_state; typedef std::size_t cv_state;
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
struct cv_state struct cv_state
@@ -105,6 +111,10 @@ private:
pthread_t m_thread_id; pthread_t m_thread_id;
bool m_valid_id; bool m_valid_id;
# endif # 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 #endif
}; };
@@ -121,7 +131,7 @@ public:
~recursive_timed_mutex(); ~recursive_timed_mutex();
private: private:
#if defined(BOOST_HAS_WINTHREADS) #if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
typedef std::size_t cv_state; typedef std::size_t cv_state;
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
struct cv_state struct cv_state
@@ -146,6 +156,10 @@ private:
pthread_t m_thread_id; pthread_t m_thread_id;
bool m_valid_id; bool m_valid_id;
unsigned m_count; 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 #endif
}; };

View File

@@ -26,6 +26,8 @@
#if defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_PTHREADS)
# include <pthread.h> # include <pthread.h>
# include <boost/thread/condition.hpp> # include <boost/thread/condition.hpp>
#elif defined(BOOST_HAS_MPTASKS)
# include <Multiprocessing.h>
#endif #endif
namespace boost { namespace boost {
@@ -54,6 +56,9 @@ private:
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
private: private:
pthread_t m_thread; pthread_t m_thread;
#elif defined(BOOST_HAS_MPTASKS)
MPQueueID m_pJoinQueueID;
MPTaskID m_pTaskID;
#endif #endif
bool m_joinable; bool m_joinable;
}; };

View File

@@ -21,6 +21,8 @@
#if defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_PTHREADS)
# include <pthread.h> # include <pthread.h>
#elif defined(BOOST_HAS_MPTASKS)
# include <Multiprocessing.h>
#endif #endif
namespace boost { namespace boost {
@@ -41,8 +43,15 @@ namespace boost {
void (*m_cleanup)(void*); void (*m_cleanup)(void*);
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
pthread_key_t m_key; pthread_key_t m_key;
#elif defined(BOOST_HAS_MPTASKS)
TaskStorageIndex m_key;
void (*m_cleanup)(void*);
#endif #endif
}; };
#if defined(BOOST_HAS_MPTASKS)
void thread_cleanup();
#endif
} }
template <typename T> template <typename T>

View File

@@ -40,6 +40,13 @@ struct xtime
}; };
int xtime_get(struct xtime* xtp, int clock_type); int xtime_get(struct xtime* xtp, int clock_type);
inline int xtime_cmp(const xtime& xt1, const xtime& xt2)
{
int res = (int)(xt1.sec - xt2.sec);
if (res == 0)
res = (int)(xt1.nsec - xt2.nsec);
return res;
}
} // namespace boost } // namespace boost

View File

@@ -18,10 +18,16 @@
#include "timeconv.inl" #include "timeconv.inl"
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
# define NOMINMAX # ifndef NOMINMAX
# define NOMINMAX
# endif
# include <windows.h> # include <windows.h>
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
# include <errno.h> # include <errno.h>
#elif defined(BOOST_HAS_MPTASKS)
# include <MacErrors.h>
# include "mac/init.hpp"
# include "mac/safe.hpp"
#endif #endif
namespace boost { namespace boost {
@@ -87,6 +93,7 @@ void condition::notify_one()
++m_waiting; ++m_waiting;
--m_blocked; --m_blocked;
signals = 1;
} }
else else
{ {
@@ -107,15 +114,15 @@ void condition::notify_one()
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0); res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
assert(res); 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); assert(res);
if (signals)
{
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0);
assert(res);
}
} }
} }
@@ -237,7 +244,7 @@ void condition::do_wait()
bool condition::do_timed_wait(const xtime& xt) bool condition::do_timed_wait(const xtime& xt)
{ {
unsigned milliseconds; int milliseconds;
to_duration(xt, milliseconds); to_duration(xt, milliseconds);
unsigned int res = 0; unsigned int res = 0;
@@ -351,6 +358,285 @@ bool condition::do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex)
return 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::condition()
: 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::~condition()
{
OSStatus lStatus = noErr;
lStatus = MPDeleteSemaphore(m_gate);
assert(lStatus == noErr);
lStatus = MPDeleteSemaphore(m_queue);
assert(lStatus == noErr);
}
void condition::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::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::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::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::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 #endif
} // namespace boost } // namespace boost

View File

@@ -14,7 +14,7 @@
namespace boost { namespace boost {
lock_error::lock_error() : std::runtime_error("thread lock error") lock_error::lock_error() : std::logic_error("thread lock error")
{ {
} }

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

@@ -0,0 +1,14 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#define TARGET_CARBON 1

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

@@ -0,0 +1,72 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#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

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

@@ -0,0 +1,90 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#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

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

@@ -0,0 +1,99 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#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

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

@@ -0,0 +1,69 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#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,66 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#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,53 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#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

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

@@ -0,0 +1,64 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#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

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

@@ -0,0 +1,40 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_INIT_MJM012402_HPP
#define BOOST_INIT_MJM012402_HPP
namespace boost {
namespace threads {
namespace mac {
namespace detail {
bool thread_init();
bool create_singletons();
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_INIT_MJM012402_HPP

View File

@@ -0,0 +1,30 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#include <cassert>
#include <cstdio>
#include <MacTypes.h>
#include "remote_calls.hpp"
// this function will be called when an assertion fails. We redirect the assertion
// to DebugStr (MacsBug under Mac OS 1.x-9.x, Console under Mac OS X).
void __assertion_failed(char const *pszAssertion, char const *pszFile, int nLine)
{
using std::snprintf;
unsigned char strlDebug[sizeof(Str255) + 1];
char *pszDebug = reinterpret_cast<char *>(&strlDebug[1]);
strlDebug[0] = snprintf(pszDebug, sizeof(Str255), "assertion failed: \"%s\", %s, line %d", pszAssertion, pszFile, nLine);
boost::threads::mac::dt_remote_call(DebugStr, static_cast<ConstStringPtr>(strlDebug));
}

View File

@@ -0,0 +1,134 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
//
// includes
//
#include <abort_exit.h>
#include <console.h>
#include <console_io.h>
#include <misc_io.h>
#include <SIOUX.h>
#include "remote_calls.hpp"
//
// using declarations
//
using std::__file_handle;
using std::__idle_proc;
using std::__io_error;
using std::__no_io_error;
using std::size_t;
using boost::threads::mac::st_remote_call;
//
// prototypes
//
static bool check_console();
static int do_read_console(__file_handle ulHandle, unsigned char *pBuffer, size_t *pCount, __idle_proc pfnIdleProc);
static int do_write_console(__file_handle ulHandle, unsigned char *pBuffer, size_t *pCount, __idle_proc pfnIdleProc);
//
// MSL function replacements
//
// these two functions are called by cin and cout, respectively, as well as by (all?)
// other functions in MSL that do console I/O. All that they do is as the remote
// call manager to ensure that their guts are called at system task time.
int __read_console(__file_handle handle, unsigned char * buffer, size_t * count, __idle_proc idle_proc)
{
return(st_remote_call(do_read_console, handle, buffer, count, idle_proc));
}
int __write_console(__file_handle handle, unsigned char * buffer, size_t * count, __idle_proc idle_proc)
{
return(st_remote_call(do_write_console, handle, buffer, count, idle_proc));
}
//
// implementations
//
static bool check_console()
{
static bool s_bHaveConsole(false);
static bool s_bWontHaveConsole(false);
if(s_bHaveConsole)
{
return(true);
}
if(s_bWontHaveConsole == false)
{
__stdio_atexit();
if(InstallConsole(0) != 0)
{
s_bWontHaveConsole = true;
return(false);
}
__console_exit = RemoveConsole;
s_bHaveConsole = true;
return(true);
}
return(false);
}
int do_read_console(__file_handle /*ulHandle*/, unsigned char *pBuffer, size_t *pCount, __idle_proc /*pfnIdleProc*/)
{
assert(pCount != NULL);
assert(pBuffer != NULL || *pCount == 0UL);
if(check_console() == false)
{
return(__io_error);
}
std::fflush(stdout);
long lCount = ReadCharsFromConsole(reinterpret_cast<char *>(pBuffer), static_cast<long>(*pCount));
*pCount = static_cast<size_t>(lCount);
if(lCount == -1L)
{
return(__io_error);
}
return(__no_io_error);
}
int do_write_console(__file_handle /*ulHandle*/, unsigned char *pBuffer, size_t *pCount, __idle_proc /*pfnIdleProc*/)
{
if(check_console() == false)
{
return(__io_error);
}
long lCount = WriteCharsToConsole(reinterpret_cast<char *>(pBuffer), static_cast<long>(*pCount));
*pCount = static_cast<size_t>(lCount);
if(lCount == -1L)
{
return(__io_error);
}
return(__no_io_error);
}

View File

@@ -0,0 +1,58 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
//
// includes
//
#include <cstdlib>
#include <Multiprocessing.h>
//
// using declarations
//
using std::size_t;
extern "C" {
//
// prototypes
//
void *malloc(size_t ulSize);
void free(void *pBlock);
}
//
// MSL function replacements
//
// all allocation/deallocation currently goes through MPAllocateAligned/MPFree. This
// solution is sub-optimal at best, but will have to do for now.
void *malloc(size_t ulSize)
{
static bool bIgnored = MPLibraryIsLoaded();
return(MPAllocateAligned(ulSize, kMPAllocateDefaultAligned, 0UL));
}
void free(void *pBlock)
{
if(pBlock == NULL) return;
MPFree(pBlock);
}

View File

@@ -0,0 +1,105 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
//
// includes
//
#include <new>
#include <Multiprocessing.h>
//
// using declarations
//
using std::size_t;
using std::bad_alloc;
using std::nothrow_t;
using std::nothrow;
//
// local utility functions
//
// all allocation/deallocation currently goes through MPAllocateAligned/MPFree. This
// solution is sub-optimal at best, but will have to do for now.
inline static void *allocate(size_t ulSize, const nothrow_t &)
{
static bool bIgnored = MPLibraryIsLoaded();
return(MPAllocateAligned(ulSize, kMPAllocateDefaultAligned, 0UL));
}
inline static void *allocate(size_t ulSize)
{
void *pBlock = allocate(ulSize, nothrow);
if(pBlock == NULL)
throw(bad_alloc());
return(pBlock);
}
inline static void deallocate(void *pBlock)
{
if(pBlock == NULL) return;
MPFree(pBlock);
}
//
// global operators
//
void *operator new(size_t ulSize)
{
return(allocate(ulSize));
}
void *operator new[](size_t ulSize)
{
return(allocate(ulSize));
}
void *operator new(size_t ulSize, const nothrow_t &rNoThrow)
{
return(allocate(ulSize, rNoThrow));
}
void *operator new[](size_t ulSize, const nothrow_t &rNoThrow)
{
return(allocate(ulSize, rNoThrow));
}
void operator delete(void *pBlock)
{
deallocate(pBlock);
}
void operator delete[](void *pBlock)
{
deallocate(pBlock);
}
void operator delete(void *pBlock, const nothrow_t &)
{
deallocate(pBlock);
}
void operator delete[](void *pBlock, const nothrow_t &)
{
deallocate(pBlock);
}

View File

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

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

@@ -0,0 +1,63 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#include "os.hpp"
#include <cassert>
#include <Gestalt.h>
namespace boost {
namespace threads {
namespace mac {
namespace os {
// read the OS version from Gestalt
static inline long get_version()
{
long lVersion;
OSErr nErr = Gestalt(gestaltSystemVersion, &lVersion);
assert(nErr == noErr);
return(lVersion);
}
// check if we're running under Mac OS X and cache that information
bool x()
{
static bool bX = (version() >= 0x1000);
return(bX);
}
// read the OS version and cache it
long version()
{
static long lVersion = get_version();
return(lVersion);
}
} // namespace os
} // namespace mac
} // namespace threads
} // namespace boost

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

@@ -0,0 +1,43 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_OS_MJM012402_HPP
#define BOOST_OS_MJM012402_HPP
namespace boost {
namespace threads {
namespace mac {
namespace os {
// functions to determine the OS environment. With namespaces, you get a cute call:
// mac::os::x
bool x();
long version();
} // namespace os
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_OS_MJM012402_HPP

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

@@ -0,0 +1,52 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#include "ot_context.hpp"
#include "execution_context.hpp"
#include <cassert>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
ot_context::ot_context()
{
assert(at_st());
OSStatus lStatus = InitOpenTransportInContext(0UL, &m_pContext);
// TODO - throw on error
assert(lStatus == noErr);
}
ot_context::~ot_context()
{
CloseOpenTransportInContext(m_pContext);
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost

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

@@ -0,0 +1,64 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_OT_CONTEXT_MJM012402_HPP
#define BOOST_OT_CONTEXT_MJM012402_HPP
#include <OpenTransport.h>
#include <boost/utility.hpp>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
// class ot_context is intended to be used only as a singleton. All that this class
// does is ask OpenTransport to create him an OTClientContextPtr, and then doles
// this out to anyone who wants it. ot_context should only be instantiated at
// system task time.
class ot_context: private noncopyable
{
protected:
ot_context();
~ot_context();
public:
OTClientContextPtr get_context();
private:
OTClientContextPtr m_pContext;
};
inline OTClientContextPtr ot_context::get_context()
{ return(m_pContext); }
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_OT_CONTEXT_MJM012402_HPP

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

@@ -0,0 +1,82 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_PACKAGE_MJM012402_HPP
#define BOOST_PACKAGE_MJM012402_HPP
namespace boost {
namespace threads {
namespace mac {
namespace detail {
class base_package: private noncopyable
{
public:
virtual void accept() = 0;
};
template<class R>
class package: public base_package
{
public:
inline package(function<R> &rFunctor):
m_rFunctor(rFunctor)
{ /* no-op */ }
inline ~package()
{ /* no-op */ }
virtual void accept()
{ m_oR = m_rFunctor(); }
inline R return_value()
{ return(m_oR); }
private:
function<R> &m_rFunctor;
R m_oR;
};
template<>
class package<void>: public base_package
{
public:
inline package(function<void> &rFunctor):
m_rFunctor(rFunctor)
{ /* no-op */ }
inline ~package()
{ /* no-op */ }
virtual void accept()
{ m_rFunctor(); }
inline void return_value()
{ return; }
private:
function<void> &m_rFunctor;
};
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_PACKAGE_MJM012402_HPP

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

@@ -0,0 +1,103 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_PERIODICAL_MJM012402_HPP
#define BOOST_PERIODICAL_MJM012402_HPP
#include <boost/function.hpp>
#include <boost/utility.hpp>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
// class periodical inherits from its template parameter, which should follow the
// pattern set by classes dt_scheduler and st_scheduler. periodical knows how to
// call a boost::function, where the xx_scheduler classes only know to to call a
// member periodically.
template<class Scheduler>
class periodical: private noncopyable, private Scheduler
{
public:
periodical(function<void> &rFunction);
~periodical();
public:
void start();
void stop();
protected:
virtual void periodic_function();
private:
function<void> m_oFunction;
};
template<class Scheduler>
periodical<Scheduler>::periodical(function<void> &rFunction):
m_oFunction(rFunction)
{
// no-op
}
template<class Scheduler>
periodical<Scheduler>::~periodical()
{
stop();
}
template<class Scheduler>
void periodical<Scheduler>::start()
{
start_polling();
}
template<class Scheduler>
void periodical<Scheduler>::stop()
{
stop_polling();
}
template<class Scheduler>
inline void periodical<Scheduler>::periodic_function()
{
try
{
m_oFunction();
}
catch(...)
{
}
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_PERIODICAL_MJM012402_HPP

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

@@ -0,0 +1,15 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#define NDEBUG
#define TARGET_CARBON 1

View File

@@ -0,0 +1,54 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#include "remote_call_manager.hpp"
#include <boost/bind.hpp>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
using detail::delivery_man;
remote_call_manager::remote_call_manager():
m_oDTDeliveryMan(),
m_oSTDeliveryMan(),
m_oDTFunction(bind(&delivery_man::accept_deliveries, &m_oDTDeliveryMan)),
m_oSTFunction(bind(&delivery_man::accept_deliveries, &m_oSTDeliveryMan)),
m_oDTPeriodical(m_oDTFunction),
m_oSTPeriodical(m_oSTFunction)
{
m_oDTPeriodical.start();
m_oSTPeriodical.start();
}
remote_call_manager::~remote_call_manager()
{
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost

View File

@@ -0,0 +1,108 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_REMOTE_CALL_MANAGER_MJM012402_HPP
#define BOOST_REMOTE_CALL_MANAGER_MJM012402_HPP
#include <boost/utility.hpp>
#include "delivery_man.hpp"
#include "dt_scheduler.hpp"
#include "periodical.hpp"
#include "execution_context.hpp"
#include "st_scheduler.hpp"
namespace boost {
namespace threads {
namespace mac {
namespace detail {
// class remote_call_manager is used by the remote call functions (dt_remote_call and
// st_remote_call) to execute functions in non-MP contexts.
class remote_call_manager: private noncopyable
{
protected:
remote_call_manager();
~remote_call_manager();
public:
template<class R>
R execute_at_dt(function<R> &rFunctor);
template<class R>
R execute_at_st(function<R> &rFunctor);
private:
template<class R>
static R execute_now(function<R> &rFunctor);
private:
delivery_man m_oDTDeliveryMan;
delivery_man m_oSTDeliveryMan;
function<void> m_oDTFunction;
function<void> m_oSTFunction;
periodical<dt_scheduler> m_oDTPeriodical;
periodical<st_scheduler> m_oSTPeriodical;
};
template<class R>
/*static*/ inline R remote_call_manager::execute_now(function<R> &rFunctor)
{
return(rFunctor());
}
template<>
/*static*/ inline void remote_call_manager::execute_now<void>(function<void> &rFunctor)
{
rFunctor();
}
template<class R>
inline R remote_call_manager::execute_at_dt(function<R> &rFunctor)
{
if(at_mp())
{
return(m_oDTDeliveryMan.deliver(rFunctor));
}
return(execute_now(rFunctor));
}
template<class R>
inline R remote_call_manager::execute_at_st(function<R> &rFunctor)
{
if(at_mp())
{
return(m_oSTDeliveryMan.deliver(rFunctor));
}
assert(at_st());
return(execute_now(rFunctor));
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_REMOTE_CALL_MANAGER_MJM012402_HPP

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

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

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

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

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

@@ -0,0 +1,47 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_SAFE_MJM012402_HPP
#define BOOST_SAFE_MJM012402_HPP
#include <Multiprocessing.h>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
// these functions are used to wain in an execution context-independent manor. All of these
// functions are both MP- and ST-safe.
OSStatus safe_wait_on_semaphore(MPSemaphoreID pSemaphoreID, Duration lDuration);
OSStatus safe_enter_critical_region(MPCriticalRegionID pCriticalRegionID, Duration lDuration, MPCriticalRegionID pCriticalRegionCriticalRegionID = kInvalidID);
OSStatus safe_wait_on_queue(MPQueueID pQueueID, void **pParam1, void **pParam2, void **pParam3, Duration lDuration);
OSStatus safe_delay_until(AbsoluteTime *pWakeUpTime);
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_SAFE_MJM012402_HPP

View File

@@ -0,0 +1,53 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#include "scoped_critical_region.hpp"
#include "init.hpp"
#include <cassert>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
scoped_critical_region::scoped_critical_region():
m_pCriticalRegionID(kInvalidID)
{
static bool bIgnored = thread_init();
OSStatus lStatus = MPCreateCriticalRegion(&m_pCriticalRegionID);
if(lStatus != noErr || m_pCriticalRegionID == kInvalidID)
throw(thread_resource_error());
}
scoped_critical_region::~scoped_critical_region()
{
OSStatus lStatus = MPDeleteCriticalRegion(m_pCriticalRegionID);
assert(lStatus == noErr);
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost

View File

@@ -0,0 +1,69 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_SCOPED_CRITICAL_REGION_MJM012402_HPP
#define BOOST_SCOPED_CRITICAL_REGION_MJM012402_HPP
#include <boost/thread/exceptions.hpp>
#include <Multiprocessing.h>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
// class scoped_critical_region probably needs a new name. Although the current name
// is accurate, it can be read to mean that a critical region is entered for the
// current scope. In reality, a critical region is _created_ for the current scope.
// This class is intended as a replacement for MPCriticalRegionID that will
// automatically create and dispose of itself.
class scoped_critical_region
{
public:
scoped_critical_region();
~scoped_critical_region();
public:
operator const MPCriticalRegionID &() const;
const MPCriticalRegionID &get() const;
private:
MPCriticalRegionID m_pCriticalRegionID;
};
// these are inlined for speed.
inline scoped_critical_region::operator const MPCriticalRegionID &() const
{ return(m_pCriticalRegionID); }
inline const MPCriticalRegionID &scoped_critical_region::get() const
{ return(m_pCriticalRegionID); }
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_SCOPED_CRITICAL_REGION_MJM012402_HPP

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

@@ -0,0 +1,91 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#include "st_scheduler.hpp"
#include <cassert>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
#if TARGET_CARBON
st_scheduler::st_scheduler():
m_uppTask(NULL),
m_pTimer(NULL)
{
m_uppTask = NewEventLoopTimerUPP(task_entry);
// TODO - throw on error
assert(m_uppTask != NULL);
}
st_scheduler::~st_scheduler()
{
DisposeEventLoopTimerUPP(m_uppTask);
m_uppTask = NULL;
}
void st_scheduler::start_polling()
{
assert(m_pTimer == NULL);
OSStatus lStatus = InstallEventLoopTimer(GetMainEventLoop(),
0 * kEventDurationSecond,
kEventDurationMillisecond,
m_uppTask,
this,
&m_pTimer);
// TODO - throw on error
assert(lStatus == noErr);
}
void st_scheduler::stop_polling()
{
assert(m_pTimer != NULL);
OSStatus lStatus = RemoveEventLoopTimer(m_pTimer);
assert(lStatus == noErr);
m_pTimer = NULL;
}
/*static*/ pascal void st_scheduler::task_entry(EventLoopTimerRef /*pTimer*/, void *pRefCon)
{
st_scheduler *pThis = reinterpret_cast<st_scheduler *>(pRefCon);
assert(pThis != NULL);
pThis->task();
}
void st_scheduler::task()
{
periodic_function();
}
#else
# error st_scheduler unimplemented!
#endif
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost

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

@@ -0,0 +1,73 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_ST_SCHEDULER_MJM012402_HPP
#define BOOST_ST_SCHEDULER_MJM012402_HPP
#include <CarbonEvents.h>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
// class st_scheduler calls its pure-virtual periodic_function method periodically at
// system task time. This is generally 40Hz under Mac OS 9.
class st_scheduler
{
public:
st_scheduler();
virtual ~st_scheduler();
protected:
void start_polling();
void stop_polling();
private:
virtual void periodic_function() = 0;
#if TARGET_CARBON
// use event loop timers under Carbon
private:
static pascal void task_entry(EventLoopTimerRef pTimer, void *pRefCon);
void task();
private:
EventLoopTimerUPP m_uppTask;
EventLoopTimerRef m_pTimer;
#else
// this can be implemented using OT system tasks. This would be mostly a copy-and-
// paste of the dt_scheduler code, replacing DeferredTask with SystemTask and DT
// with ST.
# error st_scheduler unimplemented!
#endif
};
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_ST_SCHEDULER_MJM012402_HPP

View File

@@ -0,0 +1,62 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#include "thread_cleanup.hpp"
namespace boost {
namespace threads {
namespace mac {
namespace detail {
namespace {
TaskStorageIndex g_ulIndex(0UL);
} // anonymous namespace
void do_thread_startup()
{
if(g_ulIndex == 0UL)
{
OSStatus lStatus = MPAllocateTaskStorageIndex(&g_ulIndex);
assert(lStatus == noErr);
}
set_thread_cleanup_task(NULL);
}
void do_thread_cleanup()
{
void (*pfnTask)() = MPGetTaskValue(g_ulIndex)
}
void set_thread_cleanup_task(void (*pfnTask)())
{
lStatus = MPSetTaskValue(g_ulIndex, reinterpret_cast<TaskStorageValue>(pfnTask));
assert(lStatus == noErr);
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost

View File

@@ -0,0 +1,42 @@
// Copyright (C) 2001
// Mac Murrett
//
// 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. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_THREAD_CLEANUP_MJM012402_HPP
#define BOOST_THREAD_CLEANUP_MJM012402_HPP
namespace boost {
namespace threads {
namespace mac {
namespace detail {
void do_thread_startup();
void do_thread_cleanup();
void set_thread_cleanup_task();
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_THREAD_CLEANUP_MJM012402_HPP

View File

@@ -24,6 +24,11 @@
# include <time.h> # include <time.h>
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
# include <errno.h> # include <errno.h>
#elif defined(BOOST_HAS_MPTASKS)
# include <MacErrors.h>
# include "mac/init.hpp"
# include "mac/safe.hpp"
#endif #endif
namespace boost { namespace boost {
@@ -140,7 +145,7 @@ bool timed_mutex::do_trylock()
bool timed_mutex::do_timedlock(const xtime& xt) bool timed_mutex::do_timedlock(const xtime& xt)
{ {
unsigned milliseconds; int milliseconds;
to_duration(xt, milliseconds); to_duration(xt, milliseconds);
unsigned int res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), milliseconds); unsigned int res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), milliseconds);
@@ -394,6 +399,134 @@ void timed_mutex::do_unlock(cv_state& state)
state.pmutex = &m_mutex; state.pmutex = &m_mutex;
} }
#elif defined(BOOST_HAS_MPTASKS)
using threads::mac::detail::safe_enter_critical_region;
mutex::mutex()
{
}
mutex::~mutex()
{
}
void mutex::do_lock()
{
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever, m_mutex_mutex);
assert(lStatus == noErr);
}
void mutex::do_unlock()
{
OSStatus lStatus = noErr;
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
}
void mutex::do_lock(cv_state& /*state*/)
{
do_lock();
}
void mutex::do_unlock(cv_state& /*state*/)
{
do_unlock();
}
try_mutex::try_mutex()
{
}
try_mutex::~try_mutex()
{
}
void try_mutex::do_lock()
{
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever, m_mutex_mutex);
assert(lStatus == noErr);
}
bool try_mutex::do_trylock()
{
OSStatus lStatus = noErr;
lStatus = MPEnterCriticalRegion(m_mutex, kDurationImmediate);
assert(lStatus == noErr || lStatus == kMPTimeoutErr);
return lStatus == noErr;
}
void try_mutex::do_unlock()
{
OSStatus lStatus = noErr;
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
}
void try_mutex::do_lock(cv_state& /*state*/)
{
do_lock();
}
void try_mutex::do_unlock(cv_state& /*state*/)
{
do_unlock();
}
timed_mutex::timed_mutex()
{
}
timed_mutex::~timed_mutex()
{
}
void timed_mutex::do_lock()
{
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever, m_mutex_mutex);
assert(lStatus == noErr);
}
bool timed_mutex::do_trylock()
{
OSStatus lStatus = noErr;
lStatus = MPEnterCriticalRegion(m_mutex, kDurationImmediate);
assert(lStatus == noErr || lStatus == kMPTimeoutErr);
return(lStatus == noErr);
}
bool timed_mutex::do_timedlock(const xtime& xt)
{
int microseconds;
to_microduration(xt, microseconds);
Duration lDuration = kDurationMicrosecond * microseconds;
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, lDuration, m_mutex_mutex);
assert(lStatus == noErr || lStatus == kMPTimeoutErr);
return(lStatus == noErr);
}
void timed_mutex::do_unlock()
{
OSStatus lStatus = noErr;
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
}
void timed_mutex::do_lock(cv_state& /*state*/)
{
do_lock();
}
void timed_mutex::do_unlock(cv_state& /*state*/)
{
do_unlock();
}
#endif #endif
} // namespace boost } // namespace boost

View File

@@ -28,6 +28,8 @@
# else # else
# include <sstream> # include <sstream>
# endif # endif
#elif defined(BOOST_HAS_MPTASKS)
# include <Multiprocessing.h>
#endif #endif
#ifdef BOOST_NO_STDC_NAMESPACE #ifdef BOOST_NO_STDC_NAMESPACE
@@ -55,6 +57,19 @@ static void do_once()
(**cb)(); (**cb)();
} }
}
#elif defined(BOOST_HAS_MPTASKS)
void *remote_call_proxy(void *pData)
{
std::pair<void (*)(), boost::once_flag *> &rData(*reinterpret_cast<std::pair<void (*)(), boost::once_flag *> *>(pData));
if(*rData.second == false)
{
rData.first();
*rData.second = true;
}
return(NULL);
} }
#endif #endif
@@ -107,6 +122,14 @@ void call_once(void (*func)(), once_flag& flag)
pthread_once(&once, &key_init); pthread_once(&once, &key_init);
pthread_setspecific(key, &func); pthread_setspecific(key, &func);
pthread_once(&flag, do_once); pthread_once(&flag, do_once);
#elif defined(BOOST_HAS_MPTASKS)
if(flag == false)
{
// all we do here is make a remote call to blue, as blue is not reentrant.
std::pair<void (*)(), once_flag *> sData(func, &flag);
MPRemoteCall(remote_call_proxy, &sData, kMPOwningProcessRemoteContext);
assert(flag == true);
}
#endif #endif
} }

View File

@@ -22,6 +22,9 @@
# include <time.h> # include <time.h>
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
# include <errno.h> # include <errno.h>
#elif defined(BOOST_HAS_MPTASKS)
# include <MacErrors.h>
# include "safe.hpp"
#endif #endif
namespace boost { namespace boost {
@@ -192,7 +195,7 @@ bool recursive_timed_mutex::do_trylock()
bool recursive_timed_mutex::do_timedlock(const xtime& xt) bool recursive_timed_mutex::do_timedlock(const xtime& xt)
{ {
unsigned milliseconds; int milliseconds;
to_duration(xt, milliseconds); to_duration(xt, milliseconds);
unsigned int res = 0; unsigned int res = 0;
@@ -766,6 +769,221 @@ void recursive_timed_mutex::do_unlock(cv_state& state)
state.pmutex = &m_mutex; state.pmutex = &m_mutex;
state.count = m_count; state.count = m_count;
} }
#elif defined(BOOST_HAS_MPTASKS)
using threads::mac::detail::safe_enter_critical_region;
recursive_mutex::recursive_mutex()
: m_count(0)
{
}
recursive_mutex::~recursive_mutex()
{
}
void recursive_mutex::do_lock()
{
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever, m_mutex_mutex);
assert(lStatus == noErr);
if (++m_count > 1)
{
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
}
}
void recursive_mutex::do_unlock()
{
if (--m_count == 0)
{
OSStatus lStatus = noErr;
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
}
}
void recursive_mutex::do_lock(cv_state& state)
{
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever, m_mutex_mutex);
assert(lStatus == noErr);
m_count = state;
}
void recursive_mutex::do_unlock(cv_state& state)
{
state = m_count;
m_count = 0;
OSStatus lStatus = noErr;
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
}
recursive_try_mutex::recursive_try_mutex()
: m_count(0)
{
}
recursive_try_mutex::~recursive_try_mutex()
{
}
void recursive_try_mutex::do_lock()
{
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever, m_mutex_mutex);
assert(lStatus == noErr);
if (++m_count > 1)
{
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
}
}
bool recursive_try_mutex::do_trylock()
{
OSStatus lStatus = noErr;
lStatus = MPEnterCriticalRegion(m_mutex, kDurationImmediate);
assert(lStatus == noErr || lStatus == kMPTimeoutErr);
if (lStatus == noErr)
{
if (++m_count > 1)
{
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
}
return true;
}
return false;
}
void recursive_try_mutex::do_unlock()
{
if (--m_count == 0)
{
OSStatus lStatus = noErr;
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
}
}
void recursive_try_mutex::do_lock(cv_state& state)
{
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever, m_mutex_mutex);
assert(lStatus == noErr);
m_count = state;
}
void recursive_try_mutex::do_unlock(cv_state& state)
{
state = m_count;
m_count = 0;
OSStatus lStatus = noErr;
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
}
recursive_timed_mutex::recursive_timed_mutex()
: m_count(0)
{
}
recursive_timed_mutex::~recursive_timed_mutex()
{
}
void recursive_timed_mutex::do_lock()
{
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever, m_mutex_mutex);
assert(lStatus == noErr);
if (++m_count > 1)
{
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
}
}
bool recursive_timed_mutex::do_trylock()
{
OSStatus lStatus = noErr;
lStatus = MPEnterCriticalRegion(m_mutex, kDurationImmediate);
assert(lStatus == noErr || lStatus == kMPTimeoutErr);
if (lStatus == noErr)
{
if (++m_count > 1)
{
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
}
return true;
}
return false;
}
bool recursive_timed_mutex::do_timedlock(const xtime& xt)
{
int microseconds;
to_microduration(xt, microseconds);
Duration lDuration = kDurationMicrosecond * microseconds;
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, lDuration, m_mutex_mutex);
assert(lStatus == noErr || lStatus == kMPTimeoutErr);
if (lStatus == noErr)
{
if (++m_count > 1)
{
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
}
return true;
}
return false;
}
void recursive_timed_mutex::do_unlock()
{
if (--m_count == 0)
{
OSStatus lStatus = noErr;
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
}
}
void recursive_timed_mutex::do_lock(cv_state& state)
{
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever, m_mutex_mutex);
assert(lStatus == noErr);
m_count = state;
}
void recursive_timed_mutex::do_unlock(cv_state& state)
{
state = m_count;
m_count = 0;
OSStatus lStatus = noErr;
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
}
#endif #endif
} // namespace boost } // namespace boost

View File

@@ -17,6 +17,12 @@
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
# include <windows.h> # include <windows.h>
# include <process.h> # include <process.h>
#elif defined(BOOST_HAS_MPTASKS)
# include <DriverServices.h>
# include "init.hpp"
# include "safe.hpp"
# include <boost/thread/tss.hpp>
#endif #endif
#include "timeconv.inl" #include "timeconv.inl"
@@ -53,6 +59,8 @@ extern "C" {
unsigned __stdcall thread_proxy(void* param) unsigned __stdcall thread_proxy(void* param)
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
static void* thread_proxy(void* param) static void* thread_proxy(void* param)
#elif defined(BOOST_HAS_MPTASKS)
static OSStatus thread_proxy(void* param)
#endif #endif
{ {
try try
@@ -65,6 +73,9 @@ static void* thread_proxy(void* param)
catch (...) catch (...)
{ {
} }
#if defined(BOOST_HAS_MPTASKS)
::boost::detail::thread_cleanup();
#endif
return 0; return 0;
} }
@@ -80,6 +91,11 @@ thread::thread()
m_id = GetCurrentThreadId(); m_id = GetCurrentThreadId();
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
m_thread = pthread_self(); m_thread = pthread_self();
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::thread_init();
threads::mac::detail::create_singletons();
m_pTaskID = MPCurrentTaskID();
m_pJoinQueueID = kInvalidID;
#endif #endif
} }
@@ -96,6 +112,25 @@ thread::thread(const function0<void>& threadfunc)
res = pthread_create(&m_thread, 0, &thread_proxy, &param); res = pthread_create(&m_thread, 0, &thread_proxy, &param);
if (res != 0) if (res != 0)
throw thread_resource_error(); throw thread_resource_error();
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::thread_init();
threads::mac::detail::create_singletons();
OSStatus lStatus = noErr;
m_pJoinQueueID = kInvalidID;
m_pTaskID = kInvalidID;
lStatus = MPCreateQueue(&m_pJoinQueueID);
if(lStatus != noErr) throw thread_resource_error();
lStatus = MPCreateTask(&thread_proxy, &param, 0UL, m_pJoinQueueID, NULL, NULL,
0UL, &m_pTaskID);
if(lStatus != noErr)
{
lStatus = MPDeleteQueue(m_pJoinQueueID);
assert(lStatus == noErr);
throw thread_resource_error();
}
#endif #endif
param.wait(); param.wait();
} }
@@ -110,6 +145,10 @@ thread::~thread()
assert(res); assert(res);
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
pthread_detach(m_thread); pthread_detach(m_thread);
#elif defined(BOOST_HAS_MPTASKS)
assert(m_pJoinQueueID != kInvalidID);
OSStatus lStatus = MPDeleteQueue(m_pJoinQueueID);
assert(lStatus == noErr);
#endif #endif
} }
} }
@@ -120,6 +159,8 @@ bool thread::operator==(const thread& other) const
return other.m_id == m_id; return other.m_id == m_id;
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
return pthread_equal(m_thread, other.m_thread) != 0; return pthread_equal(m_thread, other.m_thread) != 0;
#elif defined(BOOST_HAS_MPTASKS)
return other.m_pTaskID == m_pTaskID;
#endif #endif
} }
@@ -139,6 +180,9 @@ void thread::join()
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
res = pthread_join(m_thread, 0); res = pthread_join(m_thread, 0);
assert(res == 0); assert(res == 0);
#elif defined(BOOST_HAS_MPTASKS)
OSStatus lStatus = threads::mac::detail::safe_wait_on_queue(m_pJoinQueueID, NULL, NULL, NULL, kDurationForever);
assert(lStatus == noErr);
#endif #endif
// This isn't a race condition since any race that could occur would // This isn't a race condition since any race that could occur would
// have us in undefined behavior territory any way. // have us in undefined behavior territory any way.
@@ -147,31 +191,44 @@ void thread::join()
void thread::sleep(const xtime& xt) void thread::sleep(const xtime& xt)
{ {
for (;;)
{
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
unsigned milliseconds; int milliseconds;
to_duration(xt, milliseconds); to_duration(xt, milliseconds);
Sleep(milliseconds); Sleep(milliseconds);
xtime xt2;
xtime_get(&xt2, TIME_UTC);
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
# if defined(BOOST_HAS_PTHREAD_DELAY_NP) # if defined(BOOST_HAS_PTHREAD_DELAY_NP)
timespec ts; timespec ts;
to_timespec(xt, ts); to_timespec_duration(xt, ts);
int res = 0; int res = 0;
res = pthread_delay_np(&ts); res = pthread_delay_np(&ts);
assert(res == 0); assert(res == 0);
# elif defined(BOOST_HAS_NANOSLEEP) # elif defined(BOOST_HAS_NANOSLEEP)
timespec ts; timespec ts;
to_timespec_duration(xt, ts); to_timespec_duration(xt, ts);
// nanosleep takes a timespec that is an offset, not // nanosleep takes a timespec that is an offset, not
// an absolute time. // an absolute time.
nanosleep(&ts, 0); nanosleep(&ts, 0);
# else # else
mutex mx; mutex mx;
mutex::scoped_lock lock(mx); mutex::scoped_lock lock(mx);
condition cond; condition cond;
cond.timed_wait(lock, xt); cond.timed_wait(lock, xt);
# endif # endif
#elif defined(BOOST_HAS_MPTASKS)
int microseconds;
to_microduration(xt, microseconds);
Duration lMicroseconds(kDurationMicrosecond * microseconds);
AbsoluteTime sWakeTime(DurationToAbsolute(lMicroseconds));
threads::mac::detail::safe_delay_until(&sWakeTime);
#endif #endif
if (xtime_cmp(xt, xt2) >= 0)
return;
}
} }
void thread::yield() void thread::yield()
@@ -192,6 +249,8 @@ void thread::yield()
xtime_get(&xt, TIME_UTC); xtime_get(&xt, TIME_UTC);
sleep(xt); sleep(xt);
# endif # endif
#elif defined(BOOST_HAS_MPTASKS)
MPYield();
#endif #endif
} }

View File

@@ -32,7 +32,8 @@ namespace
#define DllMain DllEntryPoint #define DllMain DllEntryPoint
#endif #endif
BOOL APIENTRY DllMain(HANDLE module, DWORD reason, LPVOID) extern "C"
BOOL WINAPI DllMain(HANDLE module, DWORD reason, LPVOID)
{ {
switch (reason) switch (reason)
{ {

View File

@@ -10,11 +10,14 @@
// It is provided "as is" without express or implied warranty. // It is provided "as is" without express or implied warranty.
namespace { namespace {
const unsigned MILLISECONDS_PER_SECOND = 1000; const int MILLISECONDS_PER_SECOND = 1000;
const unsigned NANOSECONDS_PER_SECOND = 1000000000; const int NANOSECONDS_PER_SECOND = 1000000000;
const unsigned NANOSECONDS_PER_MILLISECOND = 1000000; const int NANOSECONDS_PER_MILLISECOND = 1000000;
inline void to_time(unsigned milliseconds, boost::xtime& xt) const int MICROSECONDS_PER_SECOND = 1000000;
const int NANOSECONDS_PER_MICROSECOND = 1000;
inline void to_time(int milliseconds, boost::xtime& xt)
{ {
int res = 0; int res = 0;
res = boost::xtime_get(&xt, boost::TIME_UTC); res = boost::xtime_get(&xt, boost::TIME_UTC);
@@ -35,14 +38,14 @@ namespace {
{ {
ts.tv_sec = static_cast<int>(xt.sec); ts.tv_sec = static_cast<int>(xt.sec);
ts.tv_nsec = static_cast<int>(xt.nsec); ts.tv_nsec = static_cast<int>(xt.nsec);
if(ts.tv_nsec > NANOSECONDS_PER_SECOND) if(ts.tv_nsec > static_cast<const int>(NANOSECONDS_PER_SECOND))
{ {
ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND; ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
ts.tv_nsec %= NANOSECONDS_PER_SECOND; ts.tv_nsec %= NANOSECONDS_PER_SECOND;
} }
} }
inline void to_time(unsigned milliseconds, timespec& ts) inline void to_time(int milliseconds, timespec& ts)
{ {
boost::xtime xt; boost::xtime xt;
to_time(milliseconds, xt); to_time(milliseconds, xt);
@@ -71,7 +74,7 @@ namespace {
ts.tv_sec -= 1; ts.tv_sec -= 1;
ts.tv_nsec += NANOSECONDS_PER_SECOND; ts.tv_nsec += NANOSECONDS_PER_SECOND;
} }
if(ts.tv_nsec > NANOSECONDS_PER_SECOND) if(ts.tv_nsec > static_cast<const int>(NANOSECONDS_PER_SECOND))
{ {
ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND; ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
ts.tv_nsec %= NANOSECONDS_PER_SECOND; ts.tv_nsec %= NANOSECONDS_PER_SECOND;
@@ -80,7 +83,7 @@ namespace {
} }
#endif #endif
inline void to_duration(const boost::xtime& xt, unsigned& milliseconds) inline void to_duration(const boost::xtime& xt, int& milliseconds)
{ {
boost::xtime cur; boost::xtime cur;
int res = 0; int res = 0;
@@ -91,9 +94,26 @@ namespace {
milliseconds = 0; milliseconds = 0;
else else
{ {
milliseconds = static_cast<unsigned>(((xt.sec - cur.sec) * MILLISECONDS_PER_SECOND) + milliseconds = ((xt.sec - cur.sec) * MILLISECONDS_PER_SECOND) +
(((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MILLISECOND/2)) / (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MILLISECOND/2)) /
NANOSECONDS_PER_MILLISECOND)); NANOSECONDS_PER_MILLISECOND);
}
}
inline void to_microduration(const boost::xtime& xt, int& microseconds)
{
boost::xtime cur;
int res = 0;
res = boost::xtime_get(&cur, boost::TIME_UTC);
assert(res == boost::TIME_UTC);
if (xt.sec < cur.sec || (xt.sec == cur.sec && xt.nsec < cur.nsec))
microseconds = 0;
else
{
microseconds = ((xt.sec - cur.sec) * MICROSECONDS_PER_SECOND) +
(((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MICROSECOND/2)) /
NANOSECONDS_PER_MICROSECOND);
} }
} }
} }

View File

@@ -72,6 +72,72 @@ namespace {
return handlers; return handlers;
} }
} }
#elif defined(BOOST_HAS_MPTASKS)
#include <map>
namespace {
typedef std::pair<void(*)(void*), void*> cleanup_info;
typedef std::map<int, cleanup_info> cleanup_handlers;
TaskStorageIndex key;
boost::once_flag once = BOOST_ONCE_INIT;
void init_cleanup_key()
{
OSStatus lStatus = MPAllocateTaskStorageIndex(&key);
assert(lStatus == noErr);
}
cleanup_handlers* get_handlers()
{
boost::call_once(&init_cleanup_key, once);
cleanup_handlers* handlers = reinterpret_cast<cleanup_handlers*>(MPGetTaskStorageValue(key));
if (!handlers)
{
try
{
handlers = new cleanup_handlers;
}
catch (...)
{
return 0;
}
OSStatus lStatus = noErr;
lStatus = MPSetTaskStorageValue(key, reinterpret_cast<TaskStorageValue>(handlers));
assert(lStatus == noErr);
// TODO - create a generalized mechanism for registering thread exit functions
// and use it here.
}
return handlers;
}
}
namespace boost {
namespace detail {
void thread_cleanup()
{
cleanup_handlers* handlers = reinterpret_cast<cleanup_handlers*>(MPGetTaskStorageValue(key));
if(handlers != NULL)
{
for (cleanup_handlers::iterator it = handlers->begin(); it != handlers->end(); ++it)
{
cleanup_info info = it->second;
if (info.second)
info.first(info.second);
}
delete handlers;
}
}
} // namespace detail
} // namespace boost
#endif #endif
namespace boost { namespace detail { namespace boost { namespace detail {
@@ -136,6 +202,42 @@ bool tss::set(void* value)
{ {
return pthread_setspecific(m_key, value) == 0; return pthread_setspecific(m_key, value) == 0;
} }
#elif defined(BOOST_HAS_MPTASKS)
tss::tss(void (*cleanup)(void*))
{
OSStatus lStatus = MPAllocateTaskStorageIndex(&m_key);
if(lStatus != noErr)
throw thread_resource_error();
m_cleanup = cleanup;
}
tss::~tss()
{
OSStatus lStatus = MPDeallocateTaskStorageIndex(m_key);
assert(lStatus == noErr);
}
void* tss::get() const
{
TaskStorageValue ulValue = MPGetTaskStorageValue(m_key);
return(reinterpret_cast<void *>(ulValue));
}
bool tss::set(void* value)
{
if (value && m_cleanup)
{
cleanup_handlers* handlers = get_handlers();
assert(handlers);
if (!handlers)
return false;
cleanup_info info(m_cleanup, value);
(*handlers)[m_key] = info;
}
OSStatus lStatus = MPSetTaskStorageValue(m_key, reinterpret_cast<TaskStorageValue>(value));
return(lStatus == noErr);
}
#endif #endif
} // namespace detail } // namespace detail

View File

@@ -15,10 +15,61 @@
# include <windows.h> # include <windows.h>
#elif defined(BOOST_HAS_GETTIMEOFDAY) #elif defined(BOOST_HAS_GETTIMEOFDAY)
# include <sys/time.h> # include <sys/time.h>
#elif defined(BOOST_HAS_MPTASKS)
# include <DriverServices.h>
# include <boost/thread/detail/force_cast.hpp>
#endif #endif
namespace boost { namespace boost {
#ifdef BOOST_HAS_MPTASKS
namespace detail
{
using thread::force_cast;
struct startup_time_info
{
startup_time_info()
{
// 1970 Jan 1 at 00:00:00
static const DateTimeRec k_sUNIXBase = {1970, 1, 1, 0, 0, 0, 0};
static unsigned long s_ulUNIXBaseSeconds = 0UL;
if(s_ulUNIXBaseSeconds == 0UL)
{
// calculate the number of seconds between the Mac OS base and the UNIX base
// the first time we enter this constructor.
DateToSeconds(&k_sUNIXBase, &s_ulUNIXBaseSeconds);
}
unsigned long ulSeconds;
// get the time in UpTime units twice, with the time in seconds in the middle.
uint64_t ullFirstUpTime = force_cast<uint64_t>(UpTime());
GetDateTime(&ulSeconds);
uint64_t ullSecondUpTime = force_cast<uint64_t>(UpTime());
// calculate the midpoint of the two UpTimes, and save that.
uint64_t ullAverageUpTime = (ullFirstUpTime + ullSecondUpTime) / 2ULL;
m_sStartupAbsoluteTime = force_cast<AbsoluteTime>(ullAverageUpTime);
// save the number of seconds, recentered at the UNIX base.
m_ulStartupSeconds = ulSeconds - s_ulUNIXBaseSeconds;
}
AbsoluteTime m_sStartupAbsoluteTime;
UInt32 m_ulStartupSeconds;
};
static startup_time_info g_sStartupTimeInfo;
} // namespace detail
#endif
int xtime_get(struct xtime* xtp, int clock_type) int xtime_get(struct xtime* xtp, int clock_type)
{ {
if (clock_type == TIME_UTC) if (clock_type == TIME_UTC)
@@ -43,6 +94,19 @@ int xtime_get(struct xtime* xtp, int clock_type)
xtp->sec = ts.tv_sec; xtp->sec = ts.tv_sec;
xtp->nsec = ts.tv_nsec; xtp->nsec = ts.tv_nsec;
return clock_type; return clock_type;
#elif defined(BOOST_HAS_MPTASKS)
using detail::thread::force_cast;
// the Mac OS does not have an MP-safe way of getting the date/time, so we use a
// delta from the startup time. We _could_ defer this and use something that is
// interrupt-safe, but this would be _SLOW_, and we need speed here.
const uint64_t k_ullNanosecondsPerSecond(1000ULL * 1000ULL * 1000ULL);
AbsoluteTime sUpTime(UpTime());
uint64_t ullNanoseconds(force_cast<uint64_t>(AbsoluteDeltaToNanoseconds(sUpTime, detail::g_sStartupTimeInfo.m_sStartupAbsoluteTime)));
uint64_t ullSeconds = (ullNanoseconds / k_ullNanosecondsPerSecond);
ullNanoseconds -= (ullSeconds * k_ullNanosecondsPerSecond);
xtp->sec = detail::g_sStartupTimeInfo.m_ulStartupSeconds + ullSeconds;
xtp->nsec = ullNanoseconds;
return clock_type;
#else #else
# error "xtime_get implementation undefined" # error "xtime_get implementation undefined"
#endif #endif

2
test/.cvsignore Normal file
View File

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

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