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

Compare commits

..

76 Commits

Author SHA1 Message Date
Beman Dawes
6f795dce04 Change +++m_count to ++m_count in three places
[SVN r11217]
2001-09-23 12:31:10 +00:00
Beman Dawes
7496ecbc73 sprintf -> std::sprintf + related workarounds
[SVN r11202]
2001-09-22 13:29:58 +00:00
Beman Dawes
76e80ee4c4 Added std:: to size_t in three places
[SVN r11173]
2001-09-20 18:46:11 +00:00
William E. Kempf
8e2536fc54 Updated for new config system.
[SVN r11168]
2001-09-20 14:52:42 +00:00
William E. Kempf
9bbbfbe6ff Fixed some extern "C" bugs.
[SVN r11153]
2001-09-19 17:52:44 +00:00
Beman Dawes
a2fc9ebfaa Fix broken links and other HTML changes related to new config system
[SVN r11142]
2001-09-18 21:24:51 +00:00
William E. Kempf
16c78b81e2 Fixed bug in pthread implementation.
[SVN r11125]
2001-09-14 17:47:09 +00:00
William E. Kempf
e71b204d10 Cleaned up code on warning level 4.
[SVN r11122]
2001-09-14 15:13:12 +00:00
William E. Kempf
f64208ce7a Third round of changes from the review.
[SVN r11109]
2001-09-12 21:29:42 +00:00
Beman Dawes
3410029cad Changes relating to addition of overview.html
[SVN r11103]
2001-09-12 14:38:03 +00:00
Beman Dawes
25fd0f52e7 Initial commit
[SVN r11102]
2001-09-12 14:36:32 +00:00
William E. Kempf
095f16c4f1 Made the constructors inline.
[SVN r11082]
2001-09-10 02:48:20 +00:00
William E. Kempf
5a4a5f405f Fixed bugs in the implementation found during review.
[SVN r11081]
2001-09-10 02:47:46 +00:00
William E. Kempf
7775aceb86 Third changes during review.
[SVN r11049]
2001-09-06 13:11:34 +00:00
William E. Kempf
29177b34a7 Second round of changes during review.
[SVN r11024]
2001-09-05 01:44:20 +00:00
Beman Dawes
ae1c315e0c Fixes after review of Bill's first batch of changes based on Formal Review comments.
[SVN r11021]
2001-09-04 17:16:22 +00:00
William E. Kempf
3592d8c412 First round of modifications during review.
[SVN r11001]
2001-09-03 18:08:35 +00:00
William E. Kempf
63fdf6ef22 Final modifications before submission.
[SVN r10961]
2001-08-30 00:51:17 +00:00
William E. Kempf
915c2cd206 Changed thread design. Updated code and documentation in preperation of submission.
[SVN r10952]
2001-08-28 20:19:37 +00:00
Beman Dawes
54abba952b Event rationale + minor other cleanups
[SVN r10884]
2001-08-17 12:07:35 +00:00
William E. Kempf
7cee797d2e Maded tss class an implementation detail and added thread_specific_ptr template.
[SVN r10873]
2001-08-15 20:49:42 +00:00
William E. Kempf
a7fb1e73d2 Cleaned up code for tss and once methods. Added unit tests for once methods.
[SVN r10838]
2001-08-10 20:47:02 +00:00
Beman Dawes
6a46149868 Added "share stack objects" Q&A
[SVN r10831]
2001-08-10 13:41:58 +00:00
Beman Dawes
f07d726011 Wording clarifications based on comments by Asger Alstrup Nielsen
[SVN r10830]
2001-08-10 12:22:37 +00:00
William E. Kempf
344ddb5fd2 Added tss cleanup functionality and once methods.
[SVN r10827]
2001-08-09 20:32:52 +00:00
Beman Dawes
537b623b18 Add two new questions
[SVN r10820]
2001-08-08 21:07:43 +00:00
Beman Dawes
ab180e79d1 Clarified Memory visibility between threads
[SVN r10798]
2001-08-07 14:45:35 +00:00
Beman Dawes
089dc81880 Major docs workover; use stylesheet, std doc form, show namespace boost in synopsis, rename locks basic_ -> scoped_, etc.
[SVN r10797]
2001-08-06 20:46:24 +00:00
Beman Dawes
73187a40b6 Initial commit
[SVN r10796]
2001-08-06 20:41:47 +00:00
Beman Dawes
3d06b18e3e Renamed from basic_*.html
[SVN r10795]
2001-08-06 20:41:02 +00:00
Beman Dawes
fd9d19b050 Renamed scoped_*.html
[SVN r10794]
2001-08-06 20:39:53 +00:00
William E. Kempf
692aa0e352 Moved lock types into boost::detail::thread. Renamed the lock types. Added locked() methods to lock types.
[SVN r10725]
2001-07-30 18:29:25 +00:00
Beman Dawes
307bbdc951 Format updated.
[SVN r10707]
2001-07-25 20:10:39 +00:00
Beman Dawes
b460053eda Make format consistent with other pages.
[SVN r10706]
2001-07-25 19:38:47 +00:00
Beman Dawes
df704a5dae "basic_lock" -> "scoped_lock" name changes. Added locked() member.
[SVN r10704]
2001-07-25 15:56:43 +00:00
Beman Dawes
9b76b71b5f Changes links format_thread_definition.html -> definitions.html
[SVN r10672]
2001-07-19 20:42:31 +00:00
Beman Dawes
427a109865 Renamed file; was thread_formal_definitions.html
[SVN r10671]
2001-07-19 20:41:30 +00:00
Beman Dawes
5662e2f6bb Remove prior to adding renamed (definitions.html) file
[SVN r10670]
2001-07-19 20:40:40 +00:00
Beman Dawes
6a6fbd0553 Change spelling "thread safe" to "thread-safe" and link to definition of the term. Fix other minor spelling errors.
[SVN r10669]
2001-07-19 20:24:45 +00:00
William E. Kempf
5084e9ccd2 Changed the documentation of basic_lock to describe proper lock() behavior.
Minor modifications to condition.html style.


[SVN r10668]
2001-07-19 18:36:43 +00:00
Beman Dawes
84cb093ee6 basic_lock and related updates
[SVN r10667]
2001-07-19 17:33:12 +00:00
Beman Dawes
8305cad4f8 Add entry, more uniformly apply citation tag
[SVN r10661]
2001-07-18 19:17:47 +00:00
William E. Kempf
b52c5d45ec Added new FAQ questions and cleaned up some documentation.
[SVN r10659]
2001-07-18 14:15:44 +00:00
Beman Dawes
71103fe1bc make wait and timed_wait formatting consistent
[SVN r10655]
2001-07-18 01:16:35 +00:00
Beman Dawes
57d262d4d6 Recast into stanard Boost.Threads doc form (Beman)
[SVN r10651]
2001-07-17 21:22:21 +00:00
Beman Dawes
acf721b0bd Minor changes
[SVN r10650]
2001-07-17 21:17:56 +00:00
William E. Kempf
3ee4bf04dc Fixed minor code changes.
[SVN r10639]
2001-07-16 20:48:39 +00:00
William E. Kempf
6e4a874880 Fixed minor code bugs and changed Jamfiles according to form suggested by Dave Abrahams.
[SVN r10638]
2001-07-16 20:47:48 +00:00
William E. Kempf
b07d60aa94 Updated tss.html for new documentation style. Fixed minor things in thread.html.
[SVN r10637]
2001-07-16 20:04:31 +00:00
William E. Kempf
fb3aed485c Added reference for POSA2.
[SVN r10636]
2001-07-16 18:45:53 +00:00
William E. Kempf
cbf212f1cd Added styles.css. Updated threads.html documentation for new look and design.
[SVN r10635]
2001-07-16 18:24:07 +00:00
Beman Dawes
562c4583d4 Add bibliography link
[SVN r10632]
2001-07-16 15:47:50 +00:00
Beman Dawes
95053b7516 Move Bibliography to separate page, minor tweeks
[SVN r10631]
2001-07-16 15:47:23 +00:00
Beman Dawes
65d06c138e Initial commit
[SVN r10630]
2001-07-16 15:46:04 +00:00
Dave Abrahams
9e3e80558c Repaired.
[SVN r10627]
2001-07-15 19:48:39 +00:00
William E. Kempf
d27e195ca2 Changed code that included exceptions.h to include exceptions.hpp.
[SVN r10601]
2001-07-12 20:36:04 +00:00
William E. Kempf
0ae839e0bb Applied patches for Unix/GNU toolset.
[SVN r10600]
2001-07-12 20:29:43 +00:00
William E. Kempf
21067cb309 Removed extraneous VC++ project files.
[SVN r10560]
2001-07-06 20:13:08 +00:00
Beman Dawes
5cb2a46ae4 Minor wording improvements, more references added
[SVN r10555]
2001-07-06 19:23:45 +00:00
William E. Kempf
66fa1995cf Fixed coding style to match proposed Boost guidelines.
[SVN r10550]
2001-07-06 18:23:40 +00:00
William E. Kempf
6e83cfdc72 Added a FAQ document.
[SVN r10549]
2001-07-06 18:02:56 +00:00
William E. Kempf
c2930faaec Added thread_group documentation.
[SVN r10544]
2001-07-05 19:29:05 +00:00
William E. Kempf
64ad66034a Updated thread documentation to reflect latest design.
[SVN r10543]
2001-07-05 19:11:07 +00:00
William E. Kempf
101e7cfbda Fixed the title.
[SVN r10541]
2001-07-05 18:40:12 +00:00
William E. Kempf
76de0ff7fd Added rationale documentation.
[SVN r10540]
2001-07-05 18:33:05 +00:00
William E. Kempf
f70b32cc63 Modified boost::thread to use a noncopyable design.
[SVN r10519]
2001-07-03 18:29:18 +00:00
William E. Kempf
8ce4eeca24 Changed boost::thread to use a noncopyable design.
[SVN r10518]
2001-07-03 18:28:10 +00:00
William E. Kempf
2febaf386c Modified to use Boost.Function for the threadproc.
[SVN r10437]
2001-06-26 19:20:11 +00:00
William E. Kempf
1d6f10702d Fixed bug (case sensitive subproject name) in jamfiles that prevented building.
[SVN r10434]
2001-06-26 15:40:59 +00:00
William E. Kempf
ebe3a7beee Update all Jamfiles for new build system. (Note: problem with <lib> pseudo-target)
[SVN r10428]
2001-06-25 21:53:57 +00:00
William E. Kempf
9e38dc5f48 Made WinThreads the default for MSVC, as it should have been to begin with.
[SVN r10427]
2001-06-25 21:52:35 +00:00
William E. Kempf
6dafed21fc First attempt at modifying Jamfiles for latest Boost.Build system.
[SVN r10425]
2001-06-25 18:15:31 +00:00
Beman Dawes
067d2a39f7 Integrate new Formal Definition of "Thread" page
[SVN r10365]
2001-06-20 22:49:44 +00:00
Beman Dawes
d70f46126b Replaced by _atomic.cpp
[SVN r10343]
2001-06-15 15:44:13 +00:00
Beman Dawes
b282e06a90 Initial commit
[SVN r10342]
2001-06-15 15:42:45 +00:00
nobody
abd2e68f8d This commit was manufactured by cvs2svn to create branch
'thread-initial'.

[SVN r10341]
2001-06-15 15:42:44 +00:00
55 changed files with 4135 additions and 4267 deletions

View File

@@ -23,27 +23,18 @@ subproject libs/thread/build ;
# TSS destruction. # TSS destruction.
if $(NT) if $(NT)
{ {
if $(PTW32) dll libboost_threadmon : ../src/threadmon.cpp
{ # requirements
PTW32_REQUIREMENTS = <define>BOOST_HAS_PTHREADS <define>PtW32NoCatchWarn ; : <threading>multi
} : debug release ;
else
{
dll libboost_threadmon : ../src/threadmon.cpp
# requirements
: <include>$(BOOST_ROOT)
<threading>multi
: debug release ;
}
} }
# Base names of the source files for 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 semaphore thread tss xtime once ;
lib libboost_thread : ../src/$(CPP_SOURCES).cpp lib libboost_thread : ../src/$(CPP_SOURCES).cpp
# requirements # requirements
: <include>$(BOOST_ROOT) : <include>$(BOOST_ROOT)
$(PTW32_REQUIREMENTS)
<threading>multi <threading>multi
: debug release ; : debug release ;

View File

