mirror of
https://github.com/boostorg/thread.git
synced 2026-02-13 12:52:11 +00:00
Compare commits
76 Commits
boost-1.25
...
svn-branch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f795dce04 | ||
|
|
7496ecbc73 | ||
|
|
76e80ee4c4 | ||
|
|
8e2536fc54 | ||
|
|
9bbbfbe6ff | ||
|
|
a2fc9ebfaa | ||
|
|
16c78b81e2 | ||
|
|
e71b204d10 | ||
|
|
f64208ce7a | ||
|
|
3410029cad | ||
|
|
25fd0f52e7 | ||
|
|
095f16c4f1 | ||
|
|
5a4a5f405f | ||
|
|
7775aceb86 | ||
|
|
29177b34a7 | ||
|
|
ae1c315e0c | ||
|
|
3592d8c412 | ||
|
|
63fdf6ef22 | ||
|
|
915c2cd206 | ||
|
|
54abba952b | ||
|
|
7cee797d2e | ||
|
|
a7fb1e73d2 | ||
|
|
6a46149868 | ||
|
|
f07d726011 | ||
|
|
344ddb5fd2 | ||
|
|
537b623b18 | ||
|
|
ab180e79d1 | ||
|
|
089dc81880 | ||
|
|
73187a40b6 | ||
|
|
3d06b18e3e | ||
|
|
fd9d19b050 | ||
|
|
692aa0e352 | ||
|
|
307bbdc951 | ||
|
|
b460053eda | ||
|
|
df704a5dae | ||
|
|
9b76b71b5f | ||
|
|
427a109865 | ||
|
|
5662e2f6bb | ||
|
|
6a6fbd0553 | ||
|
|
5084e9ccd2 | ||
|
|
84cb093ee6 | ||
|
|
8305cad4f8 | ||
|
|
b52c5d45ec | ||
|
|
71103fe1bc | ||
|
|
57d262d4d6 | ||
|
|
acf721b0bd | ||
|
|
3ee4bf04dc | ||
|
|
6e4a874880 | ||
|
|
b07d60aa94 | ||
|
|
fb3aed485c | ||
|
|
cbf212f1cd | ||
|
|
562c4583d4 | ||
|
|
95053b7516 | ||
|
|
65d06c138e | ||
|
|
9e3e80558c | ||
|
|
d27e195ca2 | ||
|
|
0ae839e0bb | ||
|
|
21067cb309 | ||
|
|
5cb2a46ae4 | ||
|
|
66fa1995cf | ||
|
|
6e83cfdc72 | ||
|
|
c2930faaec | ||
|
|
64ad66034a | ||
|
|
101e7cfbda | ||
|
|
76de0ff7fd | ||
|
|
f70b32cc63 | ||
|
|
8ce4eeca24 | ||
|
|
2febaf386c | ||
|
|
1d6f10702d | ||
|
|
ebe3a7beee | ||
|
|
9e38dc5f48 | ||
|
|
6dafed21fc | ||
|
|
067d2a39f7 | ||
|
|
d70f46126b | ||
|
|
b282e06a90 | ||
|
|
abd2e68f8d |
@@ -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 ;
|
||||||
|
|||||||
@@ -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 È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>© <i>Copyright <a href="mailto:williamkempf@hotmail.com">
|
|
||||||
William E. Kempf</a> 2001</i></p>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -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. Includes descriptions of Path
|
||||||
|
Expressions, Message Passing, and Remote Procedure Call in addition to the
|
||||||
|
basics.
|
||||||
|
</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.
|
||||||
|
</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>"This paper describes the evolution of language features for
|
||||||
|
multiprogramming from event queues and semaphores to critical regions and
|
||||||
|
monitors." 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.
|
||||||
|
</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'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.
|
||||||
|
</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.
|
||||||
|
</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>"This paper describes the evolution of language
|
|
||||||
features for multiprogramming from event queues and
|
|
||||||
semaphores to critical regions and monitors." 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'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'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>© Copyright Beman Dawes, 2001</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -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"><boost/thread/once.hpp></a>
|
||||||
"../../../boost/thread/once.hpp"><boost/thread/once.hpp></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& 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& flag);
|
void call_once(void (*func)(), once_flag& 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> if (flag == once_init)<br>
|
|
||||||
func();</code>
|
|
||||||
|
|
||||||
<p><b>Postcondition:</b> <code>flag</code> != <code>
|
<code>
|
||||||
once_init</code></p>
|
if (flag == once_init)<br>
|
||||||
<hr>
|
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"><boost/thread/thread.hpp></a>
|
||||||
"../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
#include <a href="../../../boost/thread/tss.hpp"><boost/thread/once.hpp></a>
|
||||||
#include <a href=
|
|
||||||
"../../../boost/thread/tss.hpp"><boost/thread/once.hpp></a>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
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>© 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>
|
||||||
|
|
||||||
|
|||||||
@@ -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'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'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'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
|
||||||
"waiting" 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"><boost/thread/condition.hpp></a>
|
||||||
"../../../boost/thread/condition.hpp"><boost/thread/condition.hpp></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 <typename <a href="scoped_lock.html">ScopedLock</a>>
|
template <typename <a href="scoped_lock.html">ScopedLock</a>>
|
||||||
void wait(<a href="scoped_lock.html">ScopedLock</a>& lock);
|
void wait(<a href="scoped_lock.html">ScopedLock</a>& lock);
|
||||||
template <typename <a href="scoped_lock.html">ScopedLock</a>, typename <a
|
template <typename <a href="scoped_lock.html">ScopedLock</a>, typename <A href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</A>>
|
||||||
href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a>>
|
void wait(<a href="scoped_lock.html">ScopedLock</a>& lock, <A href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</A> pred);
|
||||||
void wait(<a href="scoped_lock.html">ScopedLock</a>& lock, <a href=
|
|
||||||
"http://www.sgi.com/tech/stl/Predicate.html">Predicate</a> pred);
|
|
||||||
template <typename <a href="scoped_lock.html">ScopedLock</a>>
|
template <typename <a href="scoped_lock.html">ScopedLock</a>>
|
||||||
bool timed_wait(<a href=
|
bool timed_wait(<a href="scoped_lock.html">ScopedLock</a>& lock, const xtime& xt);
|
||||||
"scoped_lock.html">ScopedLock</a>& lock, const xtime& xt);
|
template <typename <a href="scoped_lock.html">ScopedLock</a>, typename <A href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</A>>
|
||||||
template <typename <a href="scoped_lock.html">ScopedLock</a>, typename <a
|
bool timed_wait(<a href="scoped_lock.html">ScopedLock</a>& lock, const xtime& 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>>
|
|
||||||
bool timed_wait(<a href=
|
|
||||||
"scoped_lock.html">ScopedLock</a>& lock, const xtime& 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'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 <typename ScopedLock>
|
template <typename ScopedLock>
|
||||||
void wait(ScopedLock& lock);
|
void wait(ScopedLock& 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->notify_one()</code> or <code>this->notify_all()</code>,
|
||||||
<code>this->notify_one()</code> or <code>
|
and then reacquires the lock. All effects occur in an atomic fashion.</p>
|
||||||
this->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 "spurious wake ups". The second version
|
|
||||||
encapsulates this loop idiom internally and is generally the preferred
|
|
||||||
method.</p>
|
|
||||||
<pre>
|
<pre>
|
||||||
template <typename ScopedLock, typename Pr>
|
template <typename ScopedLock, typename Pr>
|
||||||
void wait(ScopedLock& lock, Pr pred);
|
void wait(ScopedLock& 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> 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>
|
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 <typename ScopedLock>
|
template <typename ScopedTimedLock>
|
||||||
bool timed_wait(ScopedLock& lock, const <a href=
|
bool timed_wait(ScopedTimedLock& lock, const <a href="xtime.html">xtime</a>& xt);
|
||||||
"xtime.html">xtime</a>& 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->notify_one()</code> or
|
||||||
call to <code>this->notify_one()</code> or <code>
|
<code>this->notify_all()</code>, or until <code>xt</code>, and then reacquires the
|
||||||
this->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 "spurious wake ups". 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 <typename ScopedLock, typename Pr>
|
template <typename ScopedTimedLock, typename Pr>
|
||||||
bool timed_wait(ScopedLock& lock, const <a href=
|
bool timed_wait(ScopedTimedLock& lock, const <a href="xtime.html">xtime</a>& xt, Pr pred);
|
||||||
"xtime.html">xtime</a>& 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> while (!pred())<br>
|
|
||||||
{<br>
|
|
||||||
if (!timed_wait(lock, xt))<br>
|
|
||||||
return
|
|
||||||
false;<br>
|
|
||||||
}</code>
|
|
||||||
|
|
||||||
<p><b>Throws:</b> <code><a href="lock_error.html">lock_error</a></code>
|
<code>
|
||||||
if <code>!lock.locked()</code></p>
|
while (!pred())<br>
|
||||||
|
{<br>
|
||||||
|
if (!timed_wait(lock, xt))<br>
|
||||||
|
return false;<br>
|
||||||
|
}
|
||||||
|
</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 <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <a href="../../../boost/utility.hpp"><boost/utility.hpp></a>
|
#include <A href="../../../boost/utility.hpp"><boost/utility.hpp></a>
|
||||||
#include <a href=
|
#include <A href="../../../boost/thread/condition.hpp"><boost/thread/condition.hpp></a>
|
||||||
"../../../boost/thread/condition.hpp"><boost/thread/condition.hpp></a>
|
#include <A href="../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
||||||
#include <a href=
|
|
||||||
"../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></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>© 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>
|
||||||
|
|
||||||
|
|||||||
178
doc/config.html
178
doc/config.html
@@ -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"> <boost/config.hpp></a>.
|
||||||
"../../config/config.htm"><boost/config.hpp></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'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>© Copyright <a href="mailto:williamkempf@hotmail.com">
|
|
||||||
William E. Kempf</a> 2001 all rights reserved.</i></p>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -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>. References to the standard
|
||||||
|
are in the form [1.2.3/4], which
|
||||||
|
represents the section number, with the paragraph number following the "/".</p>
|
||||||
|
<p>Because the definitions are written in something akin to
|
||||||
|
"standardese", they can be difficult to understand. The intent
|
||||||
|
isn't to confuse, but rather to clarify the additional requirements
|
||||||
|
Boost.Threads places on a C++ implementation as defined by the C++ Standard.</p>
|
||||||
|
<h2>Definitions</h2>
|
||||||
|
<h3>Thread</h3>
|
||||||
|
<p>Thread is short for "thread of execution". A thread of execution is an execution environment [1.9/7] within the execution environment
|
||||||
|
of a C++ program [1.9]. The main() function [3.6.1] of the program is the
|
||||||
|
initial function of the initial thread. A program in a 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 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 "waiting" is synonymous for "blocked"</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. 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'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
|
||||||
|
"sequence point at a call" is the sequence point after the evaluation
|
||||||
|
of all function arguments [1.9/17], while the "sequence point after a
|
||||||
|
call" is the sequence point after the copying of the returned
|
||||||
|
value..." [1.9/17].</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. </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 -->07 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14762" -->
|
||||||
|
</p>
|
||||||
|
<p>© Copyright Beman Dawes, 2001</p>
|
||||||
|
<p> </p>
|
||||||
|
<p> </p>
|
||||||
|
<p> </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 "/".</p>
|
|
||||||
|
|
||||||
<p>Because the definitions are written in something akin to
|
|
||||||
"standardese", they can be difficult to understand. The
|
|
||||||
intent isn't to confuse, but rather to clarify the additional
|
|
||||||
requirements Boost.Threads places on a C++ implementation as defined by
|
|
||||||
the C++ Standard.</p>
|
|
||||||
|
|
||||||
<h2>Definitions</h2>
|
|
||||||
|
|
||||||
<h3>Thread</h3>
|
|
||||||
|
|
||||||
<p>Thread is short for "thread of execution". A thread of
|
|
||||||
execution is an execution environment [1.9/7] within the execution
|
|
||||||
environment of a C++ program [1.9]. The main() function [3.6.1] of the
|
|
||||||
program is the initial function of the initial thread. A program in a
|
|
||||||
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 "waiting" is
|
|
||||||
synonymous for "blocked"</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'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 "sequence point at a
|
|
||||||
call" is the sequence point after the evaluation of all function
|
|
||||||
arguments [1.9/17], while the "sequence point after a call"
|
|
||||||
is the sequence point after the copying of the returned value..."
|
|
||||||
[1.9/17].</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>© Copyright Beman Dawes, 2001</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
211
doc/faq.html
211
doc/faq.html
@@ -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'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'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't model such C based APIs.</p>
|
APIs.</p>
|
||||||
|
|
||||||
<h2>2b. Why wasn'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'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'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'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'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'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'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't thread cancellation or termination provided?</h2>
|
<h2>8. Why isn't thread cancellation or termination provided?</h2>
|
||||||
|
|
||||||
<p>There'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>© Copyright <a href="mailto:williamkempf@hotmail.com">
|
</body>
|
||||||
William E. Kempf</a> 2001 all rights reserved.</i></p>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
201
doc/index.html
201
doc/index.html
@@ -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 "as is" 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>© <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
|
|
||||||
"as is" without express or implied warranty.</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -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's world, it'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++'s
|
|
||||||
strengths, or to address C++'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'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 "native" API that programmers are inclined
|
|
||||||
to ignore the higher level API. <b>Boost.Threads</b> was
|
|
||||||
designed to minimize the chances of this occurring. The
|
|
||||||
interfaces have been crafted to allow an implementation the
|
|
||||||
greatest chance of being as efficient as possible. This goal is
|
|
||||||
often at odds with the goal for <i>safety</i>. Every effort was
|
|
||||||
made to ensure efficient implementations, but when in conflict
|
|
||||||
<i>safety</i> has always taken precedence.</p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3>Iterative Phases</h3>
|
<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 "state of the art" and the
|
|
||||||
only concepts available to programmers. Recently there has been a lot
|
|
||||||
of research in other concepts, such as in "Communicating
|
|
||||||
Sequential Processes." <b>Boost.Threads</b> was designed in
|
|
||||||
iterative steps, providing the building blocks necessary for the next
|
|
||||||
step, and giving the researcher the tools necessary to explore new
|
|
||||||
concepts in a portable manner.</p>
|
|
||||||
|
|
||||||
<p>Given the goal of following a dynamic, iterative approach <b>
|
<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's a big
|
|
||||||
problem faced by developers wishing to supply such high quality
|
|
||||||
libraries, namely thread-safety. The C++ standard doesn't address
|
|
||||||
threads at all, but real world programs often make use of native
|
|
||||||
threading support. A portable library that doesn't address the
|
|
||||||
issue of thread-safety is there for not much help to a programmer who
|
|
||||||
wants to use the library in his multi-threaded application. So
|
|
||||||
there's a very great need for portable primitives that will allow
|
|
||||||
the library developer to create <a href="definitions.html#Thread-safe">
|
|
||||||
thread-safe</a> implementations. This need far out weighs the need for
|
|
||||||
portable methods to create and manage threads.</p>
|
|
||||||
|
|
||||||
<p>Because of this need, the first phase of <b>Boost.Threads</b>
|
|
||||||
focuses solely on providing portable primitive concepts for thread
|
|
||||||
synchronization. Types provided in this phase include the <a href="mutex.html">
|
|
||||||
mutex/try_mutex/timed_mutex</a>, <a href="recursive_mutex.html">
|
|
||||||
recursive_mutex/recursive_try_mutex/recursive_timed_mutex</a>, <a href=
|
|
||||||
"scoped_lock.html">scoped_lock</a>, <a href="scoped_try_lock.html">
|
|
||||||
scoped_try_lock</a>, <a href="scoped_timed_lock.html">
|
|
||||||
scoped_timed_lock</a> and <a href="lock_error.html">lock_error</a>.
|
|
||||||
These are considered the "core" synchronization primitives,
|
|
||||||
though there are others that will be added in later phases.</p>
|
|
||||||
|
|
||||||
<h4>Phase 2, Thread Management and Thread Specific Storage</h4>
|
|
||||||
|
|
||||||
<p>This phase addresses the creation and management of threads and
|
|
||||||
provides a mechanism for thread specific storage (data associated with
|
|
||||||
a thread instance). Thread management is a tricky issue in C++, so this
|
|
||||||
phase addresses only the basic needs of multi-threaded program. Later
|
|
||||||
phases are likely to add additional functionality in this area. This
|
|
||||||
phase of <b>Boost.Threads</b> adds the <a href="thread.html">thread</a>
|
|
||||||
and <a href="thread_specific_ptr.html">thread_specific_ptr</a> types.
|
|
||||||
With these additions the <b>Boost.Threads</b> library can be considered
|
|
||||||
minimal but complete.</p>
|
|
||||||
|
|
||||||
<h4>The Next Phase</h4>
|
|
||||||
|
|
||||||
<p>The next phase will address more advanced synchronization concepts,
|
|
||||||
such as read/write mutexes and barriers.</p>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<p>Revised
|
|
||||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->05 November, 2001<!--webbot bot="Timestamp" endspan i-checksum="39359" --></p>
|
|
||||||
|
|
||||||
<p><i>© Copyright <a href="mailto:williamkempf@hotmail.com">
|
|
||||||
William E. Kempf</a> 2001 all rights reserved.</i></p>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -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'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>(&lk)->~L();</code></td>
|
|
||||||
|
|
||||||
<td><code>if (locked()) unlock();</code></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td valign="top"><code>(&clk)->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>(&clk)->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>(&lk)->~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>(&clk)->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>(&clk)->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> </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>© 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> </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>
|
||||||
|
|
||||||
|
|||||||
@@ -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"><boost/thread/thread.hpp></a>
|
||||||
"../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></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"><boost/thread/mutex.hpp></a>
|
||||||
"../../../boost/thread/mutex.hpp"><boost/thread/mutex.hpp></a>
|
#include <a href="../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
||||||
#include <a href=
|
|
||||||
"../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
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>© 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>
|
||||||
|
|
||||||
|
|||||||
390
doc/mutex.html
390
doc/mutex.html
@@ -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> 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<mutex></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<try_mutex><br>
|
||||||
|
</code></a><code><a href="scoped_try_lock.html">boost::detail::thread::scoped_try_lock<try_mutex></a></code></td>
|
||||||
|
<td valign="middle"><a href="lock_concept.html#ScopedLock">ScopedLock</a><br>
|
||||||
|
<a href="lock_concept.html#ScopedTryLock">ScopedTryLock</a></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<timed_mutex></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<timed_mutex></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<timed_mutex></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<mutex></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<try_mutex><br>
|
|
||||||
|
|
||||||
</code></a> <code><a href="scoped_try_lock.html">
|
|
||||||
boost::detail::thread::scoped_try_lock<try_mutex></a></code></td>
|
|
||||||
|
|
||||||
<td valign="middle"><a href="lock_concept.html#ScopedLock">
|
|
||||||
ScopedLock</a><br>
|
|
||||||
<a href="lock_concept.html#ScopedTryLock">
|
|
||||||
ScopedTryLock</a></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<timed_mutex></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<timed_mutex></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<timed_mutex></code></a></td>
|
|
||||||
|
|
||||||
<td valign="middle"><a href="lock_concept.html#ScopedLock">
|
|
||||||
ScopedLock</a><br>
|
|
||||||
<a href="lock_concept.html#ScopedTryLock">
|
|
||||||
ScopedTryLock</a><br>
|
|
||||||
<a href="lock_concept.html#ScopedTimedLock">
|
|
||||||
ScopedTimedLock</a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p>The <tt>mutex</tt>, <tt>try_mutex</tt> and <tt>timed_mutex</tt>
|
|
||||||
classes use an <tt>Unspecified</tt> <a href=
|
|
||||||
"mutex_concept.html#LockingStrategies">locking strategy</a>, so
|
|
||||||
attempts to recursively lock them or attempts to unlock them by threads
|
|
||||||
that don't own a lock on them result in <b>undefined behavior</b>.
|
|
||||||
This strategy allows implementations to be as efficient as possible on
|
|
||||||
any given platform. It is, however, recommended that implementations
|
|
||||||
include debugging support to detect misuse when <tt>NDEBUG</tt> is not
|
|
||||||
defined.</p>
|
|
||||||
|
|
||||||
<p>Like all the <b>Boost.Threads</b> <a href="mutex_concept.html">mutex
|
|
||||||
models</a>, the <tt>mutex</tt>, <tt>try_mutex</tt> and <tt>
|
|
||||||
timed_mutex</tt> leave the <a href=
|
|
||||||
"mutex_concept.html#SchedulingPolicies">scheduling policy</a> as <tt>
|
|
||||||
Unspecified</tt>. Programmers should assume that threads waiting for a
|
|
||||||
lock on objects of these types acquire the lock in a random order, even
|
|
||||||
though the specific behavior for a given platform may be different.</p>
|
|
||||||
|
|
||||||
<h2><a name="Header">Header</a></h2>
|
|
||||||
<pre>
|
<pre>
|
||||||
#include <a href=
|
#include <a href="../../../boost/thread/mutex.hpp"><boost/thread/mutex.hpp></a>
|
||||||
"../../../boost/thread/mutex.hpp"><boost/thread/mutex.hpp></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"><boost/thread/mutex.hpp></a>
|
||||||
"../../../boost/thread/mutex.hpp"><boost/thread/mutex.hpp></a>
|
#include <a href="../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
||||||
#include <a href=
|
|
||||||
"../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
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>© 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>
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
|
||||||
<a href="#Recursive">Recursive</a><br>
|
|
||||||
<a href="#CheckedStrategy">Checked</a><br>
|
|
||||||
<a href="#UncheckedStrategy">Unchecked</a><br>
|
|
||||||
<a href="#UnspecifiedStrategy">
|
|
||||||
Unspecified</a><br>
|
|
||||||
<a href="#SchedulingPolicies">Scheduling Policies</a><br>
|
|
||||||
<a href="#FIFO">FIFO</a><br>
|
|
||||||
<a href="#Priority Driven">Priority
|
|
||||||
Driven</a><br>
|
|
||||||
<a href="#UndefinedScheduling">
|
|
||||||
Undefined</a><br>
|
|
||||||
<a href="#UnspecifiedScheduling">
|
|
||||||
Unspecified</a><br>
|
|
||||||
<a href="#Requirements">Concept Requirements</a><br>
|
|
||||||
<a href="#Mutex">Mutex Concept</a><br>
|
|
||||||
<a href="#TryMutex">TryMutex Concept</a><br>
|
|
||||||
<a href="#TimedMutex">TimedMutex
|
|
||||||
Concept</a><br>
|
|
||||||
<a href="#Models">Models</a></p>
|
|
||||||
|
|
||||||
<h2><a name="Introduction">Introduction</a></h2>
|
|
||||||
|
|
||||||
<p>A mutex (short for mutual-exclusion) concept serializes access to a
|
|
||||||
resource shared between multiple threads. The <a href="#Mutex">
|
|
||||||
Mutex</a> concept, with <a href="#TryMutex">TryMutex</a> and <a href=
|
|
||||||
"#TimedMutex">TimedMutex</a> refinements, formalize the requirements. A
|
|
||||||
model that implements Mutex and its refinements has two states: <b>
|
|
||||||
locked</b> and <b>unlocked</b>. Before using a shared resource, a
|
|
||||||
thread locks a Boost.Threads mutex model object, insuring <a href=
|
|
||||||
"definitions.html#Thread-safe">thread-safe</a> access to the shared
|
|
||||||
resource. When use of the shared resource is complete, the thread
|
|
||||||
unlocks the mutex model object, allowing another thread to acquire the
|
|
||||||
lock and use the shared resource.</p>
|
|
||||||
|
|
||||||
<p>Traditional C thread APIs, like Pthreads or the Windows thread APIs,
|
|
||||||
expose functions to lock and unlock a mutex model. This is dangerous
|
|
||||||
since it's easy to forget to unlock a locked mutex. When the flow
|
|
||||||
of control is complex, with multiple return points, the likelihood of
|
|
||||||
forgetting to unlock a mutex model would become even greater. When
|
|
||||||
exceptions are thrown, it becomes nearly impossible to ensure that the
|
|
||||||
mutex is unlocked properly when using these traditional API's. The
|
|
||||||
result is <a href="definitions.html#Deadlock">deadlock</a>.</p>
|
|
||||||
|
|
||||||
<p>Many C++ threading libraries use a pattern known as <i>Scoped
|
|
||||||
Locking</i> <a href="bibliography.html#Schmidt 00">[Schmidt 00]</a> to
|
|
||||||
free the programmer from the need to explicitly lock and unlock
|
|
||||||
mutexes. With this pattern, a <a href="lock_concept.html">lock
|
|
||||||
concept</a> is employed where the lock model's constructor locks
|
|
||||||
the associated mutex model and the destructor automatically does the
|
|
||||||
unlocking. The <b>Boost.Threads</b> library takes this pattern to the
|
|
||||||
extreme in that lock concepts are the only way to lock and unlock a
|
|
||||||
mutex model: lock and unlock functions are not exposed by any <b>
|
|
||||||
Boost.Threads</b> mutex models. This helps to ensure safe usage
|
|
||||||
patterns, especially when code throws exceptions.</p>
|
|
||||||
|
|
||||||
<h2><a name="LockingStrategies">Locking Strategies</a></h2>
|
|
||||||
|
|
||||||
<p>Every mutex model follows one of several locking strategies. These
|
|
||||||
strategies define the semantics for the locking operation when the
|
|
||||||
calling thread already owns a lock on the mutex model.</p>
|
|
||||||
|
|
||||||
<h3><a name="Recursive">Recursive</a></h3>
|
|
||||||
|
|
||||||
<p>With a recursive locking strategy when a thread attempts to acquire
|
|
||||||
a lock on the mutex model for which it already owns a lock, the
|
|
||||||
operation is successful. Note the distinction between a thread, which
|
|
||||||
may have multiple locks outstanding on a recursive mutex, and a lock
|
|
||||||
object, which even for a recursive mutex cannot have its lock()
|
|
||||||
function called multiple times without first calling unlock().</p>
|
|
||||||
|
|
||||||
<p>Internally a lock count is maintained and the owning thread must
|
|
||||||
unlock the mutex model the same number of times that it's locked it
|
|
||||||
before the mutex model's state returns to unlocked. Since mutex
|
|
||||||
models in <b>Boost.Threads</b> expose locking functionality only
|
|
||||||
through lock concepts, a thread will always unlock a mutex model the
|
|
||||||
same number of times that it locked it. This helps to eliminate a whole
|
|
||||||
set of errors typically found in traditional C style thread APIs.</p>
|
|
||||||
|
|
||||||
<p>Classes <a href="recursive_mutex.html">recursive_mutex</a>, <a href=
|
|
||||||
"recursive_mutex.html">recursive_try_mutex</a> and <a href=
|
|
||||||
"recursive_mutex.html">recursive_timed_mutex</a> use this locking
|
|
||||||
strategy.</p>
|
|
||||||
|
|
||||||
<h3><a name="CheckedStrategy">Checked</a></h3>
|
|
||||||
|
|
||||||
<p>With a checked locking strategy when a thread attempts to acquire a
|
|
||||||
lock on the mutex model for which the thread already owns a lock, the
|
|
||||||
operation will fail with some sort of error indication. Further,
|
|
||||||
attempts by a thread to unlock a mutex that was not locked by the
|
|
||||||
thread will also return some sort of error indication. In <b>
|
|
||||||
Boost.Threads</b>, an exception of type <a href="lock_error.html">
|
|
||||||
lock_error</a> would be thrown in these cases.</p>
|
|
||||||
|
|
||||||
<p><b>Boost.Threads</b> does not currently provide any mutex models
|
|
||||||
that use this strategy.</p>
|
|
||||||
|
|
||||||
<h3><a name="UncheckedStrategy">Unchecked</a></h3>
|
|
||||||
|
|
||||||
<p>With an unchecked locking strategy when a thread attempts to acquire
|
|
||||||
a lock on the mutex model for which the thread already owns a lock the
|
|
||||||
operation will <a href="definitions.html#Deadlock">deadlock</a>. In
|
|
||||||
general this locking strategy is less safe than a checked or recursive
|
|
||||||
strategy, but it's also a faster strategy and so is employed by
|
|
||||||
many libraries.</p>
|
|
||||||
|
|
||||||
<p><b>Boost.Threads</b> does not currently provide any mutex models
|
|
||||||
that use this strategy.</p>
|
|
||||||
|
|
||||||
<h3><a name="UnspecifiedStrategy">Unspecified</a></h3>
|
|
||||||
|
|
||||||
<p>With an unspecified locking strategy, when a thread attempts to
|
|
||||||
acquire a lock on a mutex model for which the thread already owns a
|
|
||||||
lock the operation results in <b>undefined behavior</b>. When a mutex
|
|
||||||
model has an unspecified locking strategy the programmer must assume
|
|
||||||
that the mutex model instead uses an unchecked strategy.</p>
|
|
||||||
|
|
||||||
<p>In general a mutex model with an unspecified locking strategy is
|
|
||||||
unsafe, and it requires programmer discipline to use the mutex model
|
|
||||||
properly. However, this strategy allows an implementation to be as fast
|
|
||||||
as possible with no restrictions on its implementation. This is
|
|
||||||
especially true for portable implementations that wrap the native
|
|
||||||
threading support of a platform. For this reason, the classes <a href=
|
|
||||||
"mutex.html">mutex</a>, <a href="mutex.html">try_mutex</a> and <a href=
|
|
||||||
"mutex.html">timed_mutex</a> use this locking strategy despite the lack
|
|
||||||
of safety.</p>
|
|
||||||
|
|
||||||
<h2><a name="SchedulingPolicies">Scheduling Policies</a></h2>
|
|
||||||
|
|
||||||
<p>Every mutex model follows one of several scheduling policies. These
|
|
||||||
policies define the semantics when the mutex model is unlocked and
|
|
||||||
there is more than one thread waiting to acquire a lock. In other
|
|
||||||
words, the policy defines which waiting thread shall acquire the
|
|
||||||
lock.</p>
|
|
||||||
|
|
||||||
<h3><a name="FIFO">FIFO</a></h3>
|
|
||||||
|
|
||||||
<p>With a FIFO scheduling policy, threads waiting for the lock will
|
|
||||||
acquire it in a first come first serve order (or First In First Out).
|
|
||||||
This can help prevent a high priority thread from starving lower
|
|
||||||
priority threads that are also waiting on the mutex lock.</p>
|
|
||||||
|
|
||||||
<h3><a name="Priority Driven">Priority Driven</a></h3>
|
|
||||||
|
|
||||||
<p>With a Priority Driven scheduling policy, the thread with the
|
|
||||||
highest priority acquires the lock. Note that this means that
|
|
||||||
low-priority threads may never acquire the lock if the mutex model has
|
|
||||||
high contention and there is always at least one high-priority thread
|
|
||||||
waiting. This is known as thread starvation. When multiple threads of
|
|
||||||
the same priority are waiting on the mutex lock one of the other
|
|
||||||
scheduling priorities will determine which thread shall acquire the
|
|
||||||
lock.</p>
|
|
||||||
|
|
||||||
<h3><a name="UndefinedScheduling">Undefined</a></h3>
|
<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>
|
||||||
|
<a href="#Recursive">Recursive</a><br>
|
||||||
<p>For a Mutex type M and an object m of that type, the following
|
<a href="#CheckedStrategy">Checked</a><br>
|
||||||
expressions must be well-formed and have the indicated effects.</p>
|
<a href="#UncheckedStrategy">Unchecked</a><br>
|
||||||
|
<a href="#UnspecifiedStrategy">Unspecified</a><br>
|
||||||
<table summary="Mutex expressions" border="1" cellpadding="5">
|
<a href="#SchedulingPolicies">Scheduling Policies</a><br>
|
||||||
<tr>
|
<a href="#FIFO">FIFO</a><br>
|
||||||
<td><b>Expression</b></td>
|
<a href="#Priority Driven">Priority Driven</a><br>
|
||||||
|
<a href="#UndefinedScheduling">Undefined</a><br>
|
||||||
<td><b>Effects</b></td>
|
<a href="#UnspecifiedScheduling">Unspecified</a><br>
|
||||||
</tr>
|
<a href="#Requirements">Concept Requirements</a><br>
|
||||||
|
<a href="#Mutex">Mutex Concept</a><br>
|
||||||
<tr>
|
<a href="#TryMutex">TryMutex Concept</a><br>
|
||||||
<td><code>M m;</code></td>
|
<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>(&m)->~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"> </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>© 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>(&m)->~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"> </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>
|
||||||
|
|
||||||
|
|||||||
@@ -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. 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><a href="definitions.html#Deadlock">Deadlock</a> (sometimes called
|
||||||
|
"deadly embrace")
|
||||||
|
<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'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>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. </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>]. 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. </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>
|
||||||
|
|
||||||
<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 "deadly embrace")</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'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'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>© Copyright 2001 Beman Dawes</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -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 "potential parallelism"
|
<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'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'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>
|
||||||
"pthread" library. However, this is a standard only on POSIX
|
|
||||||
platforms, so its portability is limited.</p>
|
|
||||||
|
|
||||||
<p>Another problem with POSIX and other platform specific thread
|
<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's available in a C library.</p>
|
|
||||||
|
|
||||||
<p>What'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'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'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'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'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'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'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'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'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'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'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'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'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't
|
|
||||||
a problem, and so long as the lock object is properly used there's
|
|
||||||
no danger of any multi-threading issues.</p>
|
|
||||||
|
|
||||||
<h2><a name="thread">Rationale for Non-copyable Thread Type</a></h2>
|
<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'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'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'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
|
||||||
"reference management" 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 "thread" 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't appear to bear
|
|
||||||
them out. To illustrate the analysis we'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'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'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'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'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't a "typical need" for a
|
there is some need.</p>
|
||||||
thread concept, though there is some need.</p>
|
|
||||||
|
|
||||||
<p>Since the need isn'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'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'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'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'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'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's
|
|
||||||
reference management, and in fact, theoretically at least, the
|
|
||||||
thread_ref may do a better job of managing the references. All of this
|
|
||||||
indicates that thread wins for (1), (2) and (3), with (4) and (5) the
|
|
||||||
winner depends on the implementation and the platform but the thread
|
|
||||||
design probably has a better chance, and with (6) it will again depend
|
|
||||||
on the implementation and platform but this time we favor thread_ref
|
|
||||||
slightly. Given all of this it's a narrow margin, but the thread
|
|
||||||
design prevails.</p>
|
|
||||||
|
|
||||||
<p>Given this analysis, and the fact that noncopyable objects for
|
<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. <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 "<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>". 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 "<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>". 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. 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. 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. 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. It seems
|
||||||
variables. Overt problems can be avoided, for example, by teaming the
|
similar to the "goto considered harmful" 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 "goto considered harmful" controversy of
|
|
||||||
30 years ago. It isn't that events, like gotos, can't be made
|
|
||||||
to work, but rather that virtually all programs using alternatives will
|
|
||||||
be easier to write, debug, read, maintain, and 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>© 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>
|
||||||
|
|
||||||
|
|||||||
@@ -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 "internal
|
is when a class supplies "internal synchronization" to ensure
|
||||||
synchronization" 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<recursive_mutex></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<recursive_try_mutex><br>
|
||||||
|
</code></a><code><a href="scoped_try_lock.html">detail::thread::scoped_try_lock<recursive_try_mutex></a></code></td>
|
||||||
|
<td valign="middle"><a href="lock_concept.html#ScopedLock">ScopedLock</a><br>
|
||||||
|
<a href="lock_concept.html#ScopedTryLock">ScopedTryLock</a></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<recursive_timed_mutex></code></a><br>
|
||||||
|
<a href="scoped_try_lock.html"><code>detail::thread::scoped_try_lock<recursive_timed_mutex></code></a><br>
|
||||||
|
<a href="scoped_timed_lock.html"><code>detail::thread::scoped_timed_lock<recursive_timed_mutex></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<recursive_mutex></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<recursive_try_mutex><br>
|
|
||||||
</code></a> <code><a href="scoped_try_lock.html">
|
|
||||||
detail::thread::scoped_try_lock<recursive_try_mutex></a></code></td>
|
|
||||||
|
|
||||||
<td valign="middle"><a href="lock_concept.html#ScopedLock">
|
|
||||||
ScopedLock</a><br>
|
|
||||||
<a href="lock_concept.html#ScopedTryLock">
|
|
||||||
ScopedTryLock</a></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<recursive_timed_mutex></code></a><br>
|
|
||||||
|
|
||||||
<a href="scoped_try_lock.html"><code>
|
|
||||||
detail::thread::scoped_try_lock<recursive_timed_mutex></code></a><br>
|
|
||||||
|
|
||||||
<a href="scoped_timed_lock.html"><code>
|
|
||||||
detail::thread::scoped_timed_lock<recursive_timed_mutex></code></a></td>
|
|
||||||
|
|
||||||
<td valign="middle"><a href="lock_concept.html#ScopedLock">
|
|
||||||
ScopedLock</a><br>
|
|
||||||
<a href="lock_concept.html#ScopedTryLock">
|
|
||||||
ScopedTryLock</a><br>
|
|
||||||
<a href="lock_concept.html#ScopedTimedLock">
|
|
||||||
ScopedTimedLock</a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<p>The <code>recursive_mutex</code>, <code>recursive_try_mutex</code>
|
|
||||||
and <code>recursive_timed_mutex</code> employ a <code>Recursive</code>
|
|
||||||
<a href="mutex_concept.html#LockingStrategies">locking strategy</a>, so
|
|
||||||
attempts to recursively lock them succeed and an internal "lock
|
|
||||||
count" is maintained. Attempts to unlock them by a thread that
|
|
||||||
does not own a lock on them will result in a <a href="lock_error.html">
|
|
||||||
lock_error</a> exception being thrown.</p>
|
|
||||||
|
|
||||||
<p>The <code>recursive_mutex</code>, <code>recursive_try_mutex</code>
|
|
||||||
and <code>recursive_timed_mutex</code> leave the <a href=
|
|
||||||
"mutex_concept.html#SchedulingPolicies">scheduling policy</a> as <code>
|
|
||||||
Unspecified</code>. Programmers should assume that threads waiting for
|
|
||||||
a lock on objects of these types acquire the lock in a random order,
|
|
||||||
even though the specific behavior for a given platform may be
|
|
||||||
different.</p>
|
|
||||||
|
|
||||||
<h2><a name="Header">Header</a></h2>
|
|
||||||
<pre>
|
<pre>
|
||||||
#include <a href=
|
#include <a href="../../../boost/thread/recursive_mutex.hpp"><boost/thread/recursive_mutex.hpp></a>
|
||||||
"../../../boost/thread/recursive_mutex.hpp"><boost/thread/recursive_mutex.hpp></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"><boost/thread/recursive_mutex.hpp></a>
|
||||||
"../../../boost/thread/recursive_mutex.hpp"><boost/thread/recursive_mutex.hpp></a>
|
#include <a href="../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
||||||
#include <a href=
|
|
||||||
"../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
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>© 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>
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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 "resource
|
<p>Class <code> scoped_lock</code> follows the "resource acquisition is
|
||||||
acquisition is initialization" idiom <a href=
|
initialization" 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 "Scoped Locking Pattern"
|
||||||
realization of the "Scoped Locking Pattern" <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"><boost/thread/detail/lock.hpp></a>
|
||||||
"../../../boost/thread/detail/lock.hpp"><boost/thread/detail/lock.hpp></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"><boost/thread/mutex.hpp></a> or
|
||||||
"../../../boost/thread/mutex.hpp"><boost/thread/mutex.hpp></a> or
|
<a href="../../../boost/thread/recursive_mutex.hpp"><boost/thread/recursive_mutex.hpp></a></i>
|
||||||
<a href=
|
|
||||||
"../../../boost/thread/recursive_mutex.hpp"><boost/thread/recursive_mutex.hpp></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 <typename Mutex>
|
template <typename Mutex>
|
||||||
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& mx, bool initially_locked=true);
|
explicit scoped_lock(Mutex& 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->operator const void*() != 0</code>.</p>
|
||||||
|
|
||||||
<p><b>Returns:</b> <code>this->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>© 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>
|
||||||
|
|
||||||
|
|||||||
@@ -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 "resource
|
<p>Class <code>scoped_timed_lock</code> follows the "resource acquisition is
|
||||||
acquisition is initialization" idiom <a href=
|
initialization" 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 "Scoped Locking Pattern"
|
||||||
realization of the "Scoped Locking Pattern" <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"><boost/thread/detail/lock.hpp></a>
|
||||||
"../../../boost/thread/detail/lock.hpp"><boost/thread/detail/lock.hpp></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"><boost/thread/mutex.hpp></a> or
|
||||||
"../../../boost/thread/mutex.hpp"><boost/thread/mutex.hpp></a> or
|
<a href="../../../boost/thread/recursive_mutex.hpp"><boost/thread/recursive_mutex.hpp></a></i>
|
||||||
<a href=
|
|
||||||
"../../../boost/thread/recursive_mutex.hpp"><boost/thread/recursive_mutex.hpp></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 <typename TimedMutex>
|
template <typename TimedMutex>
|
||||||
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& mx, const <a href=
|
scoped_timed_lock(TimedMutex& mx, const <a href="xtime.html">xtime</a>& xt);
|
||||||
"xtime.html">xtime</a>& 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& mx, bool initially_locked);
|
scoped_timed_lock(TimedMutex& 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>& xt);
|
bool timed_lock(const <a href="xtime.html">xtime</a>& 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->operator const void*() !=
|
<p><b>Returns:</b> <code>this->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 <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -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>© 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>
|
||||||
|
|
||||||
|
|||||||
@@ -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 "resource
|
<p>Class <code> scoped_try_lock</code> follows the "resource acquisition is
|
||||||
acquisition is initialization" idiom <a href=
|
initialization" 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 "Scoped Locking Pattern"
|
||||||
realization of the "Scoped Locking Pattern" <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"><boost/thread/detail/lock.hpp></a>
|
||||||
"../../../boost/thread/detail/lock.hpp"><boost/thread/detail/lock.hpp></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"><boost/thread/mutex.hpp></a> or
|
||||||
"../../../boost/thread/mutex.hpp"><boost/thread/mutex.hpp></a> or
|
<a href="../../../boost/thread/recursive_mutex.hpp"><boost/thread/recursive_mutex.hpp></a></i>
|
||||||
<a href=
|
|
||||||
"../../../boost/thread/recursive_mutex.hpp"><boost/thread/recursive_mutex.hpp></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 <typename TryMutex>
|
template <typename TryMutex>
|
||||||
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& mx);
|
explicit scoped_try_lock(TryMutex& 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& mx, bool initially_locked);
|
scoped_try_lock(TryMutex& 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->operator const void*() !=
|
<p><b>Returns:</b> <code>this->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"><boost/thread/mutex.hpp></a>
|
||||||
"../../../boost/thread/mutex.hpp"><boost/thread/mutex.hpp></a>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
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>© 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
226
doc/semaphore.html
Normal 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. </p>
|
||||||
|
|
||||||
|
<p>The dangers are spelled out by <a href="bibliography.html#Andrews-83">[Andrews-83]</a>
|
||||||
|
(function names updated, see historical note below): </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 "passeren", "to pass"), and for <b>up()</b>
|
||||||
|
was <b>V</b> (short for the Dutch "vrygeven", "to release").</p>
|
||||||
|
|
||||||
|
<h2><a name="Header">Header</a></h2>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
#include <a href="../../../boost/thread/semaphore.hpp"><boost/thread/semaphore.hpp></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& 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> m_count = count;<br>
|
||||||
|
m_max = (max == 0 ? std::numeric_limits<unsigned>::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> unsigned ct;<br>
|
||||||
|
bool ret;<br>
|
||||||
|
{ // as a single atomic operation:<br>
|
||||||
|
ct = m_count;<br>
|
||||||
|
if (m_count == m_max) ret =
|
||||||
|
false;<br>
|
||||||
|
else<br>
|
||||||
|
{<br>
|
||||||
|
ret =
|
||||||
|
true;<br>
|
||||||
|
++m_count;<br>
|
||||||
|
}<br>
|
||||||
|
}<br>
|
||||||
|
if (prev) *prev = m_count;<br>
|
||||||
|
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> </code></p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
bool down(const <a href="xtime.html">xtime</a>& 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> </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"><boost/thread/semaphore.hpp></a>
|
||||||
|
#include <a href="../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int global_data = 0;
|
||||||
|
boost::semaphore global_semaphore(1);
|
||||||
|
|
||||||
|
void change_global_data(void*)
|
||||||
|
{
|
||||||
|
global_semaphore.down();
|
||||||
|
++global_data;
|
||||||
|
std::cout << "global_data == " << global_data << std::endl;
|
||||||
|
global_semaphore.up();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char*[])
|
||||||
|
{
|
||||||
|
const int num_threads = 4;
|
||||||
|
boost::thread_group thrds;
|
||||||
|
for (int i=0; i < num_threads; ++i)
|
||||||
|
thrds.create_thread(&change_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>
|
||||||
269
doc/thread.html
269
doc/thread.html
@@ -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 "thread of
|
"thread of execution", and for definitions of threading related terms and of thread
|
||||||
execution", and for definitions of threading related terms and of
|
states such as "blocked".</p>
|
||||||
thread states such as "blocked".</p>
|
|
||||||
|
|
||||||
<p>A thread of execution has an initial function. For the program'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 "finished" or
|
<p>A thread of execution is said to be "finished" or "finished execution" when its
|
||||||
"finished execution" 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
|
||||||
"joinable" or "non-joinable".</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"><boost/thread/thread.hpp></A>
|
||||||
"../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></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><void>& threadfunc);
|
||||||
"../../function/index.html">boost::function0</a><void>& 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 "detached". 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& rhs);
|
bool operator==(const thread& 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& rhs);
|
bool operator!=(const thread& 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'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>& xt);
|
static void sleep(const <a href="xtime.html">xtime</a>& 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>
|
||||||
"ready" 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 <boost/thread/thread.hpp>
|
#include <boost/thread/thread.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -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>© 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>
|
||||||
|
|
||||||
|
|||||||
@@ -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"><boost/thread/thread.hpp></a>
|
||||||
"../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></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. 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<void>& threadfunc);
|
thread* create_thread(const boost::function0<void>& 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'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'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>'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>'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 <boost/thread/thread.hpp>
|
#include <boost/thread/thread.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -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>© 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>
|
||||||
|
|
||||||
|
|||||||
@@ -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"><boost/thread/exceptions.hpp></a>
|
||||||
"../../../boost/thread/thread.hpp"><boost/thread/exceptions.hpp></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>© 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>
|
||||||
|
|
||||||
|
|||||||
@@ -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"><boost/thread/tss.hpp></a>
|
||||||
"../../../boost/thread/tss.hpp"><boost/thread/tss.hpp></a>
|
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
namespace boost {
|
namespace boost {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
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'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->() const;
|
T* operator->() const;
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p><b>Returns:</b> <code>get()</code></p>
|
<p><b>Returns:</b> <code>get()</code></p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
T& operator*() const;
|
T& 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"><boost/thread/thread.hpp></a>
|
||||||
"../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
#include <a href="../../../boost/thread/tss.hpp"><boost/thread/tss.hpp></a>
|
||||||
#include <a href=
|
|
||||||
"../../../boost/thread/tss.hpp"><boost/thread/tss.hpp></a>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
boost::thread_specific_ptr<int> value;
|
boost::thread_specific_ptr<int> value;
|
||||||
@@ -194,7 +184,7 @@ void increment()
|
|||||||
|
|
||||||
void thread_proc()
|
void thread_proc()
|
||||||
{
|
{
|
||||||
value.reset(new int(0)); // initialize the thread's storage
|
value.reset(new int(0)); // initialize the thread's storage
|
||||||
for (int i=0; i<10; ++i)
|
for (int i=0; i<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>© 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>
|
||||||
|
|
||||||
|
|||||||
146
doc/xtime.html
146
doc/xtime.html
@@ -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'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"><boost/thread/xtime.hpp></a>
|
||||||
"../../../boost/thread/xtime.hpp"><boost/thread/xtime.hpp></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"><boost/thread/thread.hpp></a>
|
||||||
"../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
#include <a href="../../../boost/thread/tss.hpp"><boost/thread/xtime.hpp></a>
|
||||||
#include <a href=
|
|
||||||
"../../../boost/thread/tss.hpp"><boost/thread/xtime.hpp></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>© 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>
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
61
include/boost/thread/_atomic.hpp
Normal file
61
include/boost/thread/_atomic.hpp
Normal 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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
57
include/boost/thread/semaphore.hpp
Normal file
57
include/boost/thread/semaphore.hpp
Normal 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
|
||||||
@@ -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:
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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
80
src/_atomic.cpp
Normal 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
|
||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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)
|
||||||
|
|||||||
54
src/once.cpp
54
src/once.cpp
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
179
src/semaphore.cpp
Normal 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.
|
||||||
@@ -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, ¶m, 0, &m_id));
|
m_thread = _beginthreadex(0, 0, &thread_proxy, ¶m, 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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
18
test/Jamfile
18
test/Jamfile
@@ -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 ;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user