@@ -1,77 +1,72 @@
<html> <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>
</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"> <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"> <table border="0" cellpadding="7" cellspacing="0" width="100%">
<h1 align="center">Boost.Threads</h1> <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 align="center">Acknowledgements</h2> <h2>Acknowledgments</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><a href="../../../people/william_kempf.htm">William E. Kempf</a> was <p>Important contributions were also made by Jeremy Siek (lots of input on
the architect, designer, and implementor of <b>Boost.Threads</b>.</p> 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>Important contributions were also made by Jeremy Siek (lots of input <p>The documentation was written by William E. Kempf. Beman Dawes provided
on the design and on the implementation), Alexander Terekhov (lots of additional documentation material and editing.</p>
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 <p>Discussions on the boost.org mailing list were essential in the development
provided additional documentation material and editing.</p> of <b>Boost.Threads</b>. As of August 1, 2001, participants included Alan Griffiths,
Albrecht Fritzsche, Aleksey Gurtovoy, Alexander Terekhov, Andrew Green, Andy Sawyer,
Asger Alstrup Nielsen, Beman Dawes, Bill Klein, Bill Rutiser, Bill Wade, Branko
Èibej, Brent Verner, Craig Henderson, Csaba Szepesvari, Dale Peakall, Damian
Dixon, Dan Nuffer, Darryl Green, Daryle Walker, David Abrahams, David Allan
Finch, Dejan Jelovic, Dietmar Kuehl, Doug Gregor, Douglas Gregor, Duncan Harris,
Ed Brey, Eric Swanson, Eugene Karpachov, Fabrice Truillot, Frank
Gerlach, Gary Powell, Gernot Neppert, Geurt Vos, Ghazi Ramadan, Greg Colvin,
Gregory Seidman, HYS, Iain Hanson, Ian Bruntlett, J Panzer, Jeff Garland, Jeff
Paquette, Jens Maurer, Jeremy Siek, Jesse Jones, Joe Gottman, John (EBo) David,
John Bandela, John Maddock, John Max Skaller, John Panzer, Jon Jagger , Karl
Nelson, Kevlin Henney, KG Chandrasekhar, Levente Farkas, Lie-Quan Lee, Lois
Goldthwaite, Luis Pedro Coelho, Marc Girod, Mark A. Borgerding, Mark Rodgers,
Marshall Clow, Matthew Austern, Matthew Hurd, Michael D. Crawford, Michael H.
Cox , Mike Haller, Miki Jovanovic, Nathan Myers, Paul Moore, Pavel Cisler, Peter
Dimov, Petr Kocmid, Philip Nash, Rainer Deyke, Reid Sweatman, Ross Smith, Scott
McCaskill, Shalom Reich , Steve Cleary, Steven Kirk, Thomas Holenstein, Thomas
Matelich, Trevor Perrin, Valentin Bonnard, Vesa Karvonen, Wayne Miller, and
William Kempf.</p>
<p>Discussions on the boost.org mailing list were essential in the <p>Apologies for anyone inadvertently missed.</p>
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>
<hr>
<p>Revised <p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->29 August, 2001<!--webbot bot="Timestamp" endspan i-checksum="34360" -->
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p> </p>
<p>©<i> Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001</i></p>
</body>
<p>&copy; <i>Copyright <a href="mailto:williamkempf@hotmail.com">
William E. Kempf</a> 2001</i></p>
</body>
</html> </html>

View File

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

View File

@@ -1,52 +1,48 @@
<html> <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>
</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"> <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"> <table border="0" cellpadding="7" cellspacing="0" width="100%">
<h1 align="center">Boost.Threads</h1> <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>
<h2 align="center">call_once</h2> <hr>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br> <p><A href="#Introduction">Introduction</A><br>
<a href="#Header">Header</a><br> <A href="#Header">Header</A><br>
<a href="#Synopsis">Synopsis</a><br> <A href="#Synopsis">Synopsis</A><br>
<a href="#Members">Members</a><br> <A href="#Members">Members</A><br>
<a href="#Example">Example</a></p> <A href="#Example">Example</A></p>
<h2><a name="Introduction">Introduction</a></h2> <h2><a name="Introduction">Introduction</a></h2>
<p>The <code>call_once</code> routine and <code>once_flag</code> type <p>The <code>call_once</code> routine and <code>once_flag</code> type can be used to
can be used to run a routine exactly once. This can be used to run a routine exactly once. This can be used to initialize data in a
initialize data in a <a href="definitions.html#Thread-safe"> <a href="definitions.html#Thread-safe">thread-safe</a> manner.</p>
thread-safe</a> manner.</p>
<h2><a name="Header">Header</a></h2>
<h2><a name="Header">Header</a></h2>
<pre> <pre>
#include <a href= #include <a href="../../../boost/thread/once.hpp">&lt;boost/thread/once.hpp&gt;</a>
"../../../boost/thread/once.hpp">&lt;boost/thread/once.hpp&gt;</a>
</pre> </pre>
<h2><a name="Synopsis">Synopsis</a></h2> <h2><a name="Synopsis">Synopsis</a></h2>
<pre> <pre>
namespace boost { namespace boost {
@@ -57,45 +53,44 @@ void call_once(void (*func)(), once_flag&amp; flag);
} // namespace boost } // namespace boost
</pre> </pre>
<h2><a name="Reference">Reference</a></h2> <h2><a name="Reference">Reference</a></h2>
<hr>
<h3>once_flag</h3> <hr>
<h3>once_flag</h3>
<p>This implementation defined type is used as a flag to insure a <p>This implementation defined type is used as a flag to insure a routine is called only once.
routine is called only once. Instances of this type should be Instances of this type should be statically initialized to <code>once_init</code>.</p>
statically initialized to <code>once_init</code>.</p>
<hr>
<h3>once_init</h3> <hr>
<h3>once_init</h3>
<p>This is a constant value used to initialize <code>once_flag</code> <p>This is a constant value used to initialize <code>once_flag</code> instances
instances to indicate that the logically associated routine has not to indicate that the logically associated routine has not been run yet.</p>
been run yet.</p>
<hr> <hr>
<h3>call_once</h3>
<h3>call_once</h3>
<pre> <pre>
void call_once(void (*func)(), once_flag&amp; flag); void call_once(void (*func)(), once_flag&amp; flag);
</pre> </pre>
<p><b>Requires:</b> The function <code>func</code> shall not throw <p><b>Requires:</b> The function <code>func</code> shall not throw exceptions.</p>
exceptions.</p>
<p><b>Effects:</b> As if (in an atomic fashion)</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> <code>
once_init</code></p> &nbsp;&nbsp;&nbsp;if (flag == once_init)<br>
<hr> &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>
<h2><a name="Example">Example Usage</a></h2>
<pre> <pre>
#include <a href= #include <a href="../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
"../../../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 <a href=
"../../../boost/thread/tss.hpp">&lt;boost/thread/once.hpp&gt;</a>
#include &lt;cassert&gt; #include &lt;cassert&gt;
int value=0; int value=0;
@@ -103,7 +98,7 @@ boost::once_flag once = boost::once_init;
void init() void init()
{ {
++value; ++value;
} }
void thread_proc() void thread_proc()
@@ -120,13 +115,14 @@ int main(int argc, char* argv[])
assert(value == 1); assert(value == 1);
} }
</pre> </pre>
<hr>
<p>Revised <hr>
<!--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"> <p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39334" -->
William E. Kempf</a> 2001 all rights reserved.</i></p> </p>
</body>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html> </html>

View File

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

View File

@@ -1,97 +1,103 @@
<html> <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>
</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"> <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"> <table border="0" cellpadding="7" cellspacing="0" width="100%">
<h1 align="center">Boost.Threads</h1> <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>
<h2 align="center">Configuration Information</h2> <hr>
</td>
</tr>
</table>
<hr>
<p><b>Boost.Threads</b> uses several configuration macros in <a href= <p><b>Boost.Threads</b> uses several configuration macros in <a href="../../config/config.htm"> &lt;boost/config.hpp&gt;</a>.
"../../config/config.htm">&lt;boost/config.hpp&gt;</a>. These macros These macros are documented here. Most of the macros are
are documented here. Most of the macros are of interest only to of interest only to developers attempting to provide new implementations of <b>Boost.Threads</b>.
developers attempting to provide new implementations of <b> The one exception to this is BOOST_HAS_THREADS.</p>
Boost.Threads</b>. The one exception to this is BOOST_HAS_THREADS.</p>
<table summary="macros" cellspacing="10" width="100%"> <table cellspacing="10" width="100%">
<tr> <tr>
<td valign="top"><b>Macro</b> </td> <td valign="top">
<b>Macro</b>
</td>
<td valign="top">
<b>Meaning</b>
</td>
</tr>
<tr>
<td valign="top">
BOOST_HAS_THREADS
</td>
<td valign="top">
Indicates that threading support is available. This means both that there is a
platform specific implementation for <b>Boost.Threads</b> and that threading
support has been enabled in a platform specific manner. For instance, on the
Win32 platform there's an implementation for <b>Boost.Threads</b> but unless
the program is compiled against one of the multi-threading runtimes
(often determined by the
compiler predefining the macro _MT) the
BOOST_HAS_THREADS macro remains undefined.
</td>
</tr>
<tr>
<td valign="top">
BOOST_HAS_WINTHREADS
</td>
<td valign="top">
Indicates that the platform has the Microsoft Win32 threading libraries,
and that they should be used
to implement <b>Boost.Threads</b>.
</td>
</tr>
<tr>
<td valign="top">
BOOST_HAS_PTHREADS
</td>
<td valign="top">
Indicates that the platform has the POSIX pthreads libraries, and that
they should be used
to implement <b>Boost.Threads</b>.
</td>
</tr>
<tr>
<td valign="top">
BOOST_HAS_FTIME
</td>
<td valign="top">
Indicates that the implementation should use GetSystemTimeAsFileTime() and
the FILETIME type to calculate the current time. This is an implementation
detail used by boost::detail::getcurtime().
</td>
</tr>
<tr>
<td valign="top">
BOOST_HAS_GETTTIMEOFDAY
</td>
<td valign="top">
Indicates that the implementation should use gettimeofday() to calculate the
current time. This is an implementation detail used by boost::detail::getcurtime().
</td>
</tr>
</table>
<hr>
<td valign="top"><b>Meaning</b> </td> <p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->18 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39344" -->
</tr> </p>
<tr> <p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
<td valign="top">BOOST_HAS_THREADS</td> 2001 all rights reserved.</i></p>
<td valign="top">Indicates that threading support is available. </body>
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> </html>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,52 +1,49 @@
<html> <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>
</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"> <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"> <table border="0" cellpadding="7" cellspacing="0" width="100%">
<h1 align="center">Boost.Threads</h1> <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>
<h2 align="center">lock_error</h2> <hr>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br> <p><a href="#Introduction">Introduction</a><br>
<a href="#Header">Header</a><br> <a href="#Header">Header</a><br>
<a href="#Synopsis">Synopsis</a><br> <a href="#Synopsis">Synopsis</a><br>
<a href="#Members">Members</a><br> <a href="#Members">Members</a><br>
<a href="#Example">Example</a></p> <a href="#Example">Example</a></p>
<h2><a name="Introduction">Introduction</a></h2> <h2><a name="Introduction">Introduction</a></h2>
<p>The <tt>lock_error</tt> class defines an exception type thrown to <p>The <tt>lock_error</tt> class defines an exception type thrown to indicate a
indicate a locking related error has been detected. Examples of such locking related error has been detected. Examples of such errors include a lock
errors include a lock operation which can be determined to result in a operation which can be determined to result in a deadlock, or unlock operations
deadlock, or unlock operations attempted by a thread that does not own attempted by a thread that does not own the lock.</p>
the lock.</p>
<h2><a name="Header">Header</a></h2>
<h2><a name="Header">Header</a></h2>
<pre> <pre>
#include <a href= #include <a href="../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
"../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
</pre> </pre>
<h2><a name="Synopsis">Synopsis</a></h2> <h2><a name="Synopsis">Synopsis</a></h2>
<pre> <pre>
namespace boost namespace boost
@@ -58,23 +55,25 @@ namespace boost
} }
</pre> </pre>
<h2><a name="Members">Members</a></h2> <h2><a name="Members">Members</a></h2>
<hr>
<hr>
<h3>Constructor</h3>
<h3>Constructor</h3>
<pre> <pre>
lock_error(); lock_error();
</pre> </pre>
<p>Constructs a <tt>lock_error</tt> object.</p> <p>Constructs a <tt>lock_error</tt> object.</p>
<hr>
<hr>
<h2><a name="Example">Example</a> Usage</h2>
<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> #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;
int main(int, char*[]) int main(int, char*[])
@@ -94,17 +93,19 @@ int main(int, char*[])
} }
</pre> </pre>
<p>The output is:</p> <p>The output is:</p>
<pre> <pre>
thread lock error - deadlock occurred. thread lock error - deadlock occurred.
</pre> </pre>
<hr>
<p>Revised <hr>
<!--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"> <p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->10 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39328" -->
William E. Kempf</a> 2001 all rights reserved.</i></p> </p>
</body>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html> </html>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -124,7 +124,7 @@ int test_main(int, char*[])
<hr> <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>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->06 August, 2001<!--webbot bot="Timestamp" endspan i-checksum="34352" -->
</p> </p>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a> <p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>

View File

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

View File

@@ -1,87 +1,78 @@
<html> <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>
</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"> <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"> <table border="0" cellpadding="7" cellspacing="0" width="100%">
<h1 align="center">Boost.Threads</h1> <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>
<h2 align="center">scoped_timed_lock</h2> <hr>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br> <p><a href="#Introduction">Introduction</a><br>
<a href="#Header">Header</a><br> <a href="#Header">Header</a><br>
<a href="#Synopsis">Synopsis</a><br> <a href="#Synopsis">Synopsis</a><br>
<a href="#Members">Members</a><br> <a href="#Members">Members</a><br>
<a href="#Example">Example</a></p> <a href="#Example">Example</a></p>
<h2><a name="Introduction">Introduction</a></h2> <h2><a name="Introduction">Introduction</a></h2>
<p>This class template defines a generic lock type which meets the <a <p>This class template defines a generic lock type which meets the
href="lock_concept.html#ScopedTimedLock">ScopedTimedLock</a> <a href="lock_concept.html#ScopedTimedLock">ScopedTimedLock</a> requirements. The
requirements. The <a href="mutex.html">timed_mutex</a> and <a href= <a href="mutex.html">timed_mutex</a> and
"recursive_mutex.html">recursive_timed_mutex</a> classes use this <a href="recursive_mutex.html">recursive_timed_mutex</a> classes use this template to
template to define their <code>scoped_timed_lock</code> types.</p> define their <code>scoped_timed_lock</code> types.</p>
<p>Like all the <b>Boost.Threads</b> <a href="lock_concept.html">lock <p>Like all the <b>Boost.Threads</b> <a href="lock_concept.html">lock models</a>,
models</a>, <code>scoped_timed_lock</code> objects are meant to be <code>scoped_timed_lock</code> objects are meant to be short-lived. Objects of the
short-lived. Objects of the class are not <a href= class are not <a href="definitions.html#thread-safe">thread-safe</a>, and so should
"definitions.html#thread-safe">thread-safe</a>, and so should not be not be shared between threads.</p>
shared between threads.</p>
<p>Class <code>scoped_timed_lock</code> follows the &quot;resource <p>Class <code>scoped_timed_lock</code> follows the &quot;resource acquisition is
acquisition is initialization&quot; idiom <a href= initialization&quot; idiom <a href="bibliography.html#Stroustrup-00">[Stroustrup
"bibliography.html#Stroustrup-00">[Stroustrup 00 14.4.1]</a> and is a 00 14.4.1]</a> and is a realization of the &quot;Scoped Locking Pattern&quot;
realization of the &quot;Scoped Locking Pattern&quot; <a href= <a href="bibliography.html#Schmidt-00">[Schmidt-00]</a>. Thus the usage is to let the
"bibliography.html#Schmidt-00">[Schmidt-00]</a>. Thus the usage is to constructor do the locking, and then let the destructor do the unlocking automatically
let the constructor do the locking, and then let the destructor do the at the end of the enclosing scope. The lock() and unlock() members are usually not
unlocking automatically at the end of the enclosing scope. The lock() explicitly called, but are provided to allow for complex overlapping locks of multiple
and unlock() members are usually not explicitly called, but are mutexes.</p>
provided to allow for complex overlapping locks of multiple
mutexes.</p>
<p>The type used to instantiate the class must meet the <a href= <p>The type used to instantiate the class must meet the
"mutex_concept.html#TimedMutex">TimedMutex</a> requirements.</p> <a href="mutex_concept.html#TimedMutex">TimedMutex</a> requirements.</p>
<p>Although this class is an implementation detail, it is publicly <p>Although this class is an implementation detail, it is publicly documented here because
documented here because of its importance.</p> of its importance.</p>
<h2><a name="Header">Header</a></h2>
<h2><a name="Header">Header</a></h2>
<pre> <pre>
#include <a href= #include <a href="../../../boost/thread/detail/lock.hpp">&lt;boost/thread/detail/lock.hpp&gt;</a>
"../../../boost/thread/detail/lock.hpp">&lt;boost/thread/detail/lock.hpp&gt;</a>
<i>This header is usually not included directly by programmers <i>This header is usually not included directly by programmers
because it is supplied by <a href= because it is supplied by <a href="../../../boost/thread/mutex.hpp">&lt;boost/thread/mutex.hpp&gt;</a> or
"../../../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>
<a href=
"../../../boost/thread/recursive_mutex.hpp">&lt;boost/thread/recursive_mutex.hpp&gt;</a></i>
</pre> </pre>
<h2><a name="Synopsis">Synopsis</a></h2> <h2><a name="Synopsis">Synopsis</a></h2>
<pre> <pre>
namespace boost { namespace detail { namespace thread { namespace boost { namespace detail { namespace thread {
template &lt;typename TimedMutex&gt; template &lt;typename TimedMutex&gt;
class scoped_timed_lock : private <a href= class scoped_timed_lock : private <a href="../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
"../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only. // Class scoped_timed_lock meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
// Class scoped_timed_lock meets the <a href=
"overview.html#NonCopyable">NonCopyable</a> requirement.
{ {
public: public:
typedef TimedMutex mutex_type; typedef TimedMutex mutex_type;
@@ -101,137 +92,138 @@ namespace boost { namespace detail { namespace thread {
} // namespace boost } // namespace boost
</pre> </pre>
<h2><a name="Members">Members</a></h2> <h2><a name="Members">Members</a></h2>
<hr>
<hr>
<h3>Constructor</h3>
<h3>Constructor</h3>
<pre> <pre>
scoped_timed_lock(TimedMutex&amp; mx, const <a href= scoped_timed_lock(TimedMutex&amp; mx, const <a href="xtime.html">xtime</a>&amp; xt);
"xtime.html">xtime</a>&amp; xt);
</pre> </pre>
<p><b>Effects:</b> Associates mutex <code>mx</code> with <code> <p><b>Effects:</b> Associates mutex <code>mx</code> with <code>*this</code>.
*this</code>. Calls <code>timed_lock</code>( <code>xt</code>)</p> Calls <code>timed_lock</code>( <code>xt</code>)</p>
<hr>
<hr>
<pre> <pre>
scoped_timed_lock(TimedMutex&amp; mx, bool initially_locked); scoped_timed_lock(TimedMutex&amp; mx, bool initially_locked);
</pre> </pre>
<p><b>Effects:</b> Associates mutex <code>mx</code> with <code> <p><b>Effects:</b> Associates mutex <code>mx</code> with <code>*this</code>.
*this</code>. If <code>initially_locked</code> is <code>true</code>, If <code>initially_locked</code> is <code>true</code>, calls <code>lock()</code>.</p>
calls <code>lock()</code>.</p>
<hr> <hr>
<h3>Destructor</h3>
<h3>Destructor</h3>
<pre> <pre>
~scoped_timed_lock(); ~scoped_timed_lock();
</pre> </pre>
<p><b>Effects:</b> If <code>locked()</code>, calls <code> <p><b>Effects:</b> If <code> locked()</code>, calls <code>unlock()</code>. Destroys
unlock()</code>. Destroys <code>*this</code>.</p> <code>*this</code>.</p>
<hr>
<hr>
<h3>lock</h3>
<h3>lock</h3>
<pre> <pre>
void lock(); void lock();
</pre> </pre>
<p><b>Effects:</b> If the associated mutex is already locked by another <p><b>Effects:</b> If the associated mutex is already locked by another lock in the
lock in the current thread, the effects depend on the locking strategy current thread, the effects depend on the locking strategy of the associated mutex, as
of the associated mutex, as shown in the following table:</p> shown in the following table:</p>
<table summary="lock effects" border="1" cellpadding="5"> <table border="1" cellpadding="5">
<tr> <tr>
<td><i><a href="mutex_concept.html#LockingStrategies">Locking <td><i><a href="mutex_concept.html#LockingStrategies">Locking Strategy</a><br>
Strategy</a><br> of associated mutex</i></td>
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>
<td><i>Effect if associated mutex is already locked by the <p>If the associated mutex is already locked by some other thread, places the
current thread</i></td> current thread in the <a href="definitions.html#State">Blocked</a> state until
</tr> 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.
<tr> <p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>locked()</code> or
<td>Recursive</td> as indicated in <b>Effects</b>.</p>
<td>As if an additional lock were added to the mutex.</td> <hr>
</tr>
<tr> <h3>timed_lock</h3>
<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> <pre>
bool timed_lock(const <a href="xtime.html">xtime</a>&amp; xt); bool timed_lock(const <a href="xtime.html">xtime</a>&amp; xt);
</pre> </pre>
<p><b>Effects:</b> Same as <code>lock()</code>, except that if xt is <p><b>Effects:</b> Same as <code>lock()</code>, except that if xt is reached,
reached, places the current thread in the <a href= places the current thread in the <a href="definitions.html#State">Ready</a>
"definitions.html#State">Ready</a> state without further ado.</p> state without further ado.</p>
<p><b>Returns:</b> <code>locked()</code>.</p> <p><b>Returns:</b> <code>locked()</code>.</p>
<p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code> <p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>locked()</code> or
locked()</code> or as indicated in <b>Effects</b>.</p> as indicated in <b>Effects</b>.</p>
<hr>
<hr>
<h3>unlock</h3>
<h3>unlock</h3>
<pre> <pre>
void unlock(); void unlock();
</pre> </pre>
<p><b>Effects:</b> Unlocks the associated mutex.</p> <p><b>Effects: </b>Unlocks the associated mutex.</p>
<p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code> <p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>!locked()</code>.</p>
!locked()</code>.</p>
<hr> <hr>
<h3>const void* Conversion</h3>
<h3>const void* Conversion</h3>
<pre> <pre>
operator const void*() const; operator const void*() const;
</pre> </pre>
<p><b>Returns:</b> If the associated mutex is currently locked, a value <p><b>Returns:</b> If the associated mutex is currently locked, a value convertible to
convertible to <code>true</code>, else a value convertible to <code> <code>true</code>, else a value convertible to <code>false</code>.</p>
false</code>.</p>
<p><b>Rationale:</b> A <code>const void*</code> conversion is <p><b>Rationale:</b> A <code>const void*</code> conversion is considered safer than a
considered safer than a conversion to <code>bool</code>.</p> conversion to <code>bool</code>.</p>
<hr>
<hr>
<h3>locked</h3>
<h3>locked</h3>
<pre> <pre>
bool locked() const; bool locked() const;
</pre> </pre>
<p><b>Returns:</b> <code>this-&gt;operator const void*() != <p><b>Returns:</b> <code>this-&gt;operator const void*() != 0</code>.</p>
0</code>.</p>
<hr> <hr>
<h2><a name="Example">Example</a> Usage</h2>
<h2><a name="Example">Example</a> Usage</h2>
<pre> <pre>
#include &lt;boost/thread/mutex.hpp&gt; #include &lt;boost/thread/mutex.hpp&gt;
#include &lt;iostream&gt; #include &lt;iostream&gt;
@@ -251,17 +243,19 @@ int main(int, char*[])
} }
</pre> </pre>
<p>The output is:</p> <p>The output is:</p>
<pre> <pre>
locked locked
</pre> </pre>
<hr>
<p>Revised <hr>
<!--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"> <p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%B %d, %Y" startspan -->September 13, 2001<!--webbot bot="Timestamp" endspan i-checksum="37965" -->
William E. Kempf</a> 2001 all rights reserved.</i></p> </p>
</body>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html> </html>

View File

@@ -1,89 +1,78 @@
<html> <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>
</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"> <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"> <table border="0" cellpadding="7" cellspacing="0" width="100%">
<h1 align="center">Boost.Threads</h1> <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>
<h2 align="center">scoped_try_lock</h2> <hr>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br> <p><a href="#Introduction">Introduction</a><br>
<a href="#Header">Header</a><br> <a href="#Header">Header</a><br>
<a href="#Synopsis">Synopsis</a><br> <a href="#Synopsis">Synopsis</a><br>
<a href="#Members">Members</a><br> <a href="#Members">Members</a><br>
<a href="#Example">Example</a></p> <a href="#Example">Example</a></p>
<h2><a name="Introduction">Introduction</a></h2> <h2><a name="Introduction">Introduction</a></h2>
<p>This class template defines a generic lock type which meets the <a <p>This class template defines a generic lock type which meets the
href="lock_concept.html#ScopedTryLock">ScopedTryLock</a> requirements. <a href="lock_concept.html#ScopedTryLock">ScopedTryLock</a> requirements. The
The <a href="mutex.html">try_mutex</a>, <a href="mutex.html"> <a href="mutex.html">try_mutex</a>, <a href="mutex.html">timed_mutex</a>,
timed_mutex</a>, <a href="recursive_mutex.html">recursive_try_mutex</a> <a href="recursive_mutex.html">recursive_try_mutex</a> and
and <a href="recursive_mutex.html">recursive_timed_mutex</a> classes <a href="recursive_mutex.html">recursive_timed_mutex</a> classes use this template
use this template to define their <code>scoped_try_lock</code> to define their <code>scoped_try_lock</code> types.</p>
types.</p>
<p>Like all the <b>Boost.Threads</b> <a href="lock_concept.html">lock <p>Like all the <b>Boost.Threads</b> <a href="lock_concept.html">lock models</a>,
models</a>, <code>scoped_try_lock</code> objects are meant to be <code>scoped_try_lock</code> objects are meant to be short-lived. Objects of the
short-lived. Objects of the class are not <a href= class are not <a href="definitions.html#thread-safe">thread-safe</a>, and
"definitions.html#thread-safe">thread-safe</a>, and so should not be so should not be shared between threads.</p>
shared between threads.</p>
<p>Class <code>scoped_try_lock</code> follows the &quot;resource <p>Class <code> scoped_try_lock</code> follows the &quot;resource acquisition is
acquisition is initialization&quot; idiom <a href= initialization&quot; idiom <a href="bibliography.html#Stroustrup-00">[Stroustrup
"bibliography.html#Stroustrup-00">[Stroustrup 00 14.4.1]</a> and is a 00 14.4.1]</a> and is a realization of the &quot;Scoped Locking Pattern&quot;
realization of the &quot;Scoped Locking Pattern&quot; <a href= <a href="bibliography.html#Schmidt-00">[Schmidt-00]</a>. Thus the usage is to let the
"bibliography.html#Schmidt-00">[Schmidt-00]</a>. Thus the usage is to constructor do the locking, and then let the destructor do the unlocking automatically at
let the constructor do the locking, and then let the destructor do the the end of the enclosing scope. The lock() and unlock() members are usually not
unlocking automatically at the end of the enclosing scope. The lock() explicitly called, but are provided to allow for complex overlapping locks of multiple
and unlock() members are usually not explicitly called, but are mutexes.</p>
provided to allow for complex overlapping locks of multiple
mutexes.</p>
<p>Although this class is an implementation detail, it is publicly <p>Although this class is an implementation detail, it is publicly documented here because
documented here because of its importance.</p> of its importance.</p>
<p>The type used to instantiate the class must meet the <a href= <p>The type used to instantiate the class must meet the <a href="mutex_concept.html#TryMutex">TryMutex</a> requirements.</p>
"mutex_concept.html#TryMutex">TryMutex</a> requirements.</p>
<h2><a name="Header">Header</a></h2>
<h2><a name="Header">Header</a></h2>
<pre> <pre>
#include <a href= #include <a href="../../../boost/thread/detail/lock.hpp">&lt;boost/thread/detail/lock.hpp&gt;</a>
"../../../boost/thread/detail/lock.hpp">&lt;boost/thread/detail/lock.hpp&gt;</a>
<i>This header is usually not included directly by programmers <i>This header is usually not included directly by programmers
because it is supplied by <a href= because it is supplied by <a href="../../../boost/thread/mutex.hpp">&lt;boost/thread/mutex.hpp&gt;</a> or
"../../../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>
<a href=
"../../../boost/thread/recursive_mutex.hpp">&lt;boost/thread/recursive_mutex.hpp&gt;</a></i>
</pre> </pre>
<h2><a name="Synopsis">Synopsis</a></h2> <h2><a name="Synopsis">Synopsis</a></h2>
<pre> <pre>
namespace boost { namespace detail { namespace thread { namespace boost { namespace detail { namespace thread {
template &lt;typename TryMutex&gt; template &lt;typename TryMutex&gt;
class scoped_try_lock : private <a href= class scoped_try_lock : private <a href="../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
"../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only. // Class scoped_try_lock meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
// Class scoped_try_lock meets the <a href=
"overview.html#NonCopyable">NonCopyable</a> requirement.
{ {
public: public:
typedef TryMutex mutex_type; typedef TryMutex mutex_type;
@@ -103,178 +92,164 @@ namespace boost { namespace detail { namespace thread {
} // namespace boost } // namespace boost
</pre> </pre>
<h2><a name="Members">Members</a></h2> <h2><a name="Members">Members</a></h2>
<hr>
<hr>
<h3>Constructors</h3>
<h3>Constructors</h3>
<pre> <pre>
explicit scoped_try_lock(TryMutex&amp; mx); explicit scoped_try_lock(TryMutex&amp; mx);
</pre> </pre>
<p><b>Effects:</b> Associates mutex <code>mx</code> with <code> <p><b>Effects:</b> Associates mutex <code>mx</code> with <code>*this</code>.
*this</code>. Calls <code>try_lock()</code>.</p> Calls <code>try_lock()</code>.</p>
<hr>
<hr>
<pre> <pre>
scoped_try_lock(TryMutex&amp; mx, bool initially_locked); scoped_try_lock(TryMutex&amp; mx, bool initially_locked);
</pre> </pre>
<p><b>Effects:</b> Associates mutex <code>mx</code> with <code> <p><b>Effects:</b> Associates mutex <code>mx</code> with <code>*this</code>.
*this</code>. If <code>initially_locked</code> is <code>true,</code> If <code>initially_locked</code> is <code>true,</code> calls <code>lock()</code>.</p>
calls <code>lock()</code>.</p> <hr>
<hr>
<h3>Destructor</h3>
<h3>Destructor</h3>
<pre> <pre>
~scoped_try_lock(); ~scoped_try_lock();
</pre> </pre>
<p><b>Effects:</b> If <code>locked()</code>, calls <code> <p><b>Effects:</b> If <code>locked()</code>, calls <code>unlock()</code>. Destroys
unlock()</code>. Destroys <code>*this</code>.</p> <code>*this</code>.</p>
<hr>
<hr>
<h3>lock</h3>
<h3>lock</h3>
<pre> <pre>
void lock(); void lock();
</pre> </pre>
<p><b>Effects:</b> If the associated mutex is already locked by another <p><b>Effects:</b> If the associated mutex is already locked by another lock in the
lock in the current thread, the effects depend on the locking strategy current thread, the effects depend on the locking strategy of the associated mutex, as
of the associated mutex, as shown in the following table:</p> shown in the following table:</p>
<table summary="lock effects" border="1" cellpadding="5" height="147"> <table border="1" cellpadding="5" height="147">
<tr> <tr>
<td height="34"><i><a href= <td height="34"><i><a href="mutex_concept.html#LockingStrategies">Locking Strategy</a><br>
"mutex_concept.html#LockingStrategies">Locking Strategy</a><br> of associated mutex</i></td>
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>
<td height="34"><i>Effect if associated mutex is already locked <p>If the associated mutex is already locked by some other thread, places the
by the current thread</i></td> current thread in the <a href="definitions.html#State">Blocked</a> state until
</tr> 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>
<tr> <p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>locked()</code> or
<td height="19">Recursive</td> as indicated in <b>Effects</b>.</p>
<td height="19">As if an additional lock were added to the <hr>
mutex.</td>
</tr>
<tr> <h3>try_lock</h3>
<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> <pre>
bool try_lock(); bool try_lock();
</pre> </pre>
<p><b>Effects:</b> If the associated mutex is already locked by another <p><b>Effects:</b> If the associated mutex is already locked by another lock in the
lock in the current thread, the effects depend on the locking strategy current thread, the effects depend on the locking strategy of the associated mutex, as
of the associated mutex, as shown in the following table:</p> shown in the following table:</p>
<table summary="try_lock effects" border="1" cellpadding="5" height= <table border="1" cellpadding="5" height="147">
"147"> <tr>
<tr> <td height="34"><i><a href="mutex_concept.html#LockingStrategies">Locking Strategy</a><br>
<td height="34"><i><a href= of associated mutex</i></td>
"mutex_concept.html#LockingStrategies">Locking Strategy</a><br> <td height="34"><i>Effect if associated mutex is already locked by the
of associated mutex</i></td> 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>
<td height="34"><i>Effect if associated mutex is already locked <p>If the associated mutex is not already locked by some other thread, locks the
by the current thread</i></td> associated mutex and returns true, else returns false.</p>
</tr>
<tr> <p><b>Returns:</b> See effects.</p>
<td height="19">Recursive</td>
<td height="19">As if an additional lock were added to the <p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>locked()</code> or
mutex.</td> as indicated in <b>Effects</b>.</p>
</tr>
<tr> <hr>
<td height="19">Checked</td>
<td height="19">Throws <a href="lock_error.html"> <h3>unlock</h3>
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> <pre>
void unlock(); void unlock();
</pre> </pre>
<p><b>Effects:</b> Unlocks the associated mutex.</p> <p><b>Effects: </b>Unlocks the associated mutex.</p>
<p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code> <p><b>Throws:</b> <a href="lock_error.html">lock_error</a> if <code>!locked()</code>.</p>
!locked()</code>.</p>
<hr> <hr>
<h3>const void* Conversion</h3>
<h3>const void* Conversion</h3>
<pre> <pre>
operator const void*() const; operator const void*() const;
</pre> </pre>
<p><b>Returns:</b> If the associated mutex is currently locked, a value <p><b>Returns:</b> If the associated mutex is currently locked, a value convertible to
convertible to <code>true</code>, else a value convertible to <code> <code>true</code>, else a value convertible to <code>false</code>.</p>
false</code>.</p>
<p><b>Rationale:</b> A <code>const void*</code> conversion is <p><b>Rationale:</b> A <code>const void*</code> conversion is considered safer
considered safer than a conversion to <code>bool</code>.</p> than a conversion to <code>bool</code>.</p>
<hr>
<hr>
<h3>locked</h3>
<h3>locked</h3>
<pre> <pre>
bool locked() const; bool locked() const;
</pre> </pre>
<p><b>Returns:</b> <code>this-&gt;operator const void*() != <p><b>Returns:</b> <code>this-&gt;operator const void*() != 0</code>.</p>
0</code>.</p>
<hr> <hr>
<h2><a name="Example">Example</a> Usage</h2>
<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>
#include &lt;iostream&gt; #include &lt;iostream&gt;
int main(int, char*[]) int main(int, char*[])
@@ -289,17 +264,19 @@ int main(int, char*[])
} }
</pre> </pre>
<p>The output is:</p> <p>The output is:</p>
<pre> <pre>
locked locked
</pre> </pre>
<hr>
<p>Revised <hr>
<!--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"> <p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39334" -->
William E. Kempf</a> 2001 all rights reserved.</i></p> </p>
</body>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html> </html>

226
doc/semaphore.html Normal file
View File

@@ -0,0 +1,226 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, BTL, thread library, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost.Threads, semaphore</title>
</head>
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%">
<tr>
<td valign="top" width="300">
<h3><IMG height=86 alt="C++ Boost" src="../../../c++boost.gif" width=277></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">semaphore</h2>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br>
<a href="#Header">Header</a><br>
<a href="#Synopsis">Synopsis</a><br>
<a href="#Members">Members</a><br>
<a href="#Example">Example</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <tt>semaphore</tt> class defines a classic synchronization primitive invented by the
Dutch computer scientist Edsger W. Dijkstra. A semaphore manages an internal counter. This
counter never goes below zero, or above a specified maximum value. When calling
<tt>semaphore::down</tt> the calling thread will block until the value is non-zero and then
decrement the value in a single atomic operation. When calling <tt>semaphore::up</tt> the
calling thread will increment the value in a single atomic operation, failing if the value has
already reached the specified maximum.</p>
<p><b>Rationale:</b> The semaphore is the simplest synchronization primitive available and is generally the
primitive used to build other synchronization concepts at some level of implementation. For this
reason <b>Boost.Threads</b> defines the <tt>semaphore</tt> type in the classic form. This simplifies
usage and implementation, but it means that the interface is not as safe as other <b>Boost.Threads</b>
interfaces.</p>
<p><b><a name="Danger">Danger</a>:</b> Unlike the <A href="mutex_concept.html">mutex models</a> supplied by <b>Boost.Threads,</b>
there is no <A href="lock_concept.html">lock_concept</a> for the semaphore to help ensure proper
usage. Great care must be taken when using a <tt>semaphore</tt> object to ensure
<a href="definitions.html#Deadlock"> deadlock</a> or <a href="definitions.html#Race condition">race conditions</a> do not occur.&nbsp;</p>
<p>The dangers are spelled out by <a href="bibliography.html#Andrews-83">[Andrews-83]</a>
(function names updated, see historical note below):&nbsp;</p>
<blockquote>
<p>Although semaphores can be used to program almost any kind of synchronization,
<b>down()</b> and <b>up()</b> are rather unstructured primitives, and so it is easy to err when using them. Execution of each critical section must begin with a
<b>down()</b> and end with a <b>up()</b> (on the same semaphore). Omitting a <b>down()</b>
or <b>up()</b>, or accidentally coding a <b>down()</b> on one semaphore and a <b>up()</b>
on another can have disastrous effects, since mutually exclusive execution would no longer be ensured. Also, when using semaphores, a programmer can forget to include in critical sections all statements that reference shared objects. This, too, could destroy the mutual exclusion required within critical sections. A second difficulty with using semaphores is that both condition synchronization and mutual exclusion are programmed using the same pair of primitives. This makes it difficult to identify the purpose of a given
<b>down()</b> or <b>up()</b> operation without looking at the other operations on the corresponding semaphore. Since mutual exclusion and condition synchronization are distinct concepts, they should have distinct notations.</p>
</blockquote>
<p><b>Historical note: </b>Dijkstra's original name for <b>down()</b> was <b>P</b>
(short for the Dutch &quot;passeren&quot;, &quot;to pass&quot;), and for <b>up()</b>
was <b>V</b> (short for the Dutch &quot;vrygeven&quot;, &quot;to release&quot;).</p>
<h2><a name="Header">Header</a></h2>
<pre>
#include <a href="../../../boost/thread/semaphore.hpp">&lt;boost/thread/semaphore.hpp&gt;</a>
</pre>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>
namespace boost
{
class semaphore : private <a href="../../utility/utility.htm#Class noncopyable">boost::noncopyable</a> // Exposition only.
// Class semaphore meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
{
public:
explicit semaphore(unsigned count=0, unsigned max=0);
~semaphore();
bool up(unsigned count=1, unsigned* prev=0);
void down();
bool down(const xtime&amp; xt);
private:
unsigned m_count; <i>exposition only [ISO 17.3.2.3/2]
</i> unsigned m_max; <i>exposition only [ISO 17.3.2.3/2]</i>
};
}
</pre>
<h2><a name="Members">Members</a></h2>
<hr>
<h3>Constructor</h3>
<pre>
explicit semaphore(unsigned count=0, unsigned max=0);
</pre>
<p><b>Effects:</b> As if:</p>
<p><code>&nbsp;&nbsp;&nbsp;&nbsp; m_count = count;<br>
&nbsp;&nbsp;&nbsp;&nbsp; m_max = (max == 0 ? std::numeric_limits&lt;unsigned&gt;::max()
? max );</code></p>
<hr>
<h3>Destructor</h3>
<pre>
~semaphore();
</pre>
<p><b>Effects:</b> Destroys <code>*this</code>.</p>
<hr>
<h3>up</h3>
<pre>
bool up(unsigned count=1, unsigned* prev=0);
</pre>
<p><b>Effects:</b> As if:</p>
<p><code>&nbsp;&nbsp;&nbsp; unsigned ct;<br>
&nbsp;&nbsp;&nbsp; bool ret;<br>
&nbsp;&nbsp;&nbsp; { // as a single atomic operation:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ct = m_count;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (m_count == m_max) ret =
false;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret =
true;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++m_count;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; if (prev) *prev = m_count;<br>
&nbsp;&nbsp;&nbsp; return ret;</code></p>
<hr>
<h3>down</h3>
<pre>
void down();
</pre>
<p><b>Effects:</b> If <code>m_count == 0</code>, places the current thread in
the <a href="definitions.html#State">blocked</a> state until <code>m_count != 0</code>.
Finally, <code>--m_count</code>.<code>&nbsp;</code></p>
<hr>
<pre>
bool down(const <a href="xtime.html">xtime</a>&amp; xt);
</pre>
<p><b>Effects:</b> If <code>m_count == 0</code>, places the current thread in
the <a href="definitions.html#State">blocked</a> state until <code>m_count != 0</code>
or <code>xt</code> is reached. Finally, <code>--m_count</code>.<code>&nbsp;</code></p>
<p><b>Returns:</b> If xt was reached, true, else false.</p>
<hr>
<h2><a name="Example">Example</a> Usage</h2>
<pre>
#include <a href="../../../boost/thread/semaphore.hpp">&lt;boost/thread/semaphore.hpp&gt;</a>
#include <a href="../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
#include &lt;iostream&gt;
int global_data = 0;
boost::semaphore global_semaphore(1);
void change_global_data(void*)
{
global_semaphore.down();
++global_data;
std::cout &lt;&lt; &quot;global_data == &quot; &lt;&lt; global_data &lt;&lt; std::endl;
global_semaphore.up();
}
int main(int, char*[])
{
const int num_threads = 4;
boost::thread_group thrds;
for (int i=0; i &lt; num_threads; ++i)
thrds.create_thread(&amp;change_global_data, 0);
thrds.join_all();
return 0;
}
</pre>
<p>The output is:</p>
<pre>
global_data == 1
global_data == 2
global_data == 3
global_data == 4
</pre>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39334" -->
</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,92 +1,82 @@
<html> <html>
<head>
<meta http-equiv="Content-Type" content=
"text/html; charset=iso-8859-1">
<meta name="keywords" content=
"threads, Boost.Threads, thread library, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost.Threads, thread</title> <head>
</head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="keywords" content="threads, Boost.Threads, thread library, C++">
<link rel="stylesheet" type="text/css" href="styles.css">
<title>Boost.Threads, thread</title>
</head>
<body bgcolor="#ffffff" link="#0000ff" vlink="#800080"> <body bgcolor="#ffffff" link="#0000ff" vlink="#800080">
<table summary="header" border="0" cellpadding="7" cellspacing="0"
width="100%">
<tr>
<td valign="top" width="300">
<h3><img height="86" alt="C++ Boost" src=
"../../../c++boost.gif" width="277"></h3>
</td>
<td valign="top"> <table border="0" cellpadding="7" cellspacing="0" width="100%">
<h1 align="center">Boost.Threads</h1> <tr>
<td valign="top" width="300">
<h3><IMG height=86 alt="C++ Boost" src="../../../c++boost.gif" width=277></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Class thread</h2>
</td>
</tr>
</table>
<h2 align="center">Class thread</h2> <hr>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br> <p><A href="#Introduction">Introduction</A><br>
<a href="#Header">Header</a><br> <A href="#Header">Header</A><br>
<a href="#Synopsis">Synopsis</a><br> <A href="#Synopsis">Synopsis</A><br>
<a href="#Members">Members</a><br> <A href="#Members">Members</A><br>
<a href="#Example">Example</a></p> <A href="#Example">Example</A></p>
<h2><a name="Introduction">Introduction</a></h2> <h2><a name="Introduction">Introduction</a></h2>
<p>The <code>thread</code> class represents threads of execution, and <p>The <code>thread</code> class represents threads of execution, and provides
provides the functionality to create and manage threads within the <b> the functionality to create and manage threads within the <b>Boost.Threads</b>
Boost.Threads</b> library. See <a href="definitions.html"> library. See <A href="definitions.html">Definitions</A> for a precise description of
Definitions</a> for a precise description of &quot;thread of "thread of execution", and for definitions of threading related terms and of thread
execution&quot;, and for definitions of threading related terms and of states such as "blocked".</p>
thread states such as &quot;blocked&quot;.</p>
<p>A thread of execution has an initial function. For the program&#39;s <p>A thread of execution has an initial function. For the program's
initial thread, the initial function is <code>main()</code>. For other initial thread, the initial function is <code>main()</code>. For other
threads, the initial function is <code>operator()</code> of the threads, the initial function is <code>operator()</code> of the function object
function object passed to the class <code>thread</code> passed to the class <code>thread</code> constructor.</p>
constructor.</p>
<p>A thread of execution is said to be &quot;finished&quot; or <p>A thread of execution is said to be "finished" or "finished execution" when its
&quot;finished execution&quot; when its initial function returns or is initial function returns or is terminated. This includes completion of all thread
terminated. This includes completion of all thread cleanup handlers, cleanup handlers, and completion of the normal C++ function return behaviors, such
and completion of the normal C++ function return behaviors, such as as destruction of automatic storage (stack) objects and releasing any associated
destruction of automatic storage (stack) objects and releasing any implementation resources.</p>
associated implementation resources.</p>
<p>A thread object has an associated state which is either <p>A thread object has an associated state which is either "joinable" or
&quot;joinable&quot; or &quot;non-joinable&quot;.</p> "non-joinable".</p>
<p>Except as described below, the policy used by an implementation of <p>Except as described below, the policy used by an implementation of
<b>Boost.Threads</b> to schedule transitions between thread states is <b>Boost.Threads</b> to schedule transitions between thread states is unspecified.</p>
unspecified.</p>
<p><b>Note:</b> Just as the lifetime of a file may be different from <p><b>Note: </b>Just as the lifetime of a file may be different from the
the lifetime of an iostream object which represents the file, the lifetime of an iostream object which represents the file, the lifetime of a
lifetime of a thread of execution may be different from the <code> thread of execution may be different from the <code>thread</code> object which
thread</code> object which represents the thread of execution. In represents the thread of execution. In particular, after a call to <code>join()</code>,
particular, after a call to <code>join()</code>, the thread of the thread of execution will no longer exist even though the <code>thread</code>
execution will no longer exist even though the <code>thread</code> object continues to exist until the end of its normal lifetime. The
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
converse is also possible; if a <code>thread</code> object is destroyed <code>join()</code> having first been called, the thread of execution continues until
without <code>join()</code> having first been called, the thread of its initial function completes.</p>
execution continues until its initial function completes.</p>
<h2><a name="Header">Header</a></h2>
<h2><a name="Header">Header</a></h2>
<pre> <pre>
#include <a href= #include <A href="../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</A>
"../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
</pre> </pre>
<h2><a name="Synopsis">Synopsis</a></h2> <h2><a name="Synopsis">Synopsis</a></h2>
<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#noncopyable">boost::noncopyable</a> // Exposition only. // Class thread meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
// Class thread meets the <a href=
"overview.html#NonCopyable">NonCopyable</a> requirement.
{ {
public: public:
thread(); thread();
@@ -105,115 +95,116 @@ public:
} // namespace boost } // namespace boost
</pre> </pre>
<h2><a name="Members">Members</a></h2> <h2><a name="Members">Members</a></h2>
<hr>
<hr>
<h3>Constructors</h3>
<h3>Constructors</h3>
<pre> <pre>
thread(); thread();
</pre> </pre>
<p><b>Effects:</b> Constructs a <code>thread</code> object representing <p><b>Effects:</b> Constructs a <code>thread</code> object representing the current thread
the current thread of execution.</p> of execution.</p>
<p><b>Postcondition:</b> <code>*this</code> is non-joinable.</p> <p><b>Postcondition:</b> <code>*this</code> is non-joinable.</p>
<p><b>Danger:</b> <code>*this</code> is valid only within the current thread.</p>
<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>
<p><b>Effects:</b> Starts a new thread of execution and constructs a <p><b>Effects:</b> Starts a new thread of execution and constructs a <code>thread</code> object
<code>thread</code> object representing it. Copies <code> representing it. Copies <code>threadfunc</code>
threadfunc</code> (which in turn copies the function object wrapped by (which in turn copies the function object wrapped by <code>threadfunc</code>) to an
<code>threadfunc</code>) to an internal location which persists for the internal location which persists for the lifetime of the new thread of execution. Calls
lifetime of the new thread of execution. Calls <code>operator()</code> <code>operator()</code> on the copy of the <code>threadfunc</code> function object in
on the copy of the <code>threadfunc</code> function object in the new the new thread of execution.</p>
thread of execution.</p>
<p><b>Postcondition:</b> <code>*this</code> is joinable.</p> <p><b>Postcondition:</b> <code>*this</code> is joinable.</p>
<p><b>Throws:</b> <code>boost::thread_resource_error</code> if a new <p><b>Throws:</b> <code>boost::thread_resource_error</code> if a new thread of execution
thread of execution cannot be started.</p> cannot be started.</p>
<hr>
<hr>
<h3>Destructor</h3>
<h3>Destructor</h3>
<pre> <pre>
~thread(); ~thread();
</pre> </pre>
<p><b>Effects:</b> Destroys <code>*this</code>. The actual thread of <p><b>Effects:</b> Destroys <code>*this</code>. The actual thread of execution may
execution may continue to execute after the <code>thread</code> object continue to execute after the <code>thread</code> object has been destroyed.</p>
has been destroyed.</p>
<p><b>Notes:</b> If <code>*this</code> is joinable the actual thread of <p><b>Notes:</b> If <code>*this</code> is joinable the actual thread of execution
execution becomes &quot;detached&quot;. Any resources used by the becomes "detached". Any resources used by the thread will be reclaimed when the
thread will be reclaimed when the thread of execution completes. To thread of execution completes. To ensure such a thread of execution runs to completion
ensure such a thread of execution runs to completion before the <code> before the <code>thread</code> object is destroyed, call <code>join()</code>.</p>
thread</code> object is destroyed, call <code>join()</code>.</p>
<hr> <hr>
<h3>Comparison Operators</h3>
<h3>Comparison Operators</h3>
<pre> <pre>
bool operator==(const thread&amp; rhs); bool operator==(const thread&amp; rhs);
</pre> </pre>
<p><b>Requires:</b> The thread is non-terminated or <code>*this</code> <p><b>Requires:</b> The thread is non-terminated or <code>*this</code> is joinable.</p>
is joinable.</p>
<p><b>Returns:</b> <code>true</code> if <code>*this</code> and <code>rhs</code>
represent the same thread of execution.</p>
<p><b>Returns:</b> <code>true</code> if <code>*this</code> and <code>
rhs</code> represent the same thread of execution.</p>
<pre> <pre>
bool operator!=(const thread&amp; rhs); bool operator!=(const thread&amp; rhs);
</pre> </pre>
<p><b>Returns:</b> <code>!(*this==rhs)</code>.</p> <p><b>Returns:</b> <code>!(*this==rhs)</code>.</p>
<hr>
<hr>
<h3>join</h3>
<h3>join</h3>
<pre> <pre>
void join(); void join();
</pre> </pre>
<p><b>Requires:</b> <code>*this</code> is joinable.</p> <p><b>Requires:</b> <code>*this</code> is joinable.</p>
<p><b>Effects:</b> The current thread of execution blocks until the <p><b>Effects:</b> The current thread of execution blocks until the initial function of
initial function of the thread of execution represented by <code> the thread of execution represented by <code>*this</code> finishes and all resources
*this</code> finishes and all resources are reclaimed.</p> are reclaimed.</p>
<p><b>Postcondition:</b> <code>*this</code> is non-joinable.</p> <p><b>Postcondition:</b> <code>*this</code> is non-joinable.</p>
<p><b>Note:</b> If <code>*this == thread()</code> the result is <p><b>Note:</b></p> If <code>*this == thread()</code> the result is implementation defined.
implementation defined. If the implementation doesn&#39;t detect this If the implementation doesn't detect this the result will be
the result will be <a href="definitions.html#Deadlock"> <a href="definitions.html#Deadlock">deadlock</a>.</p>
deadlock</a>.</p>
<hr> <hr>
<h3>sleep</h3>
<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>
<p><b>Effects:</b> The current thread of execution blocks until <code> <p><b>Effects:</b> The current thread of execution blocks until <code>xt</code> is
xt</code> is reached.</p> reached.</p>
<hr>
<hr>
<h3>yield</h3>
<h3>yield</h3>
<pre> <pre>
static void yield(); static void yield();
</pre> </pre>
<p><b>Effects:</b> The current thread of execution is placed in the <p><b>Effects:</b> The current thread of execution is placed in the "ready" state.</p>
&quot;ready&quot; state.</p>
<p><b>Notes:</b> Allow the current thread to give up the rest of its <p><b>Notes:</b> Allow the current thread to give up the rest of its time slice
time slice (or other scheduling quota) to another thread. Particularly (or other scheduling quota) to another thread. Particularly useful in non-preemptive
useful in non-preemptive implementations.</p> implementations.</p>
<hr>
<hr>
<h2><a name="Example">Example Usage</a></h2>
<h2><a name="Example">Example Usage</a></h2>
<pre> <pre>
#include &lt;boost/thread/thread.hpp&gt; #include &lt;boost/thread/thread.hpp&gt;
#include &lt;iostream&gt; #include &lt;iostream&gt;
@@ -244,18 +235,20 @@ int main(int argc, char* argv[])
} }
</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>
<p>Revised <hr>
<!--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"> <p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39334" -->
William E. Kempf</a> 2001 all rights reserved.</i></p> </p>
</body>
<p><i>© Copyright <A href="mailto:williamkempf@hotmail.com">William E. Kempf</A>
2001 all rights reserved.</i></p>
</body>
</html> </html>

View File

@@ -1,58 +1,54 @@
<html> <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>
</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"> <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"> <table border="0" cellpadding="7" cellspacing="0" width="100%">
<h1 align="center">Boost.Threads</h1> <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>
<h2 align="center">thread_group</h2> <hr>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br> <p><a href="#Introduction">Introduction</a><br>
<a href="#Header">Header</a><br> <a href="#Header">Header</a><br>
<a href="#Synopsis">Synopsis</a><br> <a href="#Synopsis">Synopsis</a><br>
<a href="#Members">Members</a><br> <a href="#Members">Members</a><br>
<a href="#Example">Example</a></p> <a href="#Example">Example</a></p>
<h2><a name="Introduction">Introduction</a></h2> <h2><a name="Introduction">Introduction</a></h2>
<p>The <tt>thread_group</tt> class provides a container for easy <p>The <tt>thread_group</tt> class provides a container for easy grouping of threads to simplify several
grouping of threads to simplify several common thread creation and common thread creation and management idioms.</p>
management idioms.</p>
<p>All <tt>thread_group</tt> member functions are <a href= <p>All <tt>thread_group</tt> member functions are <a href="definitions.html#thread-safe">thread-safe</a>,
"definitions.html#thread-safe">thread-safe</a>, except destruction.</p> except destruction.</p>
<h2><a name="Header">Header</a></h2>
<h2><a name="Header">Header</a></h2>
<pre> <pre>
#include <a href= #include <a href="../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
"../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
</pre> </pre>
<h2><a name="Synopsis">Synopsis</a></h2> <h2><a name="Synopsis">Synopsis</a></h2>
<pre> <pre>
namespace boost namespace boost
{ {
class thread_group : <a href= class thread_group : <a href="../../utility/utility.htm#noncopyable">boost::noncopyable</a>
"../../utility/utility.htm#noncopyable">boost::noncopyable</a>
{ {
public: public:
thread_group(); thread_group();
@@ -64,77 +60,85 @@ namespace boost
void join_all(); void join_all();
}; };
} }
</pre> </pre>
<h2><a name="Members">Members</a></h2> <h2><a name="Members">Members</a></h2>
<hr> <hr>
<h3>Constructor</h3>
<h3>Constructor</h3>
<pre> <pre>
thread_group(); thread_group();
</pre> </pre>
<p><b>Effects:</b> Constructs an empty <tt>thread_group</tt> <p><b>Effects:</b> Constructs an empty <tt>thread_group</tt> container.</p>
container.</p>
<hr> <hr>
<h3>Destructor</h3>
<h3>Destructor</h3>
<pre> <pre>
~thread_group(); ~thread_group();
</pre> </pre>
<p><b>Effects:</b> Destroys each contained thread object. Destroys <p><b>Effects:</b> Destroys each contained thread object.&nbsp; Destroys <code>*this</code>.</p>
<code>*this</code>.</p>
<p><b>Notes:</b> Behavior is undefined if another thread references <p><b>Notes:</b> Behavior is undefined if another thread references *this during
*this during the execution of the destructor.</p> the execution of the destructor.</p>
<hr>
<hr>
<h3>create_thread</h3>
<h3>create_thread</h3>
<pre> <pre>
thread* create_thread(const boost::function0&lt;void&gt;&amp; threadfunc); thread* create_thread(const boost::function0&lt;void&gt;&amp; threadfunc);
</pre> </pre>
<p><b>Effects:</b> Creates a new <tt>thread</tt> object that executes <p><b>Effects:</b> Creates a new <tt>thread</tt> object that executes <tt>threadfunc</tt> and adds it to the
<tt>threadfunc</tt> and adds it to the <tt>thread_group</tt> container <tt>thread_group</tt> container object's list of managed <tt>thread</tt> objects.</p>
object&#39;s list of managed <tt>thread</tt> objects.</p>
<p><b>Returns:</b> Pointer to the newly created thread.</p> <p><b>Returns:</b> Pointer to the newly created thread.</p>
<hr>
<hr>
<h3>add_thread</h3>
<h3>add_thread</h3>
<pre> <pre>
void add_thread(thread* thrd); void add_thread(thread* thrd);
</pre> </pre>
<p><b>Effects:</b> Adds <tt>thrd</tt> to the <tt>thread_group</tt> <p><b>Effects:</b> Adds <tt>thrd</tt> to the <tt>thread_group</tt> object's list of managed <tt>thread</tt>
object&#39;s list of managed <tt>thread</tt> objects. The <tt>thrd</tt> objects. The <tt>thrd</tt> object must have been allocated via operator new and will
object must have been allocated via operator new and will be deleted be deleted when the group is destroyed.</p>
when the group is destroyed.</p>
<hr> <hr>
<h3>remove_thread</h3>
<h3>remove_thread</h3>
<pre> <pre>
void remove_thread(thread* thrd); void remove_thread(thread* thrd);
</pre> </pre>
<p><b>Effects:</b> Removes <code>*this</code>&#39;s list of managed <p><b>Effects:</b> Removes <code>*this</code>'s list of managed <tt>thread</tt>
<tt>thread</tt> objects.</p> objects.</p>
<p><b>Throws:</b> ? if <tt>thrd</tt> is not it <code>*this</code>&#39;s <p><b>Throws: </b>? if <tt>thrd</tt> is not it <code>*this</code>'s list of managed <tt>thread</tt>
list of managed <tt>thread</tt> objects.</p> objects.</p>
<hr>
<hr>
<h3>join_all</h3>
<h3>join_all</h3>
<pre> <pre>
void join_all(); void join_all();
</pre> </pre>
<p><b>Effects:</b> Calls <code>join()</code> on each of the managed <p><b>Effects:</b> Calls <code> join()</code> on each of the managed <tt>thread</tt> objects.</p>
<tt>thread</tt> objects.</p>
<hr> <hr>
<h2><a name="Example">Example</a> Usage</h2>
<h2><a name="Example">Example</a> Usage</h2>
<pre> <pre>
#include &lt;boost/thread/thread.hpp&gt; #include &lt;boost/thread/thread.hpp&gt;
#include &lt;iostream&gt; #include &lt;iostream&gt;
@@ -157,7 +161,8 @@ int main(int argc, char* argv[])
} }
</pre> </pre>
<p>The output is:</p> <p>The output is:</p>
<pre> <pre>
count = 1 count = 1
count = 2 count = 2
@@ -170,13 +175,13 @@ count = 8
count = 9 count = 9
count = 10 count = 10
</pre> </pre>
<hr> <hr>
<p>Revised <p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->06 August, 2001<!--webbot bot="Timestamp" endspan i-checksum="34352" -->
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p> </p>
<p><i>&copy; Copyright <a href="mailto:williamkempf@hotmail.com"> <p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
William E. Kempf</a> 2001 all rights reserved.</i></p> 2001 all rights reserved.</i></p>
</body>
</body>
</html> </html>

View File

@@ -1,51 +1,50 @@
<html> <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>
</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"> <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"> <table border="0" cellpadding="7" cellspacing="0" width="100%">
<h1 align="center">Boost.Threads</h1> <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>
<h2 align="center">thread_resource_error</h2> <hr>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br> <p><a href="#Introduction">Introduction</a><br>
<a href="#Header">Header</a><br> <a href="#Header">Header</a><br>
<a href="#Synopsis">Synopsis</a><br> <a href="#Synopsis">Synopsis</a><br>
<a href="#Members">Members</a><br> <a href="#Members">Members</a><br>
<a href="#Example">Example</a></p> <a href="#Example">Example</a></p>
<h2><a name="Introduction">Introduction</a></h2> <h2><a name="Introduction">Introduction</a></h2>
<p>The <code>thread_resource_error</code> class defines an exception <p>The <code>thread_resource_error</code> class defines an exception type that is thrown
type that is thrown by constructors in the <b>Boost.Threads</b> library by constructors in the <b>Boost.Threads</b> library when thread related resources
when thread related resources can not be acquired. This does not can not be
include memory allocation failures which instead throw acquired. This does not include memory allocation failures which instead throw
std::bad_alloc.</p> std::bad_alloc.</p>
<h2><a name="Header">Header</a></h2>
<h2><a name="Header">Header</a></h2>
<pre> <pre>
#include <a href= #include <a href="../../../boost/thread/thread.hpp">&lt;boost/thread/exceptions.hpp&gt;</a>
"../../../boost/thread/thread.hpp">&lt;boost/thread/exceptions.hpp&gt;</a>
</pre> </pre>
<h2><a name="Synopsis">Synopsis</a></h2> <h2><a name="Synopsis">Synopsis</a></h2>
<pre> <pre>
namespace boost namespace boost
{ {
@@ -57,22 +56,25 @@ namespace boost
} }
</pre> </pre>
<h2><a name="Members">Members</a></h2> <h2><a name="Members">Members</a></h2>
<hr>
<hr>
<h3>Constructor</h3>
<h3>Constructor</h3>
<pre> <pre>
thread_resource_error(); thread_resource_error();
</pre> </pre>
<p>Constructs a <code>thread_resource_error</code> object.</p> <p>Constructs a <code>thread_resource_error</code> object.</p>
<hr>
<p>Revised <hr>
<!--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"> <p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->04 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39335" -->
William E. Kempf</a> 2001 all rights reserved.</i></p> </p>
</body>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html> </html>

View File

@@ -1,79 +1,70 @@
<html> <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>
</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"> <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"> <table border="0" cellpadding="7" cellspacing="0" width="100%">
<h1 align="center">Boost.Threads</h1> <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>
<h2 align="center">thread_specific_ptr</h2> <hr>
</td>
</tr>
</table>
<hr>
<p><a href="#Introduction">Introduction</a><br> <p><A href="#Introduction">Introduction</A><br>
<a href="#Header">Header</a><br> <A href="#Header">Header</A><br>
<a href="#Synopsis">Synopsis</a><br> <A href="#Synopsis">Synopsis</A><br>
<a href="#Members">Members</a><br> <A href="#Members">Members</A><br>
<a href="#Example">Example</a></p> <A href="#Example">Example</A></p>
<h2><a name="Introduction">Introduction</a></h2> <h2><a name="Introduction">Introduction</a></h2>
<p>The <code>thread_specific_ptr</code> class defines an interface for <p>The <code>thread_specific_ptr</code> class defines an interface for using thread
using thread specific storage. Thread specific storage is data specific storage. Thread specific storage is data associated with individual threads
associated with individual threads and is often used to make operations and is often used to make operations
<a href="definitions.html#Thread-safe">thread-safe</a> that rely on <a href="definitions.html#Thread-safe">thread-safe</a> that rely on global data.</p>
global data.</p>
<p>Template <code>thread_specific_ptr</code> stores a pointer to an <p>Template <code>thread_specific_ptr</code> stores a pointer to an object obtained via
object obtained via <code>new</code> on a thread-by-thread basis and <code>new</code> on a thread-by-thread basis and calls delete on the contained pointer
calls delete on the contained pointer when the thread terminates. Each when the thread terminates. Each thread initially stores the null pointer in each
thread initially stores the null pointer in each <code> <code>thread_specific_ptr</code> instance.</p>
thread_specific_ptr</code> instance.</p>
<p>The template <code>thread_specific_ptr</code> is useful in the <p>The template <code>thread_specific_ptr</code> is useful in the following cases:</p>
following cases:</p>
<ul> <ul>
<li>An interface was original written assuming a single thread of <li>An interface was original written assuming a single thread of control and is
control and is being ported to a multi-threaded environment.</li> 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>
<li>Each thread of control invokes sequences of methods that share <h2><a name="Header">Header</a></h2>
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> <pre>
#include <a href= #include <a href="../../../boost/thread/tss.hpp">&lt;boost/thread/tss.hpp&gt;</a>
"../../../boost/thread/tss.hpp">&lt;boost/thread/tss.hpp&gt;</a>
</pre> </pre>
<h2><a name="Synopsis">Synopsis</a></h2> <h2><a name="Synopsis">Synopsis</a></h2>
<pre> <pre>
namespace boost { namespace boost {
template &lt;typename T&gt; template &lt;typename T&gt;
class thread_specific_ptr : private boost::noncopyable // Exposition only. class thread_specific_ptr : private boost::noncopyable // Exposition only.
// Class thread_specific_ptr meets the <a href= // Class thread_specific_ptr meets the <a href="overview.html#NonCopyable">NonCopyable</a> requirement.
"overview.html#NonCopyable">NonCopyable</a> requirement.
{ {
public: public:
thread_specific_ptr(); thread_specific_ptr();
@@ -87,101 +78,100 @@ public:
}; };
} // namespace boost } // namespace boost
</pre> </pre>
<h2><a name="Members">Members</a></h2> <h2><a name="Members">Members</a></h2>
<hr>
<hr>
<h3>Constructor</h3>
<h3>Constructor</h3>
<pre> <pre>
thread_specific_ptr(); thread_specific_ptr();
</pre> </pre>
<p><b>Postconditions:</b> A thread specific storage has been reserved <p><b>Postconditions:</b> A thread specific storage has been reserved for use by *this
for use by *this in all threads, with each thread initially storing a in all threads, with each thread initially storing a null pointer.</p>
null pointer.</p>
<p><b>Requires:</b> The expression <code>delete get()</code> is well <p><b>Requires:</b> The expression <code>delete get()</code> is well formed.</p>
formed.</p>
<p><b>Throws:</b> <code>boost::thread_resource_error</code> if the <p><b>Throws:</b> <code>boost::thread_resource_error</code> if the necessary resources
necessary resources can not be obtained.</p> can not be obtained.</p>
<p><b>Notes:</b> There is an implementation specific limit to the <p><b>Notes:</b> There is an implementation specific limit to the number of thread
number of thread specific storage objects that can be created, and this specific storage objects that can be created, and this limit may be small.</p>
limit may be small.</p>
<hr> <hr>
<h3>Destructor</h3>
<h3>Destructor</h3>
<pre> <pre>
~thread_specific_ptr(); ~thread_specific_ptr();
</pre> </pre>
<p><b>Notes:</b> Does not destroy any data that may be stored in any <p><b>Notes:</b> Does not destroy any data that may be stored in any thread's thread
thread&#39;s thread specific storage. For this reason you should not specific storage. For this reason you should not destroy a
destroy a <code>thread_specific_ptr</code> object until you are certain <code>thread_specific_ptr</code> object until you are certain there are no threads
there are no threads running that have made use of its thread specific running that have made use of its thread specific storage.</p>
storage.</p>
<hr> <hr>
<h3>get</h3>
<h3>get</h3>
<pre> <pre>
T* get() const; T* get() const;
</pre> </pre>
<p><b>Returns:</b> The object stored in thread specific storage for the <p><b>Returns:</b> The object stored in thread specific storage for the current thread
current thread for *this.</p> for *this.</p>
<p><b>Notes:</b> Each thread initially returns 0.</p> <p><b>Notes:</b> Each thread initially returns 0.</p>
<hr>
<hr>
<h3>Smart Pointer Operations</h3>
<h3>Smart Pointer Operations</h3>
<pre> <pre>
T* operator-&gt;() const; T* operator-&gt;() const;
</pre> </pre>
<p><b>Returns:</b> <code>get()</code></p> <p><b>Returns:</b> <code>get()</code></p>
<pre> <pre>
T&amp; operator*() const; T&amp; operator*() const;
</pre> </pre>
<p><b>Returns:</b> <code>get()</code></p> <p><b>Returns:</b> <code>get()</code></p>
<p><b>Requires:</b> <code>get() != 0</code></p> <p><b>Requires:</b> <code>get() != 0</code></p>
<hr>
<hr>
<h3>Release</h3>
<h3>Release</h3>
<pre> <pre>
T* release(); T* release();
</pre> </pre>
<p><b>Returns:</b> <code>get()</code></p> <p><b>Returns:</b> <code>get()</code></p>
<p><b>Postcondition:</b> *this holds the null pointer for the current <p><b>Postcondition:</b> *this holds the null pointer for the current thread.</p>
thread.</p>
<hr> <hr>
<h3>Reset</h3>
<h3>Reset</h3>
<pre> <pre>
void reset(T* p=0); void reset(T* p=0);
</pre> </pre>
<p><b>Effects:</b> If <code>get()!= p</code> then <code>delete <p><b>Effects:</b> If <code>get()!= p</code> then <code>delete get()</code>.</p>
get()</code>.</p>
<p><b>Postconditions:</b> <code>*this</code> holds the pointer <code> <p><b>Postconditions:</b> <code>*this</code> holds the pointer <code>p</code> for
p</code> for the current thread.</p> the current thread.</p>
<p><b>Notes:</b> The pointer will be deleted when the thread <p><b>Notes:</b> The pointer will be deleted when the thread terminates.</p>
terminates.</p>
<hr> <hr>
<h2><a name="Example">Example Usage</a></h2>
<h2><a name="Example">Example Usage</a></h2>
<pre> <pre>
#include <a href= #include <a href="../../../boost/thread/thread.hpp">&lt;boost/thread/thread.hpp&gt;</a>
"../../../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 <a href=
"../../../boost/thread/tss.hpp">&lt;boost/thread/tss.hpp&gt;</a>
#include &lt;cassert&gt; #include &lt;cassert&gt;
boost::thread_specific_ptr&lt;int&gt; value; boost::thread_specific_ptr&lt;int&gt; value;
@@ -194,7 +184,7 @@ void increment()
void thread_proc() void thread_proc()
{ {
value.reset(new int(0)); // initialize the thread&#39;s storage value.reset(new int(0)); // initialize the thread's storage
for (int i=0; i&lt;10; ++i) for (int i=0; i&lt;10; ++i)
{ {
increment(); increment();
@@ -211,13 +201,14 @@ int main(int argc, char* argv[])
threads.join_all(); threads.join_all();
} }
</pre> </pre>
<hr>
<p>Revised <hr>
<!--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"> <p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39334" -->
William E. Kempf</a> 2001 all rights reserved.</i></p> </p>
</body>
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">William E. Kempf</a>
2001 all rights reserved.</i></p>
</body>
</html> </html>

View File

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

View File

@@ -1,5 +1,6 @@
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp> #include <boost/thread/condition.hpp>
#include <boost/thread/semaphore.hpp>
#include <boost/thread/thread.hpp> #include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp> #include <boost/thread/xtime.hpp>
#include <iostream> #include <iostream>

View File

@@ -0,0 +1,61 @@
/*
*
* 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.
*
* Revision History (excluding minor changes for specific compilers)
* 8 Feb 01 Initial version.
*/
#ifndef BOOST_ATOMIC_HPP
#define BOOST_ATOMIC_HPP
#include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS
# error Thread support is unavailable!
#endif
#if !defined(BOOST_HAS_WINTHREADS)
# include <boost/thread/mutex.hpp>
#endif
namespace boost {
class atomic_t
{
public:
typedef long value_type;
friend value_type read(const atomic_t&);
friend value_type increment(atomic_t&);
friend value_type decrement(atomic_t&);
friend value_type swap(atomic_t&, value_type);
friend value_type compare_swap(atomic_t&, value_type, value_type);
explicit atomic_t(value_type val=0)
: _value(val)
{
}
private:
volatile value_type _value;
#if !defined(BOOST_HAS_WINTHREADS)
mutex _mutex;
#endif
};
extern atomic_t::value_type read(const atomic_t&);
extern atomic_t::value_type increment(atomic_t&);
extern atomic_t::value_type decrement(atomic_t&);
extern atomic_t::value_type swap(atomic_t&, atomic_t::value_type);
extern atomic_t::value_type compare_swap(atomic_t&, atomic_t::value_type, atomic_t::value_type);
} // namespace boost
#endif // BOOST_ATOMIC_HPP

View File

@@ -6,7 +6,7 @@
// provided that the above copyright notice appear in all copies and // provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear // that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations // in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose. // about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty. // It is provided "as is" without express or implied warranty.
#ifndef BOOST_CONDITION_WEK070601_HPP #ifndef BOOST_CONDITION_WEK070601_HPP
@@ -14,12 +14,11 @@
#include <boost/config.hpp> #include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS #ifndef BOOST_HAS_THREADS
# error Thread support is unavailable! # error Thread support is unavailable!
#endif #endif
#include <boost/thread/exceptions.hpp> #include <boost/thread/exceptions.hpp>
#include <boost/utility.hpp> #include <boost/utility.hpp>
#include <boost/thread/detail/lock.hpp>
#if defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_PTHREADS)
# include <pthread.h> # include <pthread.h>
@@ -34,7 +33,7 @@ class condition : private noncopyable
public: public:
condition(); condition();
~condition(); ~condition();
void notify_one(); void notify_one();
void notify_all(); void notify_all();
@@ -43,7 +42,7 @@ public:
{ {
if (!lock) if (!lock)
throw lock_error(); throw lock_error();
do_wait(lock.m_mutex); do_wait(lock.m_mutex);
} }
@@ -52,7 +51,7 @@ public:
{ {
if (!lock) if (!lock)
throw lock_error(); throw lock_error();
while (!pred()) while (!pred())
do_wait(lock.m_mutex); do_wait(lock.m_mutex);
} }
@@ -62,7 +61,7 @@ public:
{ {
if (!lock) if (!lock)
throw lock_error(); throw lock_error();
return do_timed_wait(lock.m_mutex, xt); return do_timed_wait(lock.m_mutex, xt);
} }
@@ -71,7 +70,7 @@ public:
{ {
if (!lock) if (!lock)
throw lock_error(); throw lock_error();
while (!pred()) while (!pred())
{ {
if (!do_timed_wait(lock.m_mutex, xt)) if (!do_timed_wait(lock.m_mutex, xt))
@@ -89,9 +88,8 @@ private:
enter_wait(); enter_wait();
#endif #endif
typedef typename detail::thread::lock_ops<M> lock_ops; typename M::cv_state state;
lock_ops::lock_state state; mutex.do_unlock(state);
lock_ops::unlock(mutex, state);
#if defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_PTHREADS)
do_wait(state.pmutex); do_wait(state.pmutex);
@@ -99,7 +97,7 @@ private:
do_wait(); do_wait();
#endif #endif
lock_ops::lock(mutex, state); mutex.do_lock(state);
} }
template <typename M> template <typename M>
@@ -109,9 +107,8 @@ private:
enter_wait(); enter_wait();
#endif #endif
typedef typename detail::thread::lock_ops<M> lock_ops; typename M::cv_state state;
lock_ops::lock_state state; mutex.do_unlock(state);
lock_ops::unlock(mutex, state);
bool ret = false; bool ret = false;
@@ -121,7 +118,7 @@ private:
ret = do_timed_wait(xt); ret = do_timed_wait(xt);
#endif #endif
lock_ops::lock(mutex, state); mutex.do_lock(state);
return ret; return ret;
} }
@@ -136,9 +133,9 @@ private:
#endif #endif
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
void* m_gate; unsigned long m_gate;
void* m_queue; unsigned long m_queue;
void* m_mutex; unsigned long m_mutex;
unsigned m_gone; // # threads that timed out and never made it to the m_queue 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 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 unsigned m_waiting; // # threads m_waiting no longer m_waiting for the condition but still

View File

@@ -6,7 +6,7 @@
// provided that the above copyright notice appear in all copies and // provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear // that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations // in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose. // about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty. // It is provided "as is" without express or implied warranty.
// This file is used to configure Boost.Threads during development // This file is used to configure Boost.Threads during development

View File

@@ -6,7 +6,7 @@
// provided that the above copyright notice appear in all copies and // provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear // that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations // in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose. // about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty. // It is provided "as is" without express or implied warranty.
#ifndef BOOST_XLOCK_WEK070601_HPP #ifndef BOOST_XLOCK_WEK070601_HPP
@@ -22,47 +22,12 @@ struct xtime;
namespace detail { namespace thread { namespace detail { namespace thread {
template <typename Mutex>
class lock_ops : private noncopyable
{
private:
lock_ops() { }
public:
typedef typename Mutex::cv_state lock_state;
static void lock(Mutex& m)
{
m.do_lock();
}
static bool trylock(Mutex& m)
{
return m.do_trylock();
}
static bool timedlock(Mutex& m, const xtime& xt)
{
return m.do_timedlock(xt);
}
static void unlock(Mutex& m)
{
m.do_unlock();
}
static void lock(Mutex& m, lock_state& state)
{
m.do_lock(state);
}
static void unlock(Mutex& m, lock_state& state)
{
m.do_unlock(state);
}
};
template <typename Mutex> template <typename Mutex>
class scoped_lock : private noncopyable class scoped_lock : private noncopyable
{ {
public: public:
typedef Mutex mutex_type; typedef Mutex mutex_type;
explicit scoped_lock(Mutex& mx, bool initially_locked=true) explicit scoped_lock(Mutex& mx, bool initially_locked=true)
: m_mutex(mx), m_locked(false) : m_mutex(mx), m_locked(false)
{ {
@@ -72,26 +37,26 @@ struct xtime;
{ {
if (m_locked) unlock(); if (m_locked) unlock();
} }
void lock() void lock()
{ {
if (m_locked) throw lock_error(); if (m_locked) throw lock_error();
lock_ops<Mutex>::lock(m_mutex); m_mutex.do_lock();
m_locked = true; m_locked = true;
} }
void unlock() void unlock()
{ {
if (!m_locked) throw lock_error(); if (!m_locked) throw lock_error();
lock_ops<Mutex>::unlock(m_mutex); m_mutex.do_unlock();
m_locked = false; m_locked = false;
} }
bool locked() const { return m_locked; } bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; } operator const void*() const { return m_locked ? this : 0; }
private: private:
friend class boost::condition; friend class boost::condition;
Mutex& m_mutex; Mutex& m_mutex;
bool m_locked; bool m_locked;
}; };
@@ -101,7 +66,7 @@ struct xtime;
{ {
public: public:
typedef TryMutex mutex_type; typedef TryMutex mutex_type;
explicit scoped_try_lock(TryMutex& mx) explicit scoped_try_lock(TryMutex& mx)
: m_mutex(mx), m_locked(false) : m_mutex(mx), m_locked(false)
{ {
@@ -116,31 +81,31 @@ struct xtime;
{ {
if (m_locked) unlock(); if (m_locked) unlock();
} }
void lock() void lock()
{ {
if (m_locked) throw lock_error(); if (m_locked) throw lock_error();
lock_ops<TryMutex>::lock(m_mutex); m_mutex.do_lock();
m_locked = true; m_locked = true;
} }
bool try_lock() bool try_lock()
{ {
if (m_locked) throw lock_error(); if (m_locked) throw lock_error();
return (m_locked = lock_ops<TryMutex>::trylock(m_mutex)); return (m_locked = m_mutex.do_trylock());
} }
void unlock() void unlock()
{ {
if (!m_locked) throw lock_error(); if (!m_locked) throw lock_error();
lock_ops<TryMutex>::unlock(m_mutex); m_mutex.do_unlock();
m_locked = false; m_locked = false;
} }
bool locked() const { return m_locked; } bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; } operator const void*() const { return m_locked ? this : 0; }
private: private:
friend class boost::condition; friend class boost::condition;
TryMutex& m_mutex; TryMutex& m_mutex;
bool m_locked; bool m_locked;
}; };
@@ -150,7 +115,7 @@ struct xtime;
{ {
public: public:
typedef TimedMutex mutex_type; typedef TimedMutex mutex_type;
scoped_timed_lock(TimedMutex& mx, const xtime& xt) scoped_timed_lock(TimedMutex& mx, const xtime& xt)
: m_mutex(mx), m_locked(false) : m_mutex(mx), m_locked(false)
{ {
@@ -165,31 +130,31 @@ struct xtime;
{ {
if (m_locked) unlock(); if (m_locked) unlock();
} }
void lock() void lock()
{ {
if (m_locked) throw lock_error(); if (m_locked) throw lock_error();
lock_ops<TimedMutex>::lock(m_mutex); m_mutex.do_lock();
m_locked = true; m_locked = true;
} }
bool timed_lock(const xtime& xt) bool timed_lock(const xtime& xt)
{ {
if (m_locked) throw lock_error(); if (m_locked) throw lock_error();
return (m_locked = lock_ops<TimedMutex>::timedlock(m_mutex, xt)); return (m_locked = m_mutex.do_timedlock(xt));
} }
void unlock() void unlock()
{ {
if (!m_locked) throw lock_error(); if (!m_locked) throw lock_error();
lock_ops<TimedMutex>::unlock(m_mutex); m_mutex.do_unlock();
m_locked = false; m_locked = false;
} }
bool locked() const { return m_locked; } bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; } operator const void*() const { return m_locked ? this : 0; }
private: private:
friend class boost::condition; friend class boost::condition;
TimedMutex& m_mutex; TimedMutex& m_mutex;
bool m_locked; bool m_locked;
}; };

View File

@@ -9,6 +9,13 @@
// about the suitability of this software for any purpose. // about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty. // 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_EXCEPTIONS_PDM070801_H #ifndef BOOST_THREAD_EXCEPTIONS_PDM070801_H
#define BOOST_THREAD_EXCEPTIONS_PDM070801_H #define BOOST_THREAD_EXCEPTIONS_PDM070801_H
@@ -25,13 +32,13 @@ namespace boost {
class lock_error : public std::runtime_error class lock_error : public std::runtime_error
{ {
public: public:
lock_error(); lock_error() : std::runtime_error("thread lock error") { }
}; };
class thread_resource_error : public std::runtime_error class thread_resource_error : public std::runtime_error
{ {
public: public:
thread_resource_error(); thread_resource_error() : std::runtime_error("thread resource error") { }
}; };
} // namespace boost } // namespace boost

View File

@@ -6,7 +6,7 @@
// provided that the above copyright notice appear in all copies and // provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear // that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations // in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose. // about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty. // It is provided "as is" without express or implied warranty.
#ifndef BOOST_MUTEX_WEK070601_HPP #ifndef BOOST_MUTEX_WEK070601_HPP
@@ -14,7 +14,7 @@
#include <boost/config.hpp> #include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS #ifndef BOOST_HAS_THREADS
# error Thread support is unavailable! # error Thread support is unavailable!
#endif #endif
#include <boost/utility.hpp> #include <boost/utility.hpp>
@@ -26,18 +26,20 @@
namespace boost { namespace boost {
class condition;
struct xtime; struct xtime;
class mutex : private noncopyable class mutex : private noncopyable
{ {
public: public:
friend class detail::thread::lock_ops<mutex>; friend class detail::thread::scoped_lock<mutex>;
friend class condition;
typedef detail::thread::scoped_lock<mutex> scoped_lock; typedef detail::thread::scoped_lock<mutex> scoped_lock;
mutex(); mutex();
~mutex(); ~mutex();
private: private:
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
typedef void* cv_state; typedef void* cv_state;
@@ -53,7 +55,7 @@ private:
void do_unlock(cv_state& state); void do_unlock(cv_state& state);
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
void* m_mutex; unsigned long m_mutex;
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex; pthread_mutex_t m_mutex;
#endif #endif
@@ -62,14 +64,16 @@ private:
class try_mutex : private noncopyable class try_mutex : private noncopyable
{ {
public: public:
friend class detail::thread::lock_ops<try_mutex>; friend class detail::thread::scoped_lock<try_mutex>;
friend class detail::thread::scoped_try_lock<try_mutex>;
friend class condition;
typedef detail::thread::scoped_lock<try_mutex> scoped_lock; typedef detail::thread::scoped_lock<try_mutex> scoped_lock;
typedef detail::thread::scoped_try_lock<try_mutex> scoped_try_lock; typedef detail::thread::scoped_try_lock<try_mutex> scoped_try_lock;
try_mutex(); try_mutex();
~try_mutex(); ~try_mutex();
private: private:
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
typedef void* cv_state; typedef void* cv_state;
@@ -86,7 +90,7 @@ private:
void do_unlock(cv_state& state); void do_unlock(cv_state& state);
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
void* m_mutex; unsigned long m_mutex;
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex; pthread_mutex_t m_mutex;
#endif #endif
@@ -95,15 +99,18 @@ private:
class timed_mutex : private noncopyable class timed_mutex : private noncopyable
{ {
public: public:
friend class detail::thread::lock_ops<timed_mutex>; friend class detail::thread::scoped_lock<timed_mutex>;
friend class detail::thread::scoped_try_lock<timed_mutex>;
friend class detail::thread::scoped_timed_lock<timed_mutex>;
friend class condition;
typedef detail::thread::scoped_lock<timed_mutex> scoped_lock; typedef detail::thread::scoped_lock<timed_mutex> scoped_lock;
typedef detail::thread::scoped_try_lock<timed_mutex> scoped_try_lock; typedef detail::thread::scoped_try_lock<timed_mutex> scoped_try_lock;
typedef detail::thread::scoped_timed_lock<timed_mutex> scoped_timed_lock; typedef detail::thread::scoped_timed_lock<timed_mutex> scoped_timed_lock;
timed_mutex(); timed_mutex();
~timed_mutex(); ~timed_mutex();
private: private:
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
typedef void* cv_state; typedef void* cv_state;
@@ -119,9 +126,9 @@ private:
void do_unlock(); void do_unlock();
void do_lock(cv_state& state); void do_lock(cv_state& state);
void do_unlock(cv_state& state); void do_unlock(cv_state& state);
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
void* m_mutex; unsigned long m_mutex;
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex; pthread_mutex_t m_mutex;
pthread_cond_t m_condition; pthread_cond_t m_condition;

View File

@@ -6,7 +6,7 @@
// provided that the above copyright notice appear in all copies and // provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear // that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations // in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose. // about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty. // It is provided "as is" without express or implied warranty.
#ifndef BOOST_ONCE_WEK080101_HPP #ifndef BOOST_ONCE_WEK080101_HPP
@@ -14,7 +14,7 @@
#include <boost/config.hpp> #include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS #ifndef BOOST_HAS_THREADS
# error Thread support is unavailable! # error Thread support is unavailable!
#endif #endif
#if defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_PTHREADS)
@@ -26,12 +26,12 @@ namespace boost {
#if defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_PTHREADS)
typedef pthread_once_t once_flag; typedef pthread_once_t once_flag;
#define BOOST_ONCE_INIT PTHREAD_ONCE_INIT const once_flag once_init = PTHREAD_ONCE_INIT;
#elif defined(BOOST_HAS_WINTHREADS) #elif defined(BOOST_HAS_WINTHREADS)
typedef bool once_flag; typedef bool once_flag;
#define BOOST_ONCE_INIT false const once_flag once_init = false;
#endif #endif

View File

@@ -6,7 +6,7 @@
// provided that the above copyright notice appear in all copies and // provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear // that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations // in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose. // about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty. // It is provided "as is" without express or implied warranty.
#ifndef BOOST_RECURSIVE_MUTEX_WEK070601_HPP #ifndef BOOST_RECURSIVE_MUTEX_WEK070601_HPP
@@ -14,7 +14,7 @@
#include <boost/config.hpp> #include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS #ifndef BOOST_HAS_THREADS
# error Thread support is unavailable! # error Thread support is unavailable!
#endif #endif
#include <boost/utility.hpp> #include <boost/utility.hpp>
@@ -26,18 +26,20 @@
namespace boost { namespace boost {
class condition;
struct xtime; struct xtime;
class recursive_mutex : private noncopyable class recursive_mutex : private noncopyable
{ {
public: public:
friend class detail::thread::lock_ops<recursive_mutex>; friend class detail::thread::scoped_lock<recursive_mutex>;
friend class condition;
typedef detail::thread::scoped_lock<recursive_mutex> scoped_lock; typedef detail::thread::scoped_lock<recursive_mutex> scoped_lock;
recursive_mutex(); recursive_mutex();
~recursive_mutex(); ~recursive_mutex();
private: private:
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
typedef std::size_t cv_state; typedef std::size_t cv_state;
@@ -54,7 +56,7 @@ private:
void do_unlock(cv_state& state); void do_unlock(cv_state& state);
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
void* m_mutex; unsigned long m_mutex;
unsigned long m_count; unsigned long m_count;
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex; pthread_mutex_t m_mutex;
@@ -70,14 +72,16 @@ private:
class recursive_try_mutex : private noncopyable class recursive_try_mutex : private noncopyable
{ {
public: public:
friend class detail::thread::lock_ops<recursive_try_mutex>; friend class detail::thread::scoped_lock<recursive_try_mutex>;
friend class detail::thread::scoped_try_lock<recursive_try_mutex>;
friend class condition;
typedef detail::thread::scoped_lock<recursive_try_mutex> scoped_lock; typedef detail::thread::scoped_lock<recursive_try_mutex> scoped_lock;
typedef detail::thread::scoped_try_lock<recursive_try_mutex> scoped_try_lock; typedef detail::thread::scoped_try_lock<recursive_try_mutex> scoped_try_lock;
recursive_try_mutex(); recursive_try_mutex();
~recursive_try_mutex(); ~recursive_try_mutex();
private: private:
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
typedef std::size_t cv_state; typedef std::size_t cv_state;
@@ -93,9 +97,9 @@ private:
void do_unlock(); void do_unlock();
void do_lock(cv_state& state); void do_lock(cv_state& state);
void do_unlock(cv_state& state); void do_unlock(cv_state& state);
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
void* m_mutex; unsigned long m_mutex;
unsigned long m_count; unsigned long m_count;
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex; pthread_mutex_t m_mutex;
@@ -111,15 +115,18 @@ private:
class recursive_timed_mutex : private noncopyable class recursive_timed_mutex : private noncopyable
{ {
public: public:
friend class detail::thread::lock_ops<recursive_timed_mutex>; friend class detail::thread::scoped_lock<recursive_timed_mutex>;
friend class detail::thread::scoped_try_lock<recursive_timed_mutex>;
friend class detail::thread::scoped_timed_lock<recursive_timed_mutex>;
friend class condition;
typedef detail::thread::scoped_lock<recursive_timed_mutex> scoped_lock; typedef detail::thread::scoped_lock<recursive_timed_mutex> scoped_lock;
typedef detail::thread::scoped_try_lock<recursive_timed_mutex> scoped_try_lock; typedef detail::thread::scoped_try_lock<recursive_timed_mutex> scoped_try_lock;
typedef detail::thread::scoped_timed_lock<recursive_timed_mutex> scoped_timed_lock; typedef detail::thread::scoped_timed_lock<recursive_timed_mutex> scoped_timed_lock;
recursive_timed_mutex(); recursive_timed_mutex();
~recursive_timed_mutex(); ~recursive_timed_mutex();
private: private:
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
typedef std::size_t cv_state; typedef std::size_t cv_state;
@@ -136,9 +143,9 @@ private:
void do_unlock(); void do_unlock();
void do_lock(cv_state& state); void do_lock(cv_state& state);
void do_unlock(cv_state& state); void do_unlock(cv_state& state);
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
void* m_mutex; unsigned long m_mutex;
unsigned long m_count; unsigned long m_count;
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
pthread_mutex_t m_mutex; pthread_mutex_t m_mutex;

View File

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

View File

@@ -6,7 +6,7 @@
// provided that the above copyright notice appear in all copies and // provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear // that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations // in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose. // about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty. // It is provided "as is" without express or implied warranty.
#ifndef BOOST_THREAD_WEK070601_HPP #ifndef BOOST_THREAD_WEK070601_HPP
@@ -14,7 +14,7 @@
#include <boost/config.hpp> #include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS #ifndef BOOST_HAS_THREADS
# error Thread support is unavailable! # error Thread support is unavailable!
#endif #endif
#include <boost/utility.hpp> #include <boost/utility.hpp>
@@ -49,7 +49,7 @@ public:
private: private:
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
void* m_thread; unsigned long m_thread;
unsigned int m_id; unsigned int m_id;
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
private: private:

View File

@@ -6,7 +6,7 @@
// provided that the above copyright notice appear in all copies and // provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear // that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations // in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose. // about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty. // It is provided "as is" without express or implied warranty.
#ifndef BOOST_TSS_WEK070601_HPP #ifndef BOOST_TSS_WEK070601_HPP
@@ -14,7 +14,7 @@
#include <boost/config.hpp> #include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS #ifndef BOOST_HAS_THREADS
# error Thread support is unavailable! # error Thread support is unavailable!
#endif #endif
#include <boost/utility.hpp> #include <boost/utility.hpp>

View File

@@ -6,7 +6,7 @@
// provided that the above copyright notice appear in all copies and // provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear // that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations // in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose. // about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty. // It is provided "as is" without express or implied warranty.
#ifndef BOOST_XTIME_WEK070601_HPP #ifndef BOOST_XTIME_WEK070601_HPP

80
src/_atomic.cpp Normal file
View File

@@ -0,0 +1,80 @@
/*
*
* 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.
*
* Revision History (excluding minor changes for specific compilers)
* 8 Feb 01 Initial version.
*/
#include <boost/thread/atomic.hpp>
#if defined(BOOST_HAS_WINTHREADS)
# include <windows.h>
#endif
namespace boost {
atomic_t::value_type read(const atomic_t& x)
{
return x._value;
}
#if defined(BOOST_HAS_WINTHREADS)
atomic_t::value_type increment(atomic_t& x)
{
return InterlockedIncrement(const_cast<long*>(&x._value));
}
atomic_t::value_type decrement(atomic_t& x)
{
return InterlockedDecrement(const_cast<long*>(&x._value));
}
atomic_t::value_type swap(atomic_t& x, atomic_t::value_type y)
{
return InterlockedExchange(const_cast<long*>(&x._value), y);
}
atomic_t::value_type compare_swap(atomic_t& x, atomic_t::value_type y, atomic_t::value_type z)
{
return InterlockedCompareExchange(const_cast<long*>(&x._value), y, z);
}
#else
atomic_t::value_type increment(atomic_t& x)
{
mutex::lock lock(x._mutex);
return ++x._value;
}
atomic_t::value_type decrement(atomic_t& x)
{
mutex::lock lock(x._mutex);
return --x._value;
}
atomic_t::value_type swap(atomic_t& x, atomic_t::value_type y)
{
mutex::lock lock(x._mutex);
atomic_t::value_type temp = x._value;
x._value = y;
return temp;
}
atomic_t::value_type compare_swap(atomic_t& x, atomic_t::value_type y, atomic_t::value_type z)
{
mutex::lock lock(x._mutex);
atomic_t::value_type temp = x._value;
if (temp == z)
x._value = y;
return temp;
}
#endif
} // namespace boost

View File

@@ -6,12 +6,12 @@
// provided that the above copyright notice appear in all copies and // provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear // that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations // in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose. // about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty. // It is provided "as is" without express or implied warranty.
#include <boost/thread/condition.hpp> #include <boost/thread/condition.hpp>
#include <boost/thread/xtime.hpp> #include <boost/thread/xtime.hpp>
#include <boost/thread/thread.hpp> #include <boost/thread/thread.hpp>
#include <boost/thread/exceptions.hpp> #include <boost/thread/exceptions.hpp>
#include <boost/limits.hpp> #include <boost/limits.hpp>
#include <cassert> #include <cassert>
@@ -30,28 +30,28 @@ namespace boost {
condition::condition() condition::condition()
: m_gone(0), m_blocked(0), m_waiting(0) : m_gone(0), m_blocked(0), m_waiting(0)
{ {
m_gate = reinterpret_cast<void*>(CreateSemaphore(0, 1, 1, 0)); m_gate = reinterpret_cast<unsigned long>(CreateSemaphore(0, 1, 1, 0));
m_queue = reinterpret_cast<void*>(CreateSemaphore(0, 0, std::numeric_limits<long>::max(), 0)); m_queue = reinterpret_cast<unsigned long>(CreateSemaphore(0, 0, std::numeric_limits<long>::max(), 0));
m_mutex = reinterpret_cast<void*>(CreateMutex(0, 0, 0)); m_mutex = reinterpret_cast<unsigned long>(CreateMutex(0, 0, 0));
if (!m_gate || !m_queue || !m_mutex) if (!m_gate || !m_queue || !m_mutex)
{ {
int res = 0; int res = 0;
if (m_gate) if (m_gate)
{ {
res = CloseHandle(reinterpret_cast<HANDLE>(m_gate)); res = CloseHandle(reinterpret_cast<HANDLE>(m_gate));
assert(res); assert(res);
} }
if (m_queue) if (m_queue)
{ {
res = CloseHandle(reinterpret_cast<HANDLE>(m_queue)); res = CloseHandle(reinterpret_cast<HANDLE>(m_queue));
assert(res); assert(res);
} }
if (m_mutex) if (m_mutex)
{ {
res = CloseHandle(reinterpret_cast<HANDLE>(m_mutex)); res = CloseHandle(reinterpret_cast<HANDLE>(m_mutex));
assert(res); assert(res);
} }
throw thread_resource_error(); throw thread_resource_error();
} }
@@ -185,7 +185,7 @@ void condition::do_wait()
int res = 0; int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), INFINITE); res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), INFINITE);
assert(res == WAIT_OBJECT_0); assert(res == WAIT_OBJECT_0);
unsigned was_waiting=0; unsigned was_waiting=0;
unsigned was_gone=0; unsigned was_gone=0;
@@ -240,12 +240,12 @@ bool condition::do_timed_wait(const xtime& xt)
unsigned milliseconds; unsigned milliseconds;
to_duration(xt, milliseconds); to_duration(xt, milliseconds);
unsigned int res = 0; int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), milliseconds); res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), milliseconds);
assert(res != WAIT_FAILED && res != WAIT_ABANDONED); assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
bool ret = (res == WAIT_OBJECT_0); bool ret = (res == WAIT_OBJECT_0);
unsigned was_waiting=0; unsigned was_waiting=0;
unsigned was_gone=0; unsigned was_gone=0;

View File

@@ -1,25 +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.
#include <boost/thread/exceptions.hpp>
#include <string>
namespace boost {
lock_error::lock_error() : std::runtime_error("thread lock error")
{
}
thread_resource_error::thread_resource_error() : std::runtime_error("thread resource error")
{
}
} // namespace boost

View File

@@ -6,7 +6,7 @@
// provided that the above copyright notice appear in all copies and // provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear // that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations // in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose. // about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty. // It is provided "as is" without express or implied warranty.
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
@@ -16,7 +16,6 @@
#include <boost/limits.hpp> #include <boost/limits.hpp>
#include <stdexcept> #include <stdexcept>
#include <cassert> #include <cassert>
#include <new>
#include "timeconv.inl" #include "timeconv.inl"
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
@@ -31,26 +30,30 @@ namespace boost {
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
mutex::mutex() mutex::mutex()
{ {
m_mutex = reinterpret_cast<void*>(new(std::nothrow) CRITICAL_SECTION); m_mutex = reinterpret_cast<unsigned long>(CreateMutex(0, 0, 0));
if (!m_mutex) if (!m_mutex)
throw thread_resource_error(); throw thread_resource_error();
InitializeCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(m_mutex));
} }
mutex::~mutex() mutex::~mutex()
{ {
DeleteCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(m_mutex)); int res = 0;
delete reinterpret_cast<LPCRITICAL_SECTION>(m_mutex); res = CloseHandle(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
} }
void mutex::do_lock() void mutex::do_lock()
{ {
EnterCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(m_mutex)); int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
assert(res == WAIT_OBJECT_0);
} }
void mutex::do_unlock() void mutex::do_unlock()
{ {
LeaveCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(m_mutex)); int res = 0;
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
} }
void mutex::do_lock(cv_state&) void mutex::do_lock(cv_state&)
@@ -65,7 +68,7 @@ void mutex::do_unlock(cv_state&)
try_mutex::try_mutex() try_mutex::try_mutex()
{ {
m_mutex = reinterpret_cast<void*>(CreateMutex(0, 0, 0)); m_mutex = reinterpret_cast<unsigned long>(CreateMutex(0, 0, 0));
if (!m_mutex) if (!m_mutex)
throw thread_resource_error(); throw thread_resource_error();
} }
@@ -86,7 +89,7 @@ void try_mutex::do_lock()
bool try_mutex::do_trylock() bool try_mutex::do_trylock()
{ {
unsigned int res = 0; int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), 0); res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), 0);
assert(res != WAIT_FAILED && res != WAIT_ABANDONED); assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
return res == WAIT_OBJECT_0; return res == WAIT_OBJECT_0;
@@ -111,7 +114,7 @@ void try_mutex::do_unlock(cv_state&)
timed_mutex::timed_mutex() timed_mutex::timed_mutex()
{ {
m_mutex = reinterpret_cast<void*>(CreateMutex(0, 0, 0)); m_mutex = reinterpret_cast<unsigned long>(CreateMutex(0, 0, 0));
if (!m_mutex) if (!m_mutex)
throw thread_resource_error(); throw thread_resource_error();
} }
@@ -132,7 +135,7 @@ void timed_mutex::do_lock()
bool timed_mutex::do_trylock() bool timed_mutex::do_trylock()
{ {
unsigned int res = 0; int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), 0); res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), 0);
assert(res != WAIT_FAILED && res != WAIT_ABANDONED); assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
return res == WAIT_OBJECT_0; return res == WAIT_OBJECT_0;
@@ -143,7 +146,7 @@ bool timed_mutex::do_timedlock(const xtime& xt)
unsigned milliseconds; unsigned milliseconds;
to_duration(xt, milliseconds); to_duration(xt, milliseconds);
unsigned int res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), milliseconds); int res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), milliseconds);
assert(res != WAIT_FAILED && res != WAIT_ABANDONED); assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
return res == WAIT_OBJECT_0; return res == WAIT_OBJECT_0;
} }
@@ -196,7 +199,7 @@ void mutex::do_unlock()
assert(res == 0); assert(res == 0);
} }
void mutex::do_lock(cv_state&) void mutex::do_lock(cv_state& state)
{ {
} }
@@ -245,7 +248,7 @@ void try_mutex::do_unlock()
assert(res == 0); assert(res == 0);
} }
void try_mutex::do_lock(cv_state&) void try_mutex::do_lock(cv_state& state)
{ {
} }
@@ -335,7 +338,7 @@ bool timed_mutex::do_timedlock(const xtime& xt)
if (res == ETIMEDOUT) if (res == ETIMEDOUT)
break; break;
} }
bool ret = false; bool ret = false;
if (!m_locked) if (!m_locked)
{ {
@@ -364,7 +367,7 @@ void timed_mutex::do_unlock()
assert(res == 0); assert(res == 0);
} }
void timed_mutex::do_lock(cv_state&) void timed_mutex::do_lock(cv_state& state)
{ {
int res = 0; int res = 0;
while (m_locked) while (m_locked)

View File

@@ -6,7 +6,7 @@
// provided that the above copyright notice appear in all copies and // provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear // that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations // in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose. // about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty. // It is provided "as is" without express or implied warranty.
#include <boost/thread/once.hpp> #include <boost/thread/once.hpp>
@@ -15,19 +15,6 @@
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
# include <windows.h> # include <windows.h>
# if defined(BOOST_NO_STRINGSTREAM)
# include <strstream>
class unfreezer
{
public:
unfreezer(std::ostrstream& s) : m_stream(s) {}
~unfreezer() { m_stream.freeze(false); }
private:
std::ostrstream& m_stream;
};
# else
# include <sstream>
# endif
#endif #endif
#ifdef BOOST_NO_STDC_NAMESPACE #ifdef BOOST_NO_STDC_NAMESPACE
@@ -51,8 +38,8 @@ static void key_init()
static void do_once() static void do_once()
{ {
once_callback* cb = reinterpret_cast<once_callback*>(pthread_getspecific(key)); once_callback cb = reinterpret_cast<once_callback>(pthread_getspecific(key));
(**cb)(); (*cb)();
} }
} }
@@ -68,18 +55,11 @@ void call_once(void (*func)(), once_flag& flag)
// Memory barrier would be needed here to prevent race conditions on some platforms with // Memory barrier would be needed here to prevent race conditions on some platforms with
// partial ordering. // partial ordering.
if (!tmp) if (!tmp)
{ {
#if defined(BOOST_NO_STRINGSTREAM) char name[41];
std::ostrstream strm; std::sprintf(name, "2AC1A572DB6944B0A65C38C4140AF2F4%X%X", GetCurrentProcessId(), &flag);
strm << "2AC1A572DB6944B0A65C38C4140AF2F4" << std::hex << GetCurrentProcessId() << &flag << std::ends; HANDLE mutex = CreateMutex(NULL, FALSE, name);
unfreezer unfreeze(strm);
HANDLE mutex = CreateMutex(NULL, FALSE, strm.str());
#else
std::ostringstream strm;
strm << "2AC1A572DB6944B0A65C38C4140AF2F4" << std::hex << GetCurrentProcessId() << &flag;
HANDLE mutex = CreateMutex(NULL, FALSE, strm.str().c_str());
#endif
assert(mutex != NULL); assert(mutex != NULL);
int res = 0; int res = 0;
@@ -87,26 +67,26 @@ void call_once(void (*func)(), once_flag& flag)
assert(res == WAIT_OBJECT_0); assert(res == WAIT_OBJECT_0);
tmp = flag; tmp = flag;
if (!tmp) if (!tmp)
{ {
func(); func();
tmp = true; tmp = true;
// Memory barrier would be needed here to prevent race conditions on some platforms // Memory barrier would be needed here to prevent race conditions on some platforms
// with partial ordering. // with partial ordering.
flag = tmp; flag = tmp;
} }
res = ReleaseMutex(mutex); res = ReleaseMutex(mutex);
assert(res); assert(res);
res = CloseHandle(mutex); res = CloseHandle(mutex);
assert(res); assert(res);
} }
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
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);
#endif #endif
} }

View File

@@ -6,11 +6,11 @@
// provided that the above copyright notice appear in all copies and // provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear // that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations // in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose. // about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty. // It is provided "as is" without express or implied warranty.
#include <boost/thread/recursive_mutex.hpp> #include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/xtime.hpp> #include <boost/thread/xtime.hpp>
#include <boost/thread/thread.hpp> #include <boost/thread/thread.hpp>
#include <boost/limits.hpp> #include <boost/limits.hpp>
#include <stdexcept> #include <stdexcept>
@@ -30,35 +30,47 @@ namespace boost {
recursive_mutex::recursive_mutex() recursive_mutex::recursive_mutex()
: m_count(0) : m_count(0)
{ {
m_mutex = reinterpret_cast<void*>(new(std::nothrow) CRITICAL_SECTION); m_mutex = reinterpret_cast<unsigned long>(CreateMutex(0, 0, 0));
if (!m_mutex) if (!m_mutex)
throw thread_resource_error(); throw thread_resource_error();
InitializeCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(m_mutex));
} }
recursive_mutex::~recursive_mutex() recursive_mutex::~recursive_mutex()
{ {
DeleteCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(m_mutex)); int res = 0;
delete reinterpret_cast<LPCRITICAL_SECTION>(m_mutex); res = CloseHandle(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
} }
void recursive_mutex::do_lock() void recursive_mutex::do_lock()
{ {
EnterCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(m_mutex)); int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
assert(res == WAIT_OBJECT_0);
if (++m_count > 1) if (++m_count > 1)
LeaveCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(m_mutex)); {
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
}
} }
void recursive_mutex::do_unlock() void recursive_mutex::do_unlock()
{ {
if (--m_count == 0) if (--m_count == 0)
LeaveCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(m_mutex)); {
int res = 0;
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
}
} }
void recursive_mutex::do_lock(cv_state& state) void recursive_mutex::do_lock(cv_state& state)
{ {
EnterCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(m_mutex)); int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), INFINITE);
assert(res == WAIT_OBJECT_0);
m_count = state; m_count = state;
} }
@@ -66,13 +78,16 @@ void recursive_mutex::do_unlock(cv_state& state)
{ {
state = m_count; state = m_count;
m_count = 0; m_count = 0;
LeaveCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(m_mutex));
int res = 0;
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
} }
recursive_try_mutex::recursive_try_mutex() recursive_try_mutex::recursive_try_mutex()
: m_count(0) : m_count(0)
{ {
m_mutex = reinterpret_cast<void*>(CreateMutex(0, 0, 0)); m_mutex = reinterpret_cast<unsigned long>(CreateMutex(0, 0, 0));
if (!m_mutex) if (!m_mutex)
throw thread_resource_error(); throw thread_resource_error();
} }
@@ -99,7 +114,7 @@ void recursive_try_mutex::do_lock()
bool recursive_try_mutex::do_trylock() bool recursive_try_mutex::do_trylock()
{ {
unsigned int res = 0; int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), 0); res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), 0);
assert(res != WAIT_FAILED && res != WAIT_ABANDONED); assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
@@ -147,7 +162,7 @@ void recursive_try_mutex::do_unlock(cv_state& state)
recursive_timed_mutex::recursive_timed_mutex() recursive_timed_mutex::recursive_timed_mutex()
: m_count(0) : m_count(0)
{ {
m_mutex = reinterpret_cast<void*>(CreateMutex(0, 0, 0)); m_mutex = reinterpret_cast<unsigned long>(CreateMutex(0, 0, 0));
if (!m_mutex) if (!m_mutex)
throw thread_resource_error(); throw thread_resource_error();
} }
@@ -174,7 +189,7 @@ void recursive_timed_mutex::do_lock()
bool recursive_timed_mutex::do_trylock() bool recursive_timed_mutex::do_trylock()
{ {
unsigned int res = 0; int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), 0); res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), 0);
assert(res != WAIT_FAILED && res != WAIT_ABANDONED); assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
@@ -195,7 +210,7 @@ bool recursive_timed_mutex::do_timedlock(const xtime& xt)
unsigned milliseconds; unsigned milliseconds;
to_duration(xt, milliseconds); to_duration(xt, milliseconds);
unsigned int res = 0; int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), milliseconds); res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_mutex), milliseconds);
assert(res != WAIT_FAILED && res != WAIT_ABANDONED); assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
@@ -234,7 +249,7 @@ void recursive_timed_mutex::do_unlock(cv_state& state)
{ {
state = m_count; state = m_count;
m_count = 0; m_count = 0;
int res = 0; int res = 0;
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex)); res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res); assert(res);
@@ -595,7 +610,7 @@ recursive_timed_mutex::recursive_timed_mutex()
res = pthread_mutex_init(&m_mutex, 0); res = pthread_mutex_init(&m_mutex, 0);
if (res != 0) if (res != 0)
throw thread_resource_error(); throw thread_resource_error();
res = pthread_cond_init(&m_unlocked, 0); res = pthread_cond_init(&m_unlocked, 0);
if (res != 0) if (res != 0)
{ {
@@ -691,7 +706,7 @@ bool recursive_timed_mutex::do_timedlock(const xtime& xt)
break; break;
assert(res == 0); assert(res == 0);
} }
if (!m_valid_id) if (!m_valid_id)
{ {
m_thread_id = tid; m_thread_id = tid;

179
src/semaphore.cpp Normal file
View File

@@ -0,0 +1,179 @@
// 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.
#include <boost/thread/semaphore.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/limits.hpp>
#include <boost/thread/exceptions.hpp>
#include <stdexcept>
#include <cassert>
#include "timeconv.inl"
#if defined(BOOST_HAS_WINTHREADS)
# include <windows.h>
#elif defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
# include <errno.h>
# include <boost/thread/mutex.hpp>
# include <boost/thread/condition.hpp>
#endif
namespace boost {
#if defined(BOOST_HAS_WINTHREADS)
semaphore::semaphore(unsigned count, unsigned max)
{
if (static_cast<long>(max) <= 0)
max = std::numeric_limits<long>::max();
m_sema = reinterpret_cast<unsigned long>(CreateSemaphore(0, count, max, 0));
if (!m_sema)
throw thread_resource_error();
}
semaphore::~semaphore()
{
int res = 0;
res = CloseHandle(reinterpret_cast<HANDLE>(m_sema));
assert(res);
}
bool semaphore::up(unsigned count, unsigned* prev)
{
long p;
bool ret = !!ReleaseSemaphore(reinterpret_cast<HANDLE>(m_sema), count, &p);
if (prev)
*prev = p;
return ret;
}
void semaphore::down()
{
int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_sema), INFINITE);
assert(res == WAIT_OBJECT_0);
}
bool semaphore::down(const xtime& xt)
{
unsigned milliseconds;
to_duration(xt, milliseconds);
int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_sema), milliseconds);
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
return res == WAIT_OBJECT_0;
}
#elif defined(BOOST_HAS_PTHREADS)
semaphore::semaphore(unsigned count, unsigned max)
: m_available(count), m_max(max ? max : std::numeric_limits<unsigned>::max())
{
int res = 0;
res = pthread_mutex_init(&m_mutex, 0);
if (res != 0)
throw thread_resource_error();
res = pthread_cond_init(&m_condition, 0);
if (res != 0)
{
pthread_mutex_destroy(&m_mutex);
throw thread_resource_error();
}
}
semaphore::~semaphore()
{
int res = 0;
res = pthread_mutex_destroy(&m_mutex);
assert(res == 0);
res = pthread_cond_destroy(&m_condition);
assert(res == 0);
}
bool semaphore::up(unsigned count, unsigned* prev)
{
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
if (prev)
*prev = m_available;
if (m_available + count > m_max)
{
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
return false;
}
m_available += count;
res = pthread_cond_broadcast(&m_condition);
assert(res == 0);
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
return true;
}
void semaphore::down()
{
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
while (m_available == 0)
{
res = pthread_cond_wait(&m_condition, &m_mutex);
assert(res == 0);
}
m_available--;
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
}
bool semaphore::down(const xtime& xt)
{
int res = 0;
res = pthread_mutex_lock(&m_mutex);
assert(res == 0);
timespec ts;
to_timespec(xt, ts);
while (m_available == 0)
{
res = pthread_cond_timedwait(&m_condition, &m_mutex, &ts);
assert(res == 0 || res == ETIMEDOUT);
if (res == ETIMEDOUT)
{
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
return false;
}
}
m_available--;
res = pthread_mutex_unlock(&m_mutex);
assert(res == 0);
return true;
}
#endif
} // namespace boost
// Change Log:
// 8 Feb 01 WEKEMPF Initial version.
// 22 May 01 WEKEMPF Modified to use xtime for time outs.

View File

@@ -6,10 +6,11 @@
// provided that the above copyright notice appear in all copies and // provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear // that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations // in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose. // about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty. // It is provided "as is" without express or implied warranty.
#include <boost/thread/thread.hpp> #include <boost/thread/thread.hpp>
#include <boost/thread/semaphore.hpp>
#include <boost/thread/xtime.hpp> #include <boost/thread/xtime.hpp>
#include <boost/thread/condition.hpp> #include <boost/thread/condition.hpp>
#include <cassert> #include <cassert>
@@ -76,7 +77,7 @@ thread::thread()
: m_joinable(false) : m_joinable(false)
{ {
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
m_thread = reinterpret_cast<void*>(GetCurrentThread()); m_thread = reinterpret_cast<unsigned long>(GetCurrentThread());
m_id = GetCurrentThreadId(); m_id = GetCurrentThreadId();
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
m_thread = pthread_self(); m_thread = pthread_self();
@@ -88,7 +89,7 @@ thread::thread(const function0<void>& threadfunc)
{ {
thread_param param(threadfunc); thread_param param(threadfunc);
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
m_thread = reinterpret_cast<void*>(_beginthreadex(0, 0, &thread_proxy, &param, 0, &m_id)); m_thread = _beginthreadex(0, 0, &thread_proxy, &param, 0, &m_id);
if (!m_thread) if (!m_thread)
throw thread_resource_error(); throw thread_resource_error();
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
@@ -162,14 +163,12 @@ void thread::sleep(const xtime& xt)
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; semaphore sema;
mutex::scoped_lock lock(mx); sema.down(xt);
condition cond;
cond.timed_wait(lock, xt);
# endif # endif
#endif #endif
} }

View File

@@ -4,15 +4,10 @@
#define BOOST_THREADMON_EXPORTS #define BOOST_THREADMON_EXPORTS
#include "threadmon.hpp" #include "threadmon.hpp"
#ifdef BOOST_HAS_WINTHREADS #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h> #include <windows.h>
#ifdef BOOST_MSVC #pragma warning(disable : 4786)
# pragma warning(disable : 4786)
#endif
#include <list> #include <list>
#include <set> #include <set>
#include <algorithm> #include <algorithm>
@@ -35,14 +30,14 @@ namespace
BOOL APIENTRY DllMain(HANDLE module, DWORD reason, LPVOID) BOOL APIENTRY DllMain(HANDLE module, DWORD reason, LPVOID)
{ {
switch (reason) switch (reason)
{ {
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
InitializeCriticalSection(&cs); InitializeCriticalSection(&cs);
key = TlsAlloc(); key = TlsAlloc();
break; break;
case DLL_THREAD_ATTACH: case DLL_THREAD_ATTACH:
break; break;
case DLL_THREAD_DETACH: case DLL_THREAD_DETACH:
{ {
// Call the thread's exit handlers. // Call the thread's exit handlers.
exit_handlers* handlers = static_cast<exit_handlers*>(TlsGetValue(key)); exit_handlers* handlers = static_cast<exit_handlers*>(TlsGetValue(key));
@@ -59,7 +54,7 @@ BOOL APIENTRY DllMain(HANDLE module, DWORD reason, LPVOID)
} }
} }
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
{ {
// Assume the main thread is ending (call its handlers) and all other threads // Assume the main thread is ending (call its handlers) and all other threads
// have already ended. If this DLL is loaded and unloaded dynamically at run time // have already ended. If this DLL is loaded and unloaded dynamically at run time
@@ -81,7 +76,7 @@ BOOL APIENTRY DllMain(HANDLE module, DWORD reason, LPVOID)
DeleteCriticalSection(&cs); DeleteCriticalSection(&cs);
TlsFree(key); TlsFree(key);
} }
break; break;
} }
return TRUE; return TRUE;
} }
@@ -141,5 +136,3 @@ int on_thread_exit(void (__cdecl * func)(void))
return 0; return 0;
} }
#endif // BOOST_HAS_WINTHREADS

View File

@@ -1,17 +1,10 @@
#include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS
# error Thread support is unavailable!
#endif
#ifdef BOOST_HAS_WINTHREADS // The following ifdef block is the standard way of creating macros which make exporting
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the BOOST_THREADMON_EXPORTS // from a DLL simpler. All files within this DLL are compiled with the BOOST_THREADMON_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project // symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see // that uses this DLL. This way any other project whose source files include this file see
// BOOST_THREADMON_API functions as being imported from a DLL, wheras this DLL sees symbols // BOOST_THREADMON_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported. // defined with this macro as being exported.
#ifdef BOOST_THREADMON_EXPORTS #ifdef BOOST_THREADMON_EXPORTS
#define BOOST_THREADMON_API __declspec(dllexport) #define BOOST_THREADMON_API __declspec(dllexport)
#else #else
@@ -19,5 +12,3 @@
#endif #endif
extern "C" BOOST_THREADMON_API int on_thread_exit(void (__cdecl * func)(void)); extern "C" BOOST_THREADMON_API int on_thread_exit(void (__cdecl * func)(void));
#endif // BOOST_HAS_WINTHREADS

View File

@@ -6,9 +6,9 @@
// provided that the above copyright notice appear in all copies and // provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear // that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations // in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose. // about the suitability of this software for any purpose.
// 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 unsigned MILLISECONDS_PER_SECOND = 1000;
const unsigned NANOSECONDS_PER_SECOND = 1000000000; const unsigned NANOSECONDS_PER_SECOND = 1000000000;
@@ -23,7 +23,7 @@ namespace {
xt.sec += (milliseconds / MILLISECONDS_PER_SECOND); xt.sec += (milliseconds / MILLISECONDS_PER_SECOND);
xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND); xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) * NANOSECONDS_PER_MILLISECOND);
if (xt.nsec > static_cast<const int>(NANOSECONDS_PER_SECOND)) if (xt.nsec > NANOSECONDS_PER_SECOND)
{ {
++xt.sec; ++xt.sec;
xt.nsec -= NANOSECONDS_PER_SECOND; xt.nsec -= NANOSECONDS_PER_SECOND;
@@ -35,11 +35,6 @@ 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)
{
ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
ts.tv_nsec %= NANOSECONDS_PER_SECOND;
}
} }
inline void to_time(unsigned milliseconds, timespec& ts) inline void to_time(unsigned milliseconds, timespec& ts)
@@ -71,11 +66,6 @@ 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)
{
ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
ts.tv_nsec %= NANOSECONDS_PER_SECOND;
}
} }
} }
#endif #endif

View File

@@ -6,7 +6,7 @@
// provided that the above copyright notice appear in all copies and // provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear // that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations // in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose. // about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty. // It is provided "as is" without express or implied warranty.
#include <boost/thread/tss.hpp> #include <boost/thread/tss.hpp>
@@ -27,7 +27,7 @@ namespace {
typedef std::map<int, cleanup_info> cleanup_handlers; typedef std::map<int, cleanup_info> cleanup_handlers;
DWORD key; DWORD key;
boost::once_flag once = BOOST_ONCE_INIT; boost::once_flag once = boost::once_init;
void init_cleanup_key() void init_cleanup_key()
{ {
@@ -106,8 +106,8 @@ bool tss::set(void* value)
assert(handlers); assert(handlers);
if (!handlers) if (!handlers)
return false; return false;
cleanup_info info(m_cleanup, value); cleanup_info info(m_cleanup, value);
(*handlers)[m_key] = info; (*handlers)[m_key] = info;
} }
return !!TlsSetValue(m_key, value); return !!TlsSetValue(m_key, value);
} }

View File

@@ -6,7 +6,7 @@
// provided that the above copyright notice appear in all copies and // provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear // that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations // in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose. // about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty. // It is provided "as is" without express or implied warranty.
#include <boost/thread/xtime.hpp> #include <boost/thread/xtime.hpp>
@@ -14,7 +14,7 @@
#if defined(BOOST_HAS_FTIME) #if defined(BOOST_HAS_FTIME)
# include <windows.h> # include <windows.h>
#elif defined(BOOST_HAS_GETTIMEOFDAY) #elif defined(BOOST_HAS_GETTIMEOFDAY)
# include <sys/time.h> # include <sys/time.h>
#endif #endif
namespace boost { namespace boost {
@@ -26,7 +26,7 @@ int xtime_get(struct xtime* xtp, int clock_type)
#if defined(BOOST_HAS_FTIME) #if defined(BOOST_HAS_FTIME)
FILETIME ft; FILETIME ft;
GetSystemTimeAsFileTime(&ft); GetSystemTimeAsFileTime(&ft);
const boost::uint64_t TIMESPEC_TO_FILETIME_OFFSET = ((boost::uint64_t)27111902UL << 32) + (boost::uint64_t)3577643008UL; const __int64 TIMESPEC_TO_FILETIME_OFFSET = ((__int64)27111902 << 32) + (__int64)3577643008;
xtp->sec = (int)((*(__int64*)&ft - TIMESPEC_TO_FILETIME_OFFSET) / 10000000); xtp->sec = (int)((*(__int64*)&ft - TIMESPEC_TO_FILETIME_OFFSET) / 10000000);
xtp->nsec = (int)((*(__int64*)&ft - TIMESPEC_TO_FILETIME_OFFSET - xtp->nsec = (int)((*(__int64*)&ft - TIMESPEC_TO_FILETIME_OFFSET -
((__int64)xtp->sec * (__int64)10000000)) * 100); ((__int64)xtp->sec * (__int64)10000000)) * 100);

View File

@@ -7,11 +7,6 @@
# #
# Declares the following targets: # Declares the following targets:
# 1. test_thread, a unit test executable. # 1. test_thread, a unit test executable.
#
# Invoke with:
# Jam [-sPTW32=lib]
# Where: lib == name of pthreads-win32 link library
# Note: Not currently working completely
# declare the location of this subproject relative to the root # declare the location of this subproject relative to the root
subproject libs/thread/test ; subproject libs/thread/test ;
@@ -25,15 +20,7 @@ subproject libs/thread/test ;
# Do some OS-specific setup # Do some OS-specific setup
if $(NT) if $(NT)
{ {
if $(PTW32) BOOST_THREADMON_LIB = <lib>../build/libboost_threadmon ;
{
PTW32_REQUIREMENTS = <define>BOOST_HAS_PTHREADS <define>PtW32NoCatchWarn ;
BOOST_THREADMON_LIB = ;
}
else
{
BOOST_THREADMON_LIB = <lib>../build/libboost_threadmon ;
}
} }
else else
{ {
@@ -42,9 +29,8 @@ else
unit-test test_thread : test_thread.cpp unit-test test_thread : test_thread.cpp
<lib>../build/libboost_thread <lib>../build/libboost_thread
$(BOOST_THREADMON_LIB) $(BOOST_THREADMON_LIB)
# requirements # requirements
: <include>$(BOOST_ROOT) : <include>$(BOOST_ROOT)
$(PTW32_REQUIREMENTS)
<threading>multi <threading>multi
: debug release ; : debug release ;

View File

@@ -2,6 +2,8 @@
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#include <boost/thread/recursive_mutex.hpp> #include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/condition.hpp> #include <boost/thread/condition.hpp>
#include <boost/thread/semaphore.hpp>
//#include <boost/thread/atomic.hpp>
#include <boost/thread/tss.hpp> #include <boost/thread/tss.hpp>
#include <boost/thread/once.hpp> #include <boost/thread/once.hpp>
#include <boost/thread/thread.hpp> #include <boost/thread/thread.hpp>
@@ -371,6 +373,39 @@ void test_condition()
test_condition_waits(); test_condition_waits();
} }
void test_semaphore()
{
boost::xtime xt;
unsigned val;
boost::semaphore sema(0, 1);
BOOST_TEST(sema.up(1, &val));
BOOST_TEST(val == 0);
BOOST_TEST(!sema.up());
sema.down();
BOOST_TEST(sema.up());
BOOST_TEST(boost::xtime_get(&xt, boost::TIME_UTC) == boost::TIME_UTC);
xt.nsec += 100000000;
BOOST_TEST(sema.down(xt));
BOOST_TEST(boost::xtime_get(&xt, boost::TIME_UTC) == boost::TIME_UTC);
xt.nsec += 100000000;
BOOST_TEST(!sema.down(xt));
}
/*void test_atomic_t()
{
boost::atomic_t atomic;
BOOST_TEST(boost::increment(atomic) > 0);
BOOST_TEST(boost::decrement(atomic) == 0);
BOOST_TEST(boost::swap(atomic, 10) == 0);
BOOST_TEST(boost::swap(atomic, 0) == 10);
BOOST_TEST(boost::compare_swap(atomic, 20, 10) == 0);
BOOST_TEST(boost::compare_swap(atomic, 20, 0) == 0);
BOOST_TEST(boost::read(atomic) == 20);
}*/
boost::mutex tss_mutex; boost::mutex tss_mutex;
int tss_instances = 0; int tss_instances = 0;
@@ -414,7 +449,7 @@ void test_tss()
} }
int once_value = 0; int once_value = 0;
boost::once_flag once = BOOST_ONCE_INIT; boost::once_flag once = boost::once_init;
void init_once_value() void init_once_value()
{ {
@@ -445,6 +480,7 @@ int test_main(int, char*[])
test_recursive_try_mutex(); test_recursive_try_mutex();
test_recursive_timed_mutex(); test_recursive_timed_mutex();
test_condition(); test_condition();
test_semaphore();
test_tss(); test_tss();
test_once(); test_once();
return 0; return 0;