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

Compare commits

..

76 Commits

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


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

[SVN r10341]
2001-06-15 15:42:44 +00:00
140 changed files with 6633 additions and 9819 deletions

View File

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

View File

@@ -1,61 +1,40 @@
# (C) Copyright William E. Kempf 2001. Permission to copy, use, modify, # (C) Copyright William E. Kempf 2001. Permission to copy, use, modify, sell and
# sell and distribute this software is granted provided this copyright # distribute this software is granted provided this copyright notice appears
# notice appears in all copies. This software is provided "as is" without # in all copies. This software is provided "as is" without express or implied
# express or implied warranty, and with no claim as to its suitability for # warranty, and with no claim as to its suitability for any purpose.
# any purpose.
# #
# Boost.Threads build Jamfile # Boost.Threads build and test Jamfile
# #
# Additional configuration variables used: # Declares the following targets:
# 1. PTW32 may be used on Win32 platforms to specify that the pthreads-win32 # 1. libboost_thread, a static link library.
# library should be used instead of "native" threads. This feature is # 1a. On Win32, a dynamic link library libboost_threadmon,
# mostly used for testing and it's generally recommended you use the # which must be used in conjunction with libboost_thread.
# native threading libraries instead. PTW32 should be set to be a list
# of two strings, the first specifying the installation path of the
# pthreads-win32 library and the second specifying which library
# variant to link against (see the pthreads-win32 documentation).
# Example: jam -sPTW32="c:\pthreads-win32 pthreadVCE.lib"
# Declare the location of this subproject relative to the root. # declare the location of this subproject relative to the root
subproject libs/thread/build ; subproject libs/thread/build ;
# Include threads.jam for Boost.Threads global build information. #######################
# This greatly simplifies the Jam code needed to configure the build
# for the various Win32 build types.
import ./threads ;
#
# Declare the Boost.Threads static link library.
#
# For Win32 we need to build a special DLL, libboost_threadmon, to handle
# TSS destruction.
if $(NT)
{ {
template thread_libs dll libboost_threadmon : ../src/threadmon.cpp
## sources ## # requirements
: <template>thread_base : <threading>multi
## requirements ## : debug release ;
: <sysinclude>$(BOOST_ROOT)
## default build ##
: debug release
;
# Base names of the source files for libboost_thread.
CPP_SOURCES = condition mutex recursive_mutex thread tss xtime once
exceptions threadmon ;
dll boost_thread
: <template>thread_libs ../src/$(CPP_SOURCES).cpp
: <define>BOOST_THREAD_BUILD_DLL=1
<runtime-link>dynamic
# the common names rule ensures that the library will
# be named according to the rules used by the install
# and auto-link features:
common-variant-tag
;
stage bin-stage
: <dll>boost_thread
: #<tag><runtime-link-static>"s"
<tag><debug>"d"
: debug release
;
install thread lib
: <dll>boost_thread
;
} }
# Base names of the source files for libboost_thread
CPP_SOURCES =
condition mutex recursive_mutex semaphore thread tss xtime once ;
lib libboost_thread : ../src/$(CPP_SOURCES).cpp
# requirements
: <include>$(BOOST_ROOT)
<threading>multi
: debug release ;

View File

@@ -1,26 +0,0 @@
import os ;
if [ os.name ] = NT
{
reqts = <link>shared:<define>BOOST_THREAD_BUILD_DLL=1 ;
}
else
{
# Declare the uses system library
lib pthread : : <name>pthread ;
usage = <library>pthread ;
}
project boost/thread
: source-location ../src
: usage-requirements $(usage)
: requirements $(reqts) <threading>multi
: default-build <threading>multi
;
CPP_SOURCES = condition mutex recursive_mutex thread tss xtime once
exceptions threadmon ;
lib boost_thread
: $(CPP_SOURCES).cpp
;

View File

@@ -1,29 +0,0 @@
# Do some OS-specific setup
{
pthreads-win32 = ;
if $(NT)
{
if $(PTW32)
{
local install-path = $(PTW32[1]) ;
local lib = $(PTW32[2]) ;
pthreads-win32 =
<define>BOOST_HAS_PTHREADS
<define>PtW32NoCatchWarn
<include>$(install-path)/pre-built/include
<library-file>$(install-path)/pre-built/lib/$(lib)
;
}
}
template thread_base
## sources ##
:
## requirements ##
: <sysinclude>$(BOOST_ROOT) <threading>multi $(pthreads-win32)
<borland><*><cxxflags>-w-8004
## default build ##
:
;
}

Binary file not shown.

72
doc/acknowledgements.html Normal file
View File

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

View File

@@ -1,69 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../../../boost.css">
<title>Boost.Threads - Acknowledgments</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Acknowledgments</h2>
</td>
</tr>
</table>
<hr>
<p><a href="../../../people/william_kempf.htm">William E. Kempf</a> was the architect,
designer, and implementor of <b>Boost.Threads</b>.</p>
<p>Mac OS Carbon implementation written by <a href="../../../people/mac_murrett.htm">Mac
Murrett</a>.</p>
<p>Important contributions were also made by Jeremy Siek (lots of input on the
design and on the implementation), Alexander Terekhov (lots of input on the
Win32 implementation, especially in regards to boost::condition, as well as
a lot of explanation of POSIX behavior), Greg Colvin (lots of input on the design),
Paul Mclachlan, Thomas Matelich and Iain Hanson (for help in trying to get the
build to work on other platforms), Kevin S. Van Horn (for several updates/corrections
to the documentation), and Martin Johnson (shared library implementation).</p>
<p>The documentation was written by William E. Kempf. Beman Dawes provided additional
documentation material and editing.</p>
<p>Discussions on the boost.org mailing list were essential in the development
of <b>Boost.Threads</b>. As of August 1, 2001, participants included Alan Griffiths,
Albrecht Fritzsche, Aleksey Gurtovoy, Alexander Terekhov, Andrew Green, Andy
Sawyer, Asger Alstrup Nielsen, Beman Dawes, Bill Klein, Bill Rutiser, Bill Wade,
Branko &Egrave;ibej, Brent Verner, Craig Henderson, Csaba Szepesvari, Dale Peakall,
Damian Dixon, Dan Nuffer, Darryl Green, Daryle Walker, David Abrahams, David
Allan Finch, Dejan Jelovic, Dietmar Kuehl, Doug Gregor, Douglas Gregor, Duncan
Harris, Ed Brey, Eric Swanson, Eugene Karpachov, Fabrice Truillot, Frank Gerlach,
Gary Powell, Gernot Neppert, Geurt Vos, Ghazi Ramadan, Greg Colvin, Gregory
Seidman, HYS, Iain Hanson, Ian Bruntlett, J Panzer, Jeff Garland, Jeff Paquette,
Jens Maurer, Jeremy Siek, Jesse Jones, Joe Gottman, John (EBo) David, John Bandela,
John Maddock, John Max Skaller, John Panzer, Jon Jagger , Karl Nelson, Kevlin
Henney, KG Chandrasekhar, Levente Farkas, Lie-Quan Lee, Lois Goldthwaite, Luis
Pedro Coelho, Marc Girod, Mark A. Borgerding, Mark Rodgers, Marshall Clow, Matthew
Austern, Matthew Hurd, Michael D. Crawford, Michael H. Cox , Mike Haller, Miki
Jovanovic, Nathan Myers, Paul Moore, Pavel Cisler, Peter Dimov, Petr Kocmid,
Philip Nash, Rainer Deyke, Reid Sweatman, Ross Smith, Scott McCaskill, Shalom
Reich , Steve Cleary, Steven Kirk, Thomas Holenstein, Thomas Matelich, Trevor
Perrin, Valentin Bonnard, Vesa Karvonen, Wayne Miller, and William Kempf.</p>
<p>Apologies for anyone inadvertently missed.</p>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
05 November, 2001
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="mailto:wekempf@cox.net">William E. Kempf</a> 2001-2002.
All Rights Reserved.</i></p>
<p>Permission to use, copy, modify, distribute and sell this software and its
documentation for any purpose is hereby granted without fee, provided that the
above copyright notice appear in all copies and that both that copyright notice
and this permission notice appear in supporting documentation. William E. Kempf
makes no representations about the suitability of this software for any purpose.
It is provided &quot;as is&quot; without express or implied warranty.</p>
</body>
</html>

View File

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

View File

@@ -1,77 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../../../boost.css">
<title>{{Library}} - Overview</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Building and Testing</h2>
</td>
</tr>
</table>
<hr>
<dl class="index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#topic1">First topic</a></dt>
<dt><a href="#topic2">Second topic</a></dt>
<dt><a href="#footnotes">Footnotes</a></dt>
</dl>
<h2><a name="introduction"></a>Introduction</h2>
<p>How you build the Boost.Threads libraries, and how you build your own applications
that use those libraries, are some of the most frequently asked questions. Build
processes are difficult to deal with in a portable manner. That's one reason
why Boost.Threads makes use of <a href="../../../tools/build/index.html">Boost.Build</a>.
In general you should refer to the documentation for <a href="../../../tools/build/index.html">Boost.Build</a>.
This document will only supply you with some simple usage examples for how to
use <em>bjam</em> to build and test Boost.Threads. In addition, this document
will try and explain the build requirements so that users may create their own
build processes (for instance, create an IDE specific project), both for building
and testing Boost.Threads, as well as for building their own projects using
Boost.Threads. </p>
<h2><a name="topic1"></a>Building the Boost.Threads Libraries</h2>
<p>To build the Boost.Thread libraries using Boost.Build, simply change to the
directory <em>boost_root</em>/libs/thread/build and execute the command:</p>
<pre>bjam -sTOOLS=<em>toolset</em></pre>
<p>This will create four variants of the Boost.Threads library with the permuations
of debug/release and runtime-link-dynamic/runtime-link-static. <em><strong>Note:</strong></em>
Invoking the above command in <em>boost_root</em> will build all of the Boost
distribution, including Boost.Threads.</p>
<p>The Jamfile supplied with Boost.Threads produces a static library named <em>libboostthread</em>.
In addition, on Win32 platforms a <em>boostthreadmon.dll</em> and a coresponding
import library are created. The source files that are used to create the <em>libboostthread</em>
library are all of the *.cpp files found in <em>boost_root</em>/libs/thread/src,
except for <em>threadmon.cpp</em>. These need to be built with the compiler's
and linker's multi-threading support enabled. On Win32 platforms the <em>boostthreadmon.dll</em>
is created from <em>boost_root</em>/libs/thread/src/threadmon.cpp. This, too,
needs to be built with the compiler's and linker's multi-threading support enabled.
If you want to create your own build solution you'll have to follow these same
guidelines. One of the most frequently reported problems when trying to do this
occurs from not enabling the compiler's and linker's support for multi-threading.</p>
<h2><a name="topic2"></a>Testing the Boost.Threads Libraries</h2>
<p>To test the Boost.Threads libraries using Boost.Build, simply change to the
directory <em>boost_root</em>/libs/thread/test and execute the command:</p>
<pre><code>bjam -sTOOLS=<em>toolset</em> test</code></pre>
<p> </p>
<h2><a name="footnotes"></a>Footnotes</h2>
<dl>
<dt><a name="footnote1" class="footnote">(1)</a> {{text}}</dt>
<dt><a name="footnote2" class="footnote">(2)</a> {{text}}</dt>
</dl>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
05 November, 2001
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="mailto:{{address}}">{{author}}</a>
2002. All Rights Reserved.</i></p>
</body>
</html>

128
doc/call_once.html Normal file
View File

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

View File

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

103
doc/config.html Normal file
View File

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

View File

@@ -1,94 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../../../boost.css">
<title>Boost.Threads - Configuration</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Configuration</h2>
</td>
</tr>
</table>
<hr>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#lib-defined-public">Public Library Defined Macros</a></dt>
<dt><a href="#lib-defined-impl">Library Defined Implementation Macros</a></dt>
</dl>
<h2><a name="introduction"></a>Introduction</h2>
<p><b>Boost.Threads</b> uses several configuration macros in <a href="../../config/config.htm">&lt;boost/config.hpp&gt;</a>,
as well as configuration macros meant to be supplied by the application. These
macros are documented here.</p>
<h2><a name="lib-defined-public"></a>Public Library Defined Macros</h2>
<p>These macros are defined by <b>Boost.Threads</b> but are expected to be used
by application code.</p>
<table summary="public library defined macros" cellspacing="10" width="100%">
<tr>
<td><b>Macro</b></td>
<td><b>Meaning</b></td>
</tr>
<tr>
<td>BOOST_HAS_THREADS</td>
<td>Indicates that threading support is available. This means both that there
is a platform specific implementation for <b>Boost.Threads</b> and that
threading support has been enabled in a platform specific manner. For instance,
on the Win32 platform there&#39;s an implementation for <b>Boost.Threads</b>
but unless the program is compiled against one of the multithreading runtimes
(often determined by the compiler predefining the macro _MT) the BOOST_HAS_THREADS
macro remains undefined.</td>
</tr>
</table>
<h2><a name="lib-defined-impl"></a>Library Defined Implementation Macros</h2>
<p>These macros are defined by <b>Boost.Threads</b> and are implementation details
of interest only to implementors.</p>
<table summary="library defined implementation macros" cellspacing="10" width="100%">
<tr>
<td><b>Macro</b></td>
<td><b>Meaning</b></td>
</tr>
<tr>
<td>BOOST_HAS_WINTHREADS</td>
<td>Indicates that the platform has the Microsoft Win32 threading libraries,
and that they should be used to implement <b>Boost.Threads</b>.</td>
</tr>
<tr>
<td>BOOST_HAS_PTHREADS</td>
<td>Indicates that the platform has the POSIX pthreads libraries, and that
they should be used to implement <b>Boost.Threads</b>.</td>
</tr>
<tr>
<td>BOOST_HAS_FTIME</td>
<td>Indicates that the implementation should use GetSystemTimeAsFileTime()
and the FILETIME type to calculate the current time. This is an implementation
detail used by boost::detail::getcurtime().</td>
</tr>
<tr>
<td>BOOST_HAS_GETTTIMEOFDAY</td>
<td>Indicates that the implementation should use gettimeofday() to calculate
the current time. This is an implementation detail used by boost::detail::getcurtime().</td>
</tr>
</table>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
05 November, 2001
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="mailto:wekempf@cox.net">William E. Kempf</a> 2001-2002.
All Rights Reserved.</i></p>
<p>Permission to use, copy, modify, distribute and sell this software and its
documentation for any purpose is hereby granted without fee, provided that the
above copyright notice appear in all copies and that both that copyright notice
and this permission notice appear in supporting documentation. William E. Kempf
makes no representations about the suitability of this software for any purpose.
It is provided &quot;as is&quot; without express or implied warranty.</p>
</body>
</html>

View File

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

View File

@@ -1,110 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../../../boost.css">
<title>Boost.Threads - Header &lt;boost/thread/exceptions.hpp&gt;</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Header &lt;<a href="../../../boost/thread/exceptions.hpp">boost/thread/exceptions.hpp</a>&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#classes">Classes</a></dt>
<dl class="page-index">
<dt><a href="#class-lock_error">Class <code>lock_error</code></a></dt>
<dl class="page-index">
<dt><a href="#class-lock_error-synopsis">Class <code>lock_error</code> synopsis</a></dt>
<dt><a href="#class-lock_error-ctors">Class <code>lock_error</code> constructors
and destructor</a></dt>
</dl>
<dt><a href="#class-thread_resource_error">Class <code>thread_resource_error</code></a></dt>
<dl class="page-index">
<dt><a href="#class-thread_resource_error-synopsis">Class <code>thread_resource_error</code>
synopsis</a></dt>
<dt><a href="#class-thread_resource_error-ctors">Class <code>thread_resource_error</code>
constructors and destructor</a></dt>
</dl>
</dl>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p>Include the header &lt;<a href="../../../boost/thread/exceptions.hpp">boost/thread/exceptions.hpp</a>&gt;
to define the exception types that may be thrown by <b>Boost.Threads</b> classes.</p>
<h2><a name="classes"></a>Classes</h2>
<h3><a name="class-lock_error"></a>Class <code>lock_error</code></h3>
<p>The lock_error class defines an exception type thrown to indicate a locking
related error has been detected. Examples of such errors include a lock operation
which can be determined to result in a deadlock, or unlock operations attempted
by a thread that does not own the lock. </p>
<h4><a name="class-lock_error-synopsis"></a>Class <code>lock_error</code> synopsis</h4>
<pre>
namespace boost
{
class lock_error : public std::logical_error
{
public:
lock_error();
};
};
</pre>
<h4><a name="class-lock_error-ctors"></a>Class <code>lock_error</code> constructors
and destructor</h4>
<pre>
lock_error();
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Constructs a <code>lock_error</code> object.</dt>
</dl>
<h3><a name="class-thread_resource_error"></a>Class <code>thread_resource_error</code></h3>
<p>The thread_resource_error class defines an exception type that is thrown by
constructors in the Boost.Threads library when thread related resources can
not be acquired. This does not include memory allocation failures which instead
throw std::bad_alloc. </p>
<h4><a name="class-thread_resource_error-synopsis"></a>Class <code>thread_resource_error</code>
synopsis</h4>
<pre>
namespace boost
{
class thread_resource_error : public std::runtime_error
{
public:
thread_resource_error();
};
};
</pre>
<h4><a name="class-thread_resource_error-ctors"></a>Class <code>thread_resource_error</code>
constructors and destructor</h4>
<pre>
thread_resource_error();
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> Constructs a <code>thread_resource_error</code> object.</dt>
</dl>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
05 November, 2001
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="mailto:wekempf@cox.net">William E. Kempf</a> 2001-2002.
All Rights Reserved.</i></p>
<p>Permission to use, copy, modify, distribute and sell this software and its
documentation for any purpose is hereby granted without fee, provided that the
above copyright notice appear in all copies and that both that copyright notice
and this permission notice appear in supporting documentation. William E. Kempf
makes no representations about the suitability of this software for any purpose.
It is provided &quot;as is&quot; without express or implied warranty.</p>
</body>
</html>

View File

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

View File

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

View File

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

View File

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

111
doc/lock_error.html Normal file
View File

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

View File

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

View File

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

View File

@@ -1,90 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../../../boost.css">
<title>Boost.Threads - Header &lt;boost/thread/once.hpp&gt;</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Header &lt;<a href="../../../boost/thread/once.hpp">boost/thread/once.hpp</a>&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#macros">Macros</a></dt>
<dl class="page-index">
<dt><a href="#macro-BOOST_ONCE_INIT">BOOST_ONCE_INIT</a></dt>
</dl>
<dt><a href="#types">Types</a></dt>
<dl class="page-index">
<dt><a href="#type-once_flag">once_flag</a></dt>
</dl>
<dt><a href="#functions">Functions</a></dt>
<dl class="page-index">
<dt><a href="#function-call_once">call_once</a></dt>
</dl>
<dt><a href="#examples">Example(s)</a></dt>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p>Include the header &lt;<a href="../../../boost/thread/once.hpp">boost/thread/once.hpp</a>&gt;
to define the <code>call_once</code> function, <code>once_flag</code> type and
<code>BOOST_ONCE_INIT</code> constant.</p>
<p>The <code>call_once</code> function and <code>once_flag</code> type (statically
initialized to <code>BOOST_ONCE_INIT</code>) can be used to run a routine exactly
once. This can be used to initialize data in a <a href="definitions.html#Thread-safe">
thread-safe</a> manner.</p>
<h2><a name="macros"></a>Macros</h2>
<pre>
<a name="macro-BOOST_ONCE_INIT"></a>#define BOOST_ONCE_INIT <i>implementation defined</i>
</pre>
<p>This is a constant value used to initialize <code>once_flag</code> instances
to indicate that the logically associated routine has not been run yet.</p>
<h2><a name="types"></a>Types</h2>
<pre>
<a name="type-once_flag"></a>typedef <i>implementation defined</i> once_flag;
</pre>
<p>This implementation defined type is used as a flag to insure a routine is called
only once. Instances of this type should be statically initialized to <code>BOOST_ONCE_INIT</code>.</p>
<h2><a name="functions"></a>Functions</h2>
<pre>
<a name="function-call_once"></a>void call_once(void (*func)(), once_flag& flag);
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> The function <code>func</code> shall not throw exceptions.</dt>
<dt><b>Effects:</b> As if (in an atomic fashion):
<pre>
if (flag == BOOST_ONCE_INIT)
func();
</pre>
</dt>
<dt><b>Postconditions:</b> <code>flag != BOOST_ONCE_INIT</code></dt>
</dl>
<h2><a name="examples"></a>Example(s)</h2>
<p><a href="../example/once.cpp">libs/thread/example/once.cpp</a></p>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
05 November, 2001
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="mailto:wekempf@cox.net">William E. Kempf</a> 2001-2002.
All Rights Reserved.</i></p>
<p>Permission to use, copy, modify, distribute and sell this software and its
documentation for any purpose is hereby granted without fee, provided that the
above copyright notice appear in all copies and that both that copyright notice
and this permission notice appear in supporting documentation. William E. Kempf
makes no representations about the suitability of this software for any purpose.
It is provided &quot;as is&quot; without express or implied warranty.</p>
</body>
</html>

View File

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

View File

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

View File

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

134
doc/removed_atomic_t.html Normal file
View File

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

213
doc/scoped_lock.html Normal file
View File

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

261
doc/scoped_timed_lock.html Normal file
View File

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

282
doc/scoped_try_lock.html Normal file
View File

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

226
doc/semaphore.html Normal file
View File

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

4
doc/styles.css Normal file
View File

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

View File

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

187
doc/thread_group.html Normal file
View File

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

View File

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

View File

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

View File

@@ -1,169 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<link rel="stylesheet" type="text/css" href="../../../boost.css">
<title>Boost.Threads - Header &lt;boost/thread/tss.hpp&gt;</title>
</head>
<body link="#0000ff" vlink="#800080">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../c++boost.gif" border="0"></a></h3>
</td>
<td valign="top">
<h1 align="center">Boost.Threads</h1>
<h2 align="center">Header &lt;<a href="../../../boost/thread/tss.hpp">boost/thread/tss.hpp</a>&gt;</h2>
</td>
</tr>
</table>
<hr>
<h2>Contents</h2>
<dl class="page-index">
<dt><a href="#introduction">Introduction</a></dt>
<dt><a href="#classes">Classes</a></dt>
<dl class="page-index">
<dt><a href="#class-thread_specific_ptr">Class <code>thread_specific_ptr</code></a></dt>
<dl class="page-index">
<dt><a href="#class-thread_specific_ptr-synopsis">Class <code>thread_specific_ptr</code>
synopsis</a></dt>
<dt><a href="#class-thread_specific_ptr-ctors">Class <code>thread_specific_ptr</code>
constructors and destructor</a></dt>
<dt><a href="#class-thread_specific_ptr-modifiers">Class <code>thread_specific_ptr</code>
modifier functions</a></dt>
<dt><a href="#class-thread_specific_ptr-observers">Class <code>thread_specific_ptr</code>
observer functions</a></dt>
</dl>
</dl>
<dt><a href="#examples">Example(s)</a></dt>
</dl>
<hr>
<h2><a name="introduction"></a>Introduction</h2>
<p>The header &lt;<a href="../../../boost/thread/tss.hpp">boost/thread/tss.hpp</a>&gt;
defines the class <a href="#class-thread_specific_ptr">thread_specific_ptr</a>
which is used to manage data associated with specific thread instances.</p>
<h2><a name="classes"></a>Classes</h2>
<h3><a name="class-thread_specific_ptr"></a>Class <code>thread_specific_ptr</code></h3>
<p>The <code>thread_specific_ptr</code> class defines an interface for using thread
specific storage. Thread specific storage is data associated with individual
threads and is often used to make operations <a href="definitions.html#Thread-safe">thread-safe</a>
that rely on global data.</p>
<p>Template <code>thread_specific_ptr</code> stores a pointer to an object obtained
via <code>new</code> on a thread-by-thread basis and calls delete on the contained
pointer when the thread terminates. Each thread initially stores the null pointer
in each <code> thread_specific_ptr</code> instance.</p>
<p>The template <code>thread_specific_ptr</code> is useful in the following cases:</p>
<ul>
<li>An interface was originally written assuming a single thread of control
and is being ported to a multithreaded environment.</li>
<li>Each thread of control invokes sequences of methods that share data that
must be logically accessed through a globally visible access point, but are
physically unique for each thread, instead of being explicitly passed.</li>
</ul>
<h4><a name="class-thread_specific_ptr-synopsis"></a>Class <code>thread_specific_ptr</code>
synopsis</h4>
<pre>
namespace boost
{
template &lt;typename T&gt;
class thread_specific_ptr : private boost::noncopyable // Exposition only.
// Class thread_specific_ptr meets the <a href="overview.html#non-copyable">NonCopyable</a> requirement.
{
public:
thread_specific_ptr();
~thread_specific_ptr();
T* get() const;
T* operator-&gt;() const;
T&amp; operator*() const;
T* release();
void reset(T* p=0);
};
};
</pre>
<h4><a name="class-thread_specific_ptr-ctors"></a>Class <code>thread_specific_ptr</code>
constructors and destructor</h4>
<pre>
thread_specific_ptr();
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> The expression <code>delete get()</code> is well formed.</dt>
<dt><b>Postconditions:</b> A thread specific storage has been reserved for use
by <code>*this</code> in all threads, with each thread initially storing a
null pointer.</dt>
<dt><b>Throws:</b> <code>boost::thread_resource_error</code> if the necessary
resources can not be obtained.</dt>
<dt><b>Note:</b> There is an implementation specific limit to the number of
thread specific storage objects that can be created, and this limit may be
small.</dt>
</dl>
<pre>
~thread_specific_ptr();
</pre>
<dl class="function-semantics">
<dt><b>Note:</b> Does not destroy any data that may be stored in any thread&#39;s
thread specific storage. For this reason you should not destroy a <code>thread_specific_ptr</code>
object until you are certain there are no threads running that have made use
of its thread specific storage.</dt>
</dl>
<h4><a name="class-thread_specific_ptr-modifiers"></a>Class <code>thread_specific_ptr</code>
modifier functions</h4>
<pre>
T* release();
</pre>
<dl class="function-semantics">
<dt><b>Postconditions:</b> <code>*this</code> holds the null pointer for the
current thread.</dt>
<dt><b>Returns:</b> <code>this-&gt;get()</code> prior to the call.</dt>
</dl>
<pre>
void reset(T* p=0);
</pre>
<dl class="function-semantics">
<dt><b>Effects:</b> If <code>this-&gt;get()!= p</code> then <code>delete this-&gt;get()</code>.
</dt>
<dt><b>Postconditions:</b> <code>*this</code> holds the pointer <code> p</code>
for the current thread.</dt>
<dt><b>Note:</b> The pointer will be deleted when the thread terminates.</dt>
</dl>
<h4><a name="class-thread_specific_ptr-observers"></a>Class <code>thread_specific_ptr</code>
observer functions</h4>
<pre>
T* get() const;
</pre>
<dl class="function-semantics">
<dt><b>Returns:</b> The object stored in thread specific storage for the current
thread for <code>*this</code>.</dt>
<dt><b>Note:</b> Each thread initially returns 0.</dt>
</dl>
<pre>
T* operator-&gt;() const;
</pre>
<dl class="function-semantics">
<dt><b>Returns:</b> <code>this-&lt;get()</code>.</dt>
</dl>
<pre>
T& operator*() const;
</pre>
<dl class="function-semantics">
<dt><b>Requires:</b> <code>this-&lt;get() != 0</code></dt>
<dt><b>Returns:</b> <code>this-&lt;get()</code>.</dt>
</dl>
<h2><a name="examples"></a>Example(s)</h2>
<p><a href="../example/tss.cpp">libs/thread/example/tss.cpp</a></p>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
05 November, 2001
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
</p>
<p><i>&copy; Copyright <a href="mailto:wekempf@cox.net">William E. Kempf</a> 2001-2002.
All Rights Reserved.</i></p>
<p>Permission to use, copy, modify, distribute and sell this software and its
documentation for any purpose is hereby granted without fee, provided that the
above copyright notice appear in all copies and that both that copyright notice
and this permission notice appear in supporting documentation. William E. Kempf
makes no representations about the suitability of this software for any purpose.
It is provided &quot;as is&quot; without express or implied warranty.</p>
</body>
</html>

View File

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

View File

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

View File

@@ -1,48 +1,66 @@
# (C) Copyright William E. Kempf 2001. Permission to copy, use, modify, sell # (C) Copyright William E. Kempf 2001. Permission to copy, use, modify, sell and
# and distribute this software is granted provided this copyright notice # distribute this software is granted provided this copyright notice appears
# appears in all copies. This software is provided "as is" without express or # in all copies. This software is provided "as is" without express or implied
# implied warranty, and with no claim as to its suitability for any purpose. # warranty, and with no claim as to its suitability for any purpose.
# #
# Boost.Threads example Jamfile # Boost.Threads build and test Jamfile
# #
# Additional configuration variables used: # Declares the following targets:
# 1. PTW32 may be used on Win32 platforms to specify that the pthreads-win32 # 1. monitor, an example program.
# library should be used instead of "native" threads. This feature is # 2. starvephil, an example program.
# mostly used for testing and it's generally recommended you use the # 3. tennis, an example program.
# native threading libraries instead. PTW32 should be set to be a list
# of two strings, the first specifying the installation path of the
# pthreads-win32 library and the second specifying which library
# variant to link against (see the pthreads-win32 documentation).
# Example: jam -sPTW32="c:\pthreads-win32 pthreadVCE.lib"
# Declare the location of this subproject relative to the root. # declare the location of this subproject relative to the root
subproject libs/thread/example ; subproject libs/thread/example ;
# Include threads.jam for Boost.Threads global build information. # Do some OS-specific setup
# This greatly simplifies the Jam code needed to configure the build if $(NT)
# for the various Win32 build types.
import ../build/threads ;
{ {
template example BOOST_THREADMON_LIB = <lib>../build/libboost_threadmon ;
## sources ##
: <template>thread_base
<dll>../build/boost_thread
## requirements ##
:
## default build ##
:
;
exe monitor : <template>example monitor.cpp ;
exe starvephil : <template>example starvephil.cpp ;
exe tennis : <template>example tennis.cpp ;
exe condition : <template>example condition.cpp ;
exe mutex : <template>example mutex.cpp ;
exe once : <template>example once.cpp ;
exe recursive_mutex : <template>example recursive_mutex.cpp ;
exe thread : <template>example thread.cpp ;
exe thread_group : <template>example thread_group.cpp ;
exe tss : <template>example tss.cpp ;
exe xtime : <template>example xtime.cpp ;
} }
else
{
BOOST_THREADMON_LIB = ;
}
#######################
#
# Declare the Boost.Threads monitor example program.
#
exe monitor : monitor/monitor.cpp
<lib>../build/libboost_thread
$(BOOST_THREADMON_LIB)
# requirements
: <include>$(BOOST_ROOT)
<threading>multi
: debug release ;
#######################
#
# Declare the Boost.Threads starvephil example program.
#
exe starvephil : starvephil/starvephil.cpp
<lib>../build/libboost_thread
$(BOOST_THREADMON_LIB)
# requirements
: <include>$(BOOST_ROOT)
<threading>multi
: debug release ;
#######################
#
# Declare the Boost.Threads tennis example program.
#
exe tennis : tennis/tennis.cpp
<lib>../build/libboost_thread
$(BOOST_THREADMON_LIB)
# requirements
: <include>$(BOOST_ROOT)
<threading>multi
: debug release ;

View File

@@ -1,5 +0,0 @@
exe starvephil
: starvephil.cpp ../build/boost_thread ../../test/build/unit_test_framework
;

View File

@@ -1,79 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#include <iostream>
#include <vector>
#include <boost/utility.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/thread.hpp>
class bounded_buffer : private boost::noncopyable
{
public:
typedef boost::mutex::scoped_lock lock;
bounded_buffer(int n) : begin(0), end(0), buffered(0), circular_buf(n) { }
void send (int m) {
lock lk(monitor);
while (buffered == circular_buf.size())
buffer_not_full.wait(lk);
circular_buf[end] = m;
end = (end+1) % circular_buf.size();
++buffered;
buffer_not_empty.notify_one();
}
int receive() {
lock lk(monitor);
while (buffered == 0)
buffer_not_empty.wait(lk);
int i = circular_buf[begin];
begin = (begin+1) % circular_buf.size();
--buffered;
buffer_not_full.notify_one();
return i;
}
private:
int begin, end, buffered;
std::vector<int> circular_buf;
boost::condition buffer_not_full, buffer_not_empty;
boost::mutex monitor;
};
bounded_buffer buf(2);
void sender() {
int n = 0;
while (n < 100) {
buf.send(n);
std::cout << "sent: " << n << std::endl;
++n;
}
buf.send(-1);
}
void receiver() {
int n;
do {
n = buf.receive();
std::cout << "received: " << n << std::endl;
} while (n != -1); // -1 indicates end of buffer
}
int main(int, char*[])
{
boost::thread thrd1(&sender);
boost::thread thrd2(&receiver);
thrd1.join();
thrd2.join();
return 0;
}

View File

@@ -1,14 +1,3 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#include <vector> #include <vector>
#include <iostream> #include <iostream>
#include <boost/thread/condition.hpp> #include <boost/thread/condition.hpp>
@@ -17,23 +6,21 @@
#include <boost/thread/thread.hpp> #include <boost/thread/thread.hpp>
namespace { namespace {
const int ITERS = 100;
const int ITERS = 100; boost::mutex io_mutex;
boost::mutex io_mutex; };
} // namespace
template <typename M> template <typename M>
class buffer_t class buffer_t
{ {
public: public:
typedef typename M::scoped_lock scoped_lock; typedef typename M::scoped_lock scoped_lock;
buffer_t(int n) buffer_t(int n)
: p(0), c(0), full(0), buf(n) : p(0), c(0), full(0), buf(n)
{ {
} }
void send(int m) void send(int m)
{ {
scoped_lock lk(mutex); scoped_lock lk(mutex);
@@ -42,7 +29,7 @@ public:
buf[p] = m; buf[p] = m;
p = (p+1) % buf.size(); p = (p+1) % buf.size();
++full; ++full;
cond.notify_one(); cond.notify_all();
} }
int receive() int receive()
{ {
@@ -52,40 +39,41 @@ public:
int i = buf[c]; int i = buf[c];
c = (c+1) % buf.size(); c = (c+1) % buf.size();
--full; --full;
cond.notify_one(); cond.notify_all();
return i; return i;
} }
static buffer_t& get_buffer() static buffer_t& get_buffer()
{ {
static buffer_t buf(2); static buffer_t buf(2);
return buf; return buf;
} }
static void do_sender_thread() static void do_sender_thread()
{ {
for (int n = 0; n < ITERS; ++n) for (int n = 0; n < ITERS; ++n)
{ {
get_buffer().send(n);
{ {
boost::mutex::scoped_lock lock(io_mutex); boost::mutex::scoped_lock lock(io_mutex);
std::cout << "sending: " << n << std::endl; std::cout << "sent: " << n << std::endl;
} }
get_buffer().send(n);
} }
} }
static void do_receiver_thread() static void do_receiver_thread()
{ {
for (int x=0; x < (ITERS/2); ++x) int n;
do
{ {
int n = get_buffer().receive(); n = get_buffer().receive();
{ {
boost::mutex::scoped_lock lock(io_mutex); boost::mutex::scoped_lock lock(io_mutex);
std::cout << "received: " << n << std::endl; std::cout << "received: " << n << std::endl;
} }
} } while (n < ITERS - 1);
} }
private: private:
M mutex; M mutex;
boost::condition cond; boost::condition cond;
@@ -98,12 +86,10 @@ void do_test(M* dummy=0)
{ {
typedef buffer_t<M> buffer_type; typedef buffer_t<M> buffer_type;
buffer_type::get_buffer(); buffer_type::get_buffer();
boost::thread thrd1(&buffer_type::do_receiver_thread); boost::thread thrd1(&buffer_type::do_sender_thread);
boost::thread thrd2(&buffer_type::do_receiver_thread); boost::thread thrd2(&buffer_type::do_receiver_thread);
boost::thread thrd3(&buffer_type::do_sender_thread);
thrd1.join(); thrd1.join();
thrd2.join(); thrd2.join();
thrd3.join();
} }
void test_buffer() void test_buffer()

View File

@@ -1,52 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <iostream>
boost::mutex io_mutex; // The iostreams are not guaranteed to be thread-safe!
class counter
{
public:
counter() : count(0) { }
int increment() {
boost::mutex::scoped_lock scoped_lock(mutex);
return ++count;
}
private:
boost::mutex mutex;
int count;
};
counter c;
void change_count()
{
int i = c.increment();
boost::mutex::scoped_lock scoped_lock(io_mutex);
std::cout << "count == " << i << std::endl;
}
int main(int, char*[])
{
const int num_threads = 4;
boost::thread_group thrds;
for (int i=0; i < num_threads; ++i)
thrds.create_thread(&change_count);
thrds.join_all();
return 0;
}

View File

@@ -1,36 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#include <boost/thread/thread.hpp>
#include <boost/thread/once.hpp>
#include <cassert>
int value=0;
boost::once_flag once = BOOST_ONCE_INIT;
void init()
{
++value;
}
void thread_proc()
{
boost::call_once(&init, once);
}
int main(int argc, char* argv[])
{
boost::thread_group threads;
for (int i=0; i<5; ++i)
threads.create_thread(&thread_proc);
threads.join_all();
assert(value == 1);
}

View File

@@ -1,54 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/thread.hpp>
#include <iostream>
class counter
{
public:
counter() : count(0) { }
int add(int val) {
boost::recursive_mutex::scoped_lock scoped_lock(mutex);
count += val;
return count;
}
int increment() {
boost::recursive_mutex::scoped_lock scoped_lock(mutex);
return add(1);
}
private:
boost::recursive_mutex mutex;
int count;
};
counter c;
void change_count()
{
std::cout << "count == " << c.increment() << std::endl;
}
int main(int, char*[])
{
const int num_threads=4;
boost::thread_group threads;
for (int i=0; i < num_threads; ++i)
threads.create_thread(&change_count);
threads.join_all();
return 0;
}

View File

@@ -1,191 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
#include <iostream>
#include <time.h>
namespace {
boost::mutex iomx;
}
class canteen
{
public:
canteen() : m_chickens(0) { }
void get(int id)
{
boost::mutex::scoped_lock lock(m_mutex);
while (m_chickens == 0)
{
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << id <<
": wot, no chickens? I'll WAIT ..." << std::endl;
}
m_condition.wait(lock);
}
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << id <<
": those chickens look good ... one please ..." << std::endl;
}
m_chickens--;
}
void put(int value)
{
boost::mutex::scoped_lock lock(m_mutex);
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock()
<< ") Chef: ouch ... make room ... this dish is "
<< "very hot ..." << std::endl;
}
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 3;
boost::thread::sleep(xt);
m_chickens += value;
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() <<
") Chef: more chickens ... " << m_chickens <<
" now available ... NOTIFYING ..." << std::endl;
}
m_condition.notify_all();
}
private:
boost::mutex m_mutex;
boost::condition m_condition;
int m_chickens;
};
canteen g_canteen;
void chef()
{
const int chickens = 4;
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Chef: starting ..." << std::endl;
}
for (;;)
{
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Chef: cooking ..." << std::endl;
}
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 2;
boost::thread::sleep(xt);
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Chef: " << chickens
<< " chickens, ready-to-go ..." << std::endl;
}
g_canteen.put(chickens);
}
}
struct phil
{
phil(int id) : m_id(id) { }
void run() {
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << m_id
<< ": starting ..." << std::endl;
}
for (;;)
{
if (m_id > 0)
{
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 3;
boost::thread::sleep(xt);
}
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << m_id
<< ": gotta eat ..." << std::endl;
}
g_canteen.get(m_id);
{
boost::mutex::scoped_lock lock(iomx);
std::cout << "(" << clock() << ") Phil" << m_id
<< ": mmm ... that's good ..." << std::endl;
}
}
}
static void do_thread(void* param) {
static_cast<phil*>(param)->run();
}
int m_id;
};
struct thread_adapt
{
thread_adapt(void (*func)(void*), void* param)
: _func(func), _param(param)
{
}
int operator()() const
{
_func(_param);
return 0;
}
void (*_func)(void*);
void* _param;
};
class thread_adapter
{
public:
thread_adapter(void (*func)(void*), void* param)
: _func(func), _param(param)
{
}
void operator()() const { _func(_param); }
private:
void (*_func)(void*);
void* _param;
};
int main(int argc, char* argv[])
{
boost::thread thrd_chef(&chef);
phil p[] = { phil(0), phil(1), phil(2), phil(3), phil(4) };
boost::thread thrd_phil0(thread_adapter(&phil::do_thread, &p[0]));
boost::thread thrd_phil1(thread_adapter(&phil::do_thread, &p[1]));
boost::thread thrd_phil2(thread_adapter(&phil::do_thread, &p[2]));
boost::thread thrd_phil3(thread_adapter(&phil::do_thread, &p[3]));
boost::thread thrd_phil4(thread_adapter(&phil::do_thread, &p[4]));
thrd_chef.join();
thrd_phil0.join();
thrd_phil1.join();
thrd_phil2.join();
thrd_phil3.join();
thrd_phil4.join();
return 0;
}

View File

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

View File

@@ -1,23 +1,13 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#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>
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
# include <windows.h> # include <windows.h>
# include <process.h> # include <process.h>
#endif #endif
enum game_state enum game_state
@@ -60,8 +50,7 @@ void player(void* param)
{ {
cond.wait(lock); cond.wait(lock);
if (state == other) if (state == other)
std::cout << "---" << player_name(active) std::cout << "---" << player_name(active) << ": Spurious wakeup!" << std::endl;
<< ": Spurious wakeup!" << std::endl;
} while (state == other); } while (state == other);
} }
@@ -72,10 +61,7 @@ void player(void* param)
struct thread_adapt struct thread_adapt
{ {
thread_adapt(void (*func)(void*), void* param) thread_adapt(void (*func)(void*), void* param) : _func(func), _param(param) { }
: _func(func), _param(param)
{
}
int operator()() const int operator()() const
{ {
_func(_param); _func(_param);
@@ -89,10 +75,7 @@ struct thread_adapt
class thread_adapter class thread_adapter
{ {
public: public:
thread_adapter(void (*func)(void*), void* param) thread_adapter(void (*func)(void*), void* param) : _func(func), _param(param) { }
: _func(func), _param(param)
{
}
void operator()() const { _func(_param); } void operator()() const { _func(_param); }
private: private:
void (*_func)(void*); void (*_func)(void*);

View File

@@ -1,40 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
#include <iostream>
struct thread_alarm
{
thread_alarm(int secs) : m_secs(secs) { }
void operator()()
{
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += m_secs;
boost::thread::sleep(xt);
std::cout << "alarm sounded..." << std::endl;
}
int m_secs;
};
int main(int argc, char* argv[])
{
int secs = 5;
std::cout << "setting alarm for 5 seconds..." << std::endl;
thread_alarm alarm(secs);
boost::thread thrd(alarm);
thrd.join();
}

View File

@@ -1,30 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#include <boost/thread/thread.hpp>
#include <iostream>
int count = 0;
boost::mutex mutex;
void increment_count()
{
boost::mutex::scoped_lock lock(mutex);
std::cout << "count = " << ++count << std::endl;
}
int main(int argc, char* argv[])
{
boost::thread_group threads;
for (int i = 0; i < 10; ++i)
threads.create_thread(&increment_count);
threads.join_all();
}

View File

@@ -1,41 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#include <boost/thread/thread.hpp>
#include <boost/thread/tss.hpp>
#include <cassert>
boost::thread_specific_ptr<int> value;
void increment()
{
int* p = value.get();
++*p;
}
void thread_proc()
{
value.reset(new int(0)); // initialize the thread's storage
for (int i=0; i<10; ++i)
{
increment();
int* p = value.get();
assert(*p == i+1);
}
}
int main(int argc, char* argv[])
{
boost::thread_group threads;
for (int i=0; i<5; ++i)
threads.create_thread(&thread_proc);
threads.join_all();
}

View File

@@ -1,21 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
int main(int argc, char* argv[])
{
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += 1;
boost::thread::sleep(xt); // Sleep for 1 second
}

View File

@@ -1,24 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#if !defined(BOOST_THREAD_WEK01082003_HPP)
#define BOOST_THREAD_WEK01082003_HPP
#include <boost/thread/thread.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/once.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/tss.hpp>
#include <boost/thread/xtime.hpp>
#endif

View File

@@ -0,0 +1,61 @@
/*
*
* Copyright (C) 2001
* William E. Kempf
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. William E. Kempf makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* Revision History (excluding minor changes for specific compilers)
* 8 Feb 01 Initial version.
*/
#ifndef BOOST_ATOMIC_HPP
#define BOOST_ATOMIC_HPP
#include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS
# error Thread support is unavailable!
#endif
#if !defined(BOOST_HAS_WINTHREADS)
# include <boost/thread/mutex.hpp>
#endif
namespace boost {
class atomic_t
{
public:
typedef long value_type;
friend value_type read(const atomic_t&);
friend value_type increment(atomic_t&);
friend value_type decrement(atomic_t&);
friend value_type swap(atomic_t&, value_type);
friend value_type compare_swap(atomic_t&, value_type, value_type);
explicit atomic_t(value_type val=0)
: _value(val)
{
}
private:
volatile value_type _value;
#if !defined(BOOST_HAS_WINTHREADS)
mutex _mutex;
#endif
};
extern atomic_t::value_type read(const atomic_t&);
extern atomic_t::value_type increment(atomic_t&);
extern atomic_t::value_type decrement(atomic_t&);
extern atomic_t::value_type swap(atomic_t&, atomic_t::value_type);
extern atomic_t::value_type compare_swap(atomic_t&, atomic_t::value_type, atomic_t::value_type);
} // namespace boost
#endif // BOOST_ATOMIC_HPP

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2001-2003 // Copyright (C) 2001
// William E. Kempf // William E. Kempf
// //
// Permission to use, copy, modify, distribute and sell this software // Permission to use, copy, modify, distribute and sell this software
@@ -6,93 +6,43 @@
// 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
#define BOOST_CONDITION_WEK070601_HPP #define BOOST_CONDITION_WEK070601_HPP
#include <boost/config.hpp> #include <boost/config.hpp>
#ifndef BOOST_HAS_THREADS
// insist on threading support being available: # error Thread support is unavailable!
#include <boost/config/requires_threads.hpp> #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>
#include <boost/thread/detail/config.hpp>
#if defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_PTHREADS)
# include <pthread.h> # include <pthread.h>
#elif defined(BOOST_HAS_MPTASKS)
# include "scoped_critical_region.hpp"
#endif #endif
namespace boost { namespace boost {
struct xtime; struct xtime;
namespace detail {
class BOOST_THREAD_DECL condition_impl : private noncopyable
{
friend class condition;
public:
condition_impl();
~condition_impl();
void notify_one();
void notify_all();
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
void enter_wait();
void do_wait();
bool do_timed_wait(const xtime& xt);
#elif defined(BOOST_HAS_PTHREADS)
void do_wait(pthread_mutex_t* pmutex);
bool do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex);
#endif
#if defined(BOOST_HAS_WINTHREADS)
void* m_gate;
void* m_queue;
void* m_mutex;
unsigned m_gone; // # threads that timed out and never made it to m_queue
unsigned long m_blocked; // # threads blocked on the condition
unsigned m_waiting; // # threads no longer waiting for the condition but
// still waiting to be removed from m_queue
#elif defined(BOOST_HAS_PTHREADS)
pthread_cond_t m_condition;
#elif defined(BOOST_HAS_MPTASKS)
MPSemaphoreID m_gate;
MPSemaphoreID m_queue;
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
unsigned m_gone; // # threads that timed out and never made it to m_queue
unsigned long m_blocked; // # threads blocked on the condition
unsigned m_waiting; // # threads no longer waiting for the condition but
// still waiting to be removed from m_queue
#endif
};
} // namespace detail
class condition : private noncopyable class condition : private noncopyable
{ {
public: public:
condition() { } condition();
~condition() { } ~condition();
void notify_one() { m_impl.notify_one(); } void notify_one();
void notify_all() { m_impl.notify_all(); } void notify_all();
template <typename L> template <typename L>
void wait(L& lock) void wait(L& lock)
{ {
if (!lock) if (!lock)
throw lock_error(); throw lock_error();
do_wait(lock.m_mutex); do_wait(lock.m_mutex);
} }
@@ -101,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);
} }
@@ -111,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);
} }
@@ -120,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))
@@ -131,63 +81,68 @@ public:
} }
private: private:
detail::condition_impl m_impl;
template <typename M> template <typename M>
void do_wait(M& mutex) void do_wait(M& mutex)
{ {
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS)) #if defined(BOOST_HAS_WINTHREADS)
m_impl.enter_wait(); enter_wait();
#endif #endif
typedef detail::thread::lock_ops<M> typename M::cv_state state;
#if defined(__HP_aCC) && __HP_aCC <= 33900 && !defined(BOOST_STRICT_CONFIG) mutex.do_unlock(state);
# define lock_ops lock_ops_ // HP confuses lock_ops witht the template
#endif
lock_ops;
typename lock_ops::lock_state state;
lock_ops::unlock(mutex, state);
#if defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_PTHREADS)
m_impl.do_wait(state.pmutex); do_wait(state.pmutex);
#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS)) #elif defined(BOOST_HAS_WINTHREADS)
m_impl.do_wait(); do_wait();
#endif #endif
lock_ops::lock(mutex, state); mutex.do_lock(state);
#undef lock_ops
} }
template <typename M> template <typename M>
bool do_timed_wait(M& mutex, const xtime& xt) bool do_timed_wait(M& mutex, const xtime& xt)
{ {
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS)) #if defined(BOOST_HAS_WINTHREADS)
m_impl.enter_wait(); enter_wait();
#endif #endif
typedef detail::thread::lock_ops<M> typename M::cv_state state;
#if defined(__HP_aCC) && __HP_aCC <= 33900 && !defined(BOOST_STRICT_CONFIG) mutex.do_unlock(state);
# define lock_ops lock_ops_ // HP confuses lock_ops witht the template
#endif
lock_ops;
typename lock_ops::lock_state state;
lock_ops::unlock(mutex, state);
bool ret = false; bool ret = false;
#if defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_PTHREADS)
ret = m_impl.do_timed_wait(xt, state.pmutex); ret = do_timed_wait(xt, state.pmutex);
#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS)) #elif defined(BOOST_HAS_WINTHREADS)
ret = m_impl.do_timed_wait(xt); ret = do_timed_wait(xt);
#endif #endif
lock_ops::lock(mutex, state); mutex.do_lock(state);
#undef lock_ops
return ret; return ret;
} }
#if defined(BOOST_HAS_WINTHREADS)
void enter_wait();
void do_wait();
bool do_timed_wait(const xtime& xt);
#elif defined(BOOST_HAS_PTHREADS)
void do_wait(pthread_mutex_t* pmutex);
bool do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex);
#endif
#if defined(BOOST_HAS_WINTHREADS)
unsigned long m_gate;
unsigned long m_queue;
unsigned long m_mutex;
unsigned m_gone; // # threads that timed out and never made it to the m_queue
unsigned long m_blocked; // # threads m_blocked m_waiting for the condition
unsigned m_waiting; // # threads m_waiting no longer m_waiting for the condition but still
// m_waiting to be removed from the m_queue
#elif defined(BOOST_HAS_PTHREADS)
pthread_cond_t m_condition;
#endif
}; };
} // namespace boost } // namespace boost
@@ -195,8 +150,7 @@ private:
// Change Log: // Change Log:
// 8 Feb 01 WEKEMPF Initial version. // 8 Feb 01 WEKEMPF Initial version.
// 22 May 01 WEKEMPF Modified to use xtime for time outs. // 22 May 01 WEKEMPF Modified to use xtime for time outs.
// 23 May 01 WEKEMPF Removed "duration" timed_waits, as they are too // 23 May 01 WEKEMPF Removed "duration" timed_waits, as they are too difficult
// difficult to use with spurious wakeups. // to use with spurious wakeups.
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
#endif // BOOST_CONDITION_WEK070601_HPP #endif // BOOST_CONDITION_WEK070601_HPP

View File

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

View File

@@ -1,44 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#ifndef BOOST_THREAD_CONFIG_WEK01032003_HPP
#define BOOST_THREAD_CONFIG_WEK01032003_HPP
#if defined(BOOST_HAS_WINTHREADS)
# if defined(BOOST_THREAD_BUILD_DLL)
# define BOOST_THREAD_DECL __declspec(dllexport)
# else
# define BOOST_THREAD_DECL __declspec(dllimport)
# endif
#else
# define BOOST_THREAD_DECL
#endif // BOOST_THREAD_SHARED_LIB
//
// Automatically link to the correct build variant where possible.
//
#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_THREAD_NO_LIB) && !defined(BOOST_THREAD_BUILD_DLL)
//
// Set the name of our library, this will get undef'ed by auto_link.hpp
// once it's done with it:
//
#define BOOST_LIB_NAME boost_thread
//
// If we're importing code from a dll, then tell auto_link.hpp about it:
//
# define BOOST_DYN_LINK
//
// And include the header that does the work:
//
#include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
#endif // BOOST_THREAD_CONFIG_WEK1032003_HPP

View File

@@ -1,44 +0,0 @@
// Copyright (C) 2001
// Mac Murrett
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_FORCE_CAST_MJM012402_HPP
#define BOOST_FORCE_CAST_MJM012402_HPP
namespace boost {
namespace detail {
namespace thread {
// force_cast will convert anything to anything.
// general case
template<class Return_Type, class Argument_Type>
inline Return_Type &force_cast(Argument_Type &rSrc)
{ return(*reinterpret_cast<Return_Type *>(&rSrc)); }
// specialization for const
template<class Return_Type, class Argument_Type>
inline const Return_Type &force_cast(const Argument_Type &rSrc)
{ return(*reinterpret_cast<const Return_Type *>(&rSrc)); }
} // namespace thread
} // namespace detail
} // namespace boost
#endif // BOOST_FORCE_CAST_MJM012402_HPP

View File

@@ -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
@@ -20,182 +20,147 @@ namespace boost {
class condition; class condition;
struct xtime; struct xtime;
namespace detail { namespace thread { namespace detail { namespace thread {
template <typename Mutex> template <typename Mutex>
class lock_ops : private noncopyable class scoped_lock : private noncopyable
{ {
private: public:
lock_ops() { } typedef Mutex mutex_type;
explicit scoped_lock(Mutex& mx, bool initially_locked=true)
: m_mutex(mx), m_locked(false)
{
if (initially_locked) lock();
}
~scoped_lock()
{
if (m_locked) unlock();
}
void lock()
{
if (m_locked) throw lock_error();
m_mutex.do_lock();
m_locked = true;
}
void unlock()
{
if (!m_locked) throw lock_error();
m_mutex.do_unlock();
m_locked = false;
}
public: bool locked() const { return m_locked; }
typedef typename Mutex::cv_state lock_state; operator const void*() const { return m_locked ? this : 0; }
private:
friend class boost::condition;
Mutex& m_mutex;
bool m_locked;
};
static void lock(Mutex& m) template <typename TryMutex>
class scoped_try_lock : private noncopyable
{ {
m.do_lock(); public:
} typedef TryMutex mutex_type;
static bool trylock(Mutex& m)
{ explicit scoped_try_lock(TryMutex& mx)
return m.do_trylock(); : m_mutex(mx), m_locked(false)
} {
static bool timedlock(Mutex& m, const xtime& xt) try_lock();
{ }
return m.do_timedlock(xt); scoped_try_lock(TryMutex& mx, bool initially_locked)
} : m_mutex(mx), m_locked(false)
static void unlock(Mutex& m) {
{ if (initially_locked) lock();
m.do_unlock(); }
} ~scoped_try_lock()
static void lock(Mutex& m, lock_state& state) {
{ if (m_locked) unlock();
m.do_lock(state); }
}
static void unlock(Mutex& m, lock_state& state) void lock()
{ {
m.do_unlock(state); if (m_locked) throw lock_error();
} m_mutex.do_lock();
}; m_locked = true;
}
bool try_lock()
{
if (m_locked) throw lock_error();
return (m_locked = m_mutex.do_trylock());
}
void unlock()
{
if (!m_locked) throw lock_error();
m_mutex.do_unlock();
m_locked = false;
}
bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; }
private:
friend class boost::condition;
TryMutex& m_mutex;
bool m_locked;
};
template <typename Mutex> template <typename TimedMutex>
class scoped_lock : private noncopyable class scoped_timed_lock : private noncopyable
{
public:
typedef Mutex mutex_type;
explicit scoped_lock(Mutex& mx, bool initially_locked=true)
: m_mutex(mx), m_locked(false)
{ {
if (initially_locked) lock(); public:
} typedef TimedMutex mutex_type;
~scoped_lock()
{ scoped_timed_lock(TimedMutex& mx, const xtime& xt)
if (m_locked) unlock(); : m_mutex(mx), m_locked(false)
} {
timed_lock(xt);
}
scoped_timed_lock(TimedMutex& mx, bool initially_locked)
: m_mutex(mx), m_locked(false)
{
if (initially_locked) lock();
}
~scoped_timed_lock()
{
if (m_locked) unlock();
}
void lock()
{
if (m_locked) throw lock_error();
m_mutex.do_lock();
m_locked = true;
}
bool timed_lock(const xtime& xt)
{
if (m_locked) throw lock_error();
return (m_locked = m_mutex.do_timedlock(xt));
}
void unlock()
{
if (!m_locked) throw lock_error();
m_mutex.do_unlock();
m_locked = false;
}
bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; }
private:
friend class boost::condition;
TimedMutex& m_mutex;
bool m_locked;
};
void lock() } // namespace thread
{ } // namespace detail
if (m_locked) throw lock_error();
lock_ops<Mutex>::lock(m_mutex);
m_locked = true;
}
void unlock()
{
if (!m_locked) throw lock_error();
lock_ops<Mutex>::unlock(m_mutex);
m_locked = false;
}
bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; }
private:
friend class boost::condition;
Mutex& m_mutex;
bool m_locked;
};
template <typename TryMutex>
class scoped_try_lock : private noncopyable
{
public:
typedef TryMutex mutex_type;
explicit scoped_try_lock(TryMutex& mx)
: m_mutex(mx), m_locked(false)
{
try_lock();
}
scoped_try_lock(TryMutex& mx, bool initially_locked)
: m_mutex(mx), m_locked(false)
{
if (initially_locked) lock();
}
~scoped_try_lock()
{
if (m_locked) unlock();
}
void lock()
{
if (m_locked) throw lock_error();
lock_ops<TryMutex>::lock(m_mutex);
m_locked = true;
}
bool try_lock()
{
if (m_locked) throw lock_error();
return (m_locked = lock_ops<TryMutex>::trylock(m_mutex));
}
void unlock()
{
if (!m_locked) throw lock_error();
lock_ops<TryMutex>::unlock(m_mutex);
m_locked = false;
}
bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; }
private:
friend class boost::condition;
TryMutex& m_mutex;
bool m_locked;
};
template <typename TimedMutex>
class scoped_timed_lock : private noncopyable
{
public:
typedef TimedMutex mutex_type;
scoped_timed_lock(TimedMutex& mx, const xtime& xt)
: m_mutex(mx), m_locked(false)
{
timed_lock(xt);
}
scoped_timed_lock(TimedMutex& mx, bool initially_locked)
: m_mutex(mx), m_locked(false)
{
if (initially_locked) lock();
}
~scoped_timed_lock()
{
if (m_locked) unlock();
}
void lock()
{
if (m_locked) throw lock_error();
lock_ops<TimedMutex>::lock(m_mutex);
m_locked = true;
}
bool timed_lock(const xtime& xt)
{
if (m_locked) throw lock_error();
return (m_locked = lock_ops<TimedMutex>::timedlock(m_mutex, xt));
}
void unlock()
{
if (!m_locked) throw lock_error();
lock_ops<TimedMutex>::unlock(m_mutex);
m_locked = false;
}
bool locked() const { return m_locked; }
operator const void*() const { return m_locked ? this : 0; }
private:
friend class boost::condition;
TimedMutex& m_mutex;
bool m_locked;
};
} // namespace thread
} // namespace detail
} // namespace boost } // namespace boost
// Change Log: // Change Log:

View File

@@ -1,64 +0,0 @@
// Copyright (C) 2001
// Mac Murrett
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_SINGLETON_MJM012402_HPP
#define BOOST_SINGLETON_MJM012402_HPP
namespace boost {
namespace detail {
namespace thread {
// class singleton has the same goal as all singletons: create one instance of a
// class on demand, then dish it out as requested.
template<class T>
class singleton: private T
{
private:
singleton();
~singleton();
public:
static T &instance();
};
template<class T>
inline singleton<T>::singleton()
{ /* no-op */ }
template<class T>
inline singleton<T>::~singleton()
{ /* no-op */ }
template<class T>
/*static*/ T &singleton<T>::instance()
{
// function-local static to force this to work correctly at static
// initialization time.
static singleton<T> s_oT;
return(s_oT);
}
} // namespace thread
} // namespace detail
} // namespace boost
#endif // BOOST_SINGLETON_MJM012402_HPP

View File

@@ -1,24 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#include <boost/config.hpp>
// insist on threading support being available:
#include <boost/config/requires_threads.hpp>
#include <boost/thread/detail/config.hpp>
#ifdef BOOST_HAS_WINTHREADS
#include <boost/thread/detail/config.hpp>
extern "C" BOOST_THREAD_DECL int on_thread_exit(void (__cdecl * func)(void));
#endif // BOOST_HAS_WINTHREADS

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2001-2003 // Copyright (C) 2001
// William E. Kempf // William E. Kempf
// //
// Permission to use, copy, modify, distribute and sell this software // Permission to use, copy, modify, distribute and sell this software
@@ -9,12 +9,16 @@
// 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
#include <boost/config.hpp>
#include <boost/thread/detail/config.hpp>
// pdm: Sorry, but this class is used all over the place & I end up // pdm: Sorry, but this class is used all over the place & I end up
// with recursive headers if I don't separate it // with recursive headers if I don't separate it
// wek: Not sure why recursive headers would cause compilation problems // wek: Not sure why recursive headers would cause compilation problems
@@ -25,21 +29,18 @@
namespace boost { namespace boost {
class BOOST_THREAD_DECL lock_error : public std::logic_error class lock_error : public std::runtime_error
{ {
public: public:
lock_error(); lock_error() : std::runtime_error("thread lock error") { }
}; };
class BOOST_THREAD_DECL 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
// Change log:
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
#endif // BOOST_THREAD_CONFIG_PDM070801_H #endif // BOOST_THREAD_CONFIG_PDM070801_H

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2001-2003 // Copyright (C) 2001
// William E. Kempf // William E. Kempf
// //
// Permission to use, copy, modify, distribute and sell this software // Permission to use, copy, modify, distribute and sell this software
@@ -6,42 +6,40 @@
// 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
#define BOOST_MUTEX_WEK070601_HPP #define BOOST_MUTEX_WEK070601_HPP
#include <boost/config.hpp> #include <boost/config.hpp>
// insist on threading support being available: #ifndef BOOST_HAS_THREADS
#include <boost/config/requires_threads.hpp> # error Thread support is unavailable!
#endif
#include <boost/utility.hpp> #include <boost/utility.hpp>
#include <boost/thread/detail/lock.hpp> #include <boost/thread/detail/lock.hpp>
#include <boost/thread/detail/config.hpp>
#if defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_PTHREADS)
# include <pthread.h> # include <pthread.h>
#endif #endif
#if defined(BOOST_HAS_MPTASKS)
# include "scoped_critical_region.hpp"
#endif
namespace boost { namespace boost {
class condition;
struct xtime; struct xtime;
class BOOST_THREAD_DECL 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;
@@ -50,10 +48,6 @@ private:
{ {
pthread_mutex_t* pmutex; pthread_mutex_t* pmutex;
}; };
#elif defined(BOOST_HAS_MPTASKS)
struct cv_state
{
};
#endif #endif
void do_lock(); void do_lock();
void do_unlock(); void do_unlock();
@@ -61,26 +55,25 @@ 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;
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
#endif #endif
}; };
class BOOST_THREAD_DECL 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;
@@ -89,10 +82,6 @@ private:
{ {
pthread_mutex_t* pmutex; pthread_mutex_t* pmutex;
}; };
#elif defined(BOOST_HAS_MPTASKS)
struct cv_state
{
};
#endif #endif
void do_lock(); void do_lock();
bool do_trylock(); bool do_trylock();
@@ -101,27 +90,27 @@ 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;
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
#endif #endif
}; };
class BOOST_THREAD_DECL 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;
@@ -130,10 +119,6 @@ private:
{ {
pthread_mutex_t* pmutex; pthread_mutex_t* pmutex;
}; };
#elif defined(BOOST_HAS_MPTASKS)
struct cv_state
{
};
#endif #endif
void do_lock(); void do_lock();
bool do_trylock(); bool do_trylock();
@@ -141,16 +126,13 @@ 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;
bool m_locked; bool m_locked;
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
#endif #endif
}; };
@@ -160,6 +142,5 @@ private:
// 8 Feb 01 WEKEMPF Initial version. // 8 Feb 01 WEKEMPF Initial version.
// 22 May 01 WEKEMPF Modified to use xtime for time outs. Factored out // 22 May 01 WEKEMPF Modified to use xtime for time outs. Factored out
// to three classes, mutex, try_mutex and timed_mutex. // to three classes, mutex, try_mutex and timed_mutex.
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
#endif // BOOST_MUTEX_WEK070601_HPP #endif // BOOST_MUTEX_WEK070601_HPP

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2001-2003 // Copyright (C) 2001
// William E. Kempf // William E. Kempf
// //
// Permission to use, copy, modify, distribute and sell this software // Permission to use, copy, modify, distribute and sell this software
@@ -6,17 +6,16 @@
// 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
#define BOOST_ONCE_WEK080101_HPP #define BOOST_ONCE_WEK080101_HPP
#include <boost/config.hpp> #include <boost/config.hpp>
// insist on threading support being available: #ifndef BOOST_HAS_THREADS
#include <boost/config/requires_threads.hpp> # error Thread support is unavailable!
#endif
#include <boost/thread/detail/config.hpp>
#if defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_PTHREADS)
# include <pthread.h> # include <pthread.h>
@@ -27,16 +26,16 @@ 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) || defined(BOOST_HAS_MPTASKS)) #elif defined(BOOST_HAS_WINTHREADS)
typedef long once_flag; typedef bool once_flag;
#define BOOST_ONCE_INIT 0 const once_flag once_init = false;
#endif #endif
void BOOST_THREAD_DECL call_once(void (*func)(), once_flag& flag); void call_once(void (*func)(), once_flag& flag);
} // namespace boost } // namespace boost

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2001-2003 // Copyright (C) 2001
// William E. Kempf // William E. Kempf
// //
// Permission to use, copy, modify, distribute and sell this software // Permission to use, copy, modify, distribute and sell this software
@@ -6,42 +6,42 @@
// 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
#define BOOST_RECURSIVE_MUTEX_WEK070601_HPP #define BOOST_RECURSIVE_MUTEX_WEK070601_HPP
#include <boost/config.hpp> #include <boost/config.hpp>
// insist on threading support being available: #ifndef BOOST_HAS_THREADS
#include <boost/config/requires_threads.hpp> # error Thread support is unavailable!
#endif
#include <boost/utility.hpp> #include <boost/utility.hpp>
#include <boost/thread/detail/lock.hpp> #include <boost/thread/detail/lock.hpp>
#include <boost/thread/detail/config.hpp>
#if defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_PTHREADS)
# include <pthread.h> # include <pthread.h>
#elif defined(BOOST_HAS_MPTASKS)
# include "scoped_critical_region.hpp"
#endif #endif
namespace boost { namespace boost {
class condition;
struct xtime; struct xtime;
class BOOST_THREAD_DECL 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) || defined(BOOST_HAS_MPTASKS)) #if defined(BOOST_HAS_WINTHREADS)
typedef std::size_t cv_state; typedef std::size_t cv_state;
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
struct cv_state struct cv_state
@@ -56,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;
@@ -66,27 +66,24 @@ private:
pthread_t m_thread_id; pthread_t m_thread_id;
bool m_valid_id; bool m_valid_id;
# endif # endif
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
std::size_t m_count;
#endif #endif
}; };
class BOOST_THREAD_DECL 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< typedef detail::thread::scoped_try_lock<recursive_try_mutex> 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) || defined(BOOST_HAS_MPTASKS)) #if defined(BOOST_HAS_WINTHREADS)
typedef std::size_t cv_state; typedef std::size_t cv_state;
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
struct cv_state struct cv_state
@@ -100,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;
@@ -112,29 +109,26 @@ private:
pthread_t m_thread_id; pthread_t m_thread_id;
bool m_valid_id; bool m_valid_id;
# endif # endif
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
std::size_t m_count;
#endif #endif
}; };
class BOOST_THREAD_DECL 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< typedef detail::thread::scoped_try_lock<recursive_timed_mutex> 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) || defined(BOOST_HAS_MPTASKS)) #if defined(BOOST_HAS_WINTHREADS)
typedef std::size_t cv_state; typedef std::size_t cv_state;
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
struct cv_state struct cv_state
@@ -149,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;
@@ -159,10 +153,6 @@ private:
pthread_t m_thread_id; pthread_t m_thread_id;
bool m_valid_id; bool m_valid_id;
unsigned m_count; unsigned m_count;
#elif defined(BOOST_HAS_MPTASKS)
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
std::size_t m_count;
#endif #endif
}; };
@@ -173,7 +163,5 @@ private:
// 1 Jun 01 WEKEMPF Modified to use xtime for time outs. Factored out // 1 Jun 01 WEKEMPF Modified to use xtime for time outs. Factored out
// to three classes, mutex, try_mutex and timed_mutex. // to three classes, mutex, try_mutex and timed_mutex.
// 11 Jun 01 WEKEMPF Modified to use PTHREAD_MUTEX_RECURSIVE if available. // 11 Jun 01 WEKEMPF Modified to use PTHREAD_MUTEX_RECURSIVE if available.
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
#endif // BOOST_RECURSIVE_MUTEX_WEK070601_HPP #endif // BOOST_RECURSIVE_MUTEX_WEK070601_HPP

View File

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

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2001-2003 // Copyright (C) 2001
// William E. Kempf // William E. Kempf
// //
// Permission to use, copy, modify, distribute and sell this software // Permission to use, copy, modify, distribute and sell this software
@@ -6,35 +6,33 @@
// 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
#define BOOST_THREAD_WEK070601_HPP #define BOOST_THREAD_WEK070601_HPP
#include <boost/config.hpp> #include <boost/config.hpp>
// insist on threading support being available: #ifndef BOOST_HAS_THREADS
#include <boost/config/requires_threads.hpp> # error Thread support is unavailable!
#endif
#include <boost/utility.hpp> #include <boost/utility.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#include <boost/thread/detail/config.hpp>
#include <list> #include <list>
#include <memory> #include <memory>
#if defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_PTHREADS)
# include <pthread.h> # include <pthread.h>
# include <boost/thread/condition.hpp> # include <boost/thread/condition.hpp>
#elif defined(BOOST_HAS_MPTASKS)
# include <Multiprocessing.h>
#endif #endif
namespace boost { namespace boost {
struct xtime; struct xtime;
class BOOST_THREAD_DECL thread : private noncopyable class thread : private noncopyable
{ {
public: public:
thread(); thread();
@@ -51,19 +49,16 @@ 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:
pthread_t m_thread; pthread_t m_thread;
#elif defined(BOOST_HAS_MPTASKS)
MPQueueID m_pJoinQueueID;
MPTaskID m_pTaskID;
#endif #endif
bool m_joinable; bool m_joinable;
}; };
class BOOST_THREAD_DECL thread_group : private noncopyable class thread_group : private noncopyable
{ {
public: public:
thread_group(); thread_group();

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2001-2003 // Copyright (C) 2001
// William E. Kempf // William E. Kempf
// //
// Permission to use, copy, modify, distribute and sell this software // Permission to use, copy, modify, distribute and sell this software
@@ -6,53 +6,44 @@
// 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
#define BOOST_TSS_WEK070601_HPP #define BOOST_TSS_WEK070601_HPP
#include <boost/config.hpp> #include <boost/config.hpp>
// insist on threading support being available: #ifndef BOOST_HAS_THREADS
#include <boost/config/requires_threads.hpp> # error Thread support is unavailable!
#endif
#include <boost/utility.hpp> #include <boost/utility.hpp>
#include <boost/thread/detail/config.hpp>
#if defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_PTHREADS)
# include <pthread.h> # include <pthread.h>
#elif defined(BOOST_HAS_MPTASKS)
# include <Multiprocessing.h>
#endif #endif
namespace boost { namespace boost {
namespace detail { namespace detail {
class BOOST_THREAD_DECL tss : private noncopyable class tss : private noncopyable
{ {
public: public:
tss(void (*cleanup)(void*)=0); tss(void (*cleanup)(void*)=0);
~tss(); ~tss();
void* get() const; void* get() const;
bool set(void* value); bool set(void* value);
private: private:
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
unsigned long m_key; unsigned long m_key;
void (*m_cleanup)(void*); void (*m_cleanup)(void*);
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
pthread_key_t m_key; pthread_key_t m_key;
#elif defined(BOOST_HAS_MPTASKS) #endif
TaskStorageIndex m_key; };
void (*m_cleanup)(void*); }
#endif
};
#if defined(BOOST_HAS_MPTASKS)
void thread_cleanup();
#endif
}
template <typename T> template <typename T>
class thread_specific_ptr : private noncopyable class thread_specific_ptr : private noncopyable
@@ -64,13 +55,7 @@ public:
T* operator->() const { return get(); } T* operator->() const { return get(); }
T& operator*() const { return *get(); } T& operator*() const { return *get(); }
T* release() { T* temp = get(); m_tss.set(0); return temp; } T* release() { T* temp = get(); m_tss.set(0); return temp; }
void reset(T* p=0) void reset(T* p=0) { T* cur = get(); if (cur == p) return; delete cur; m_tss.set(p); }
{
T* cur = get();
if (cur == p) return;
delete cur;
m_tss.set(p);
}
private: private:
static void cleanup(void* p) { delete static_cast<T*>(p); } static void cleanup(void* p) { delete static_cast<T*>(p); }

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2001-2003 // Copyright (C) 2001
// William E. Kempf // William E. Kempf
// //
// Permission to use, copy, modify, distribute and sell this software // Permission to use, copy, modify, distribute and sell this software
@@ -6,15 +6,14 @@
// 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
#define BOOST_XTIME_WEK070601_HPP #define BOOST_XTIME_WEK070601_HPP
#include <boost/config.hpp>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <boost/thread/detail/config.hpp> #include <boost/config.hpp>
namespace boost { namespace boost {
@@ -40,14 +39,7 @@ struct xtime
int_fast32_t nsec; int_fast32_t nsec;
}; };
int BOOST_THREAD_DECL xtime_get(struct xtime* xtp, int clock_type); int xtime_get(struct xtime* xtp, int clock_type);
inline int xtime_cmp(const xtime& xt1, const xtime& xt2)
{
int res = (int)(xt1.sec - xt2.sec);
if (res == 0)
res = (int)(xt1.nsec - xt2.nsec);
return res;
}
} // namespace boost } // namespace boost

View File

@@ -1,8 +0,0 @@
<html>
<head>
<meta http-equiv="refresh" content="0; URL=doc/index.html">
</head>
<body>
Automatic redirection failed, please go to <a href="doc/index.html">doc/index.html</a>
</body>
</html>

80
src/_atomic.cpp Normal file
View File

@@ -0,0 +1,80 @@
/*
*
* Copyright (C) 2001
* William E. Kempf
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. William E. Kempf makes no representations
* about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* Revision History (excluding minor changes for specific compilers)
* 8 Feb 01 Initial version.
*/
#include <boost/thread/atomic.hpp>
#if defined(BOOST_HAS_WINTHREADS)
# include <windows.h>
#endif
namespace boost {
atomic_t::value_type read(const atomic_t& x)
{
return x._value;
}
#if defined(BOOST_HAS_WINTHREADS)
atomic_t::value_type increment(atomic_t& x)
{
return InterlockedIncrement(const_cast<long*>(&x._value));
}
atomic_t::value_type decrement(atomic_t& x)
{
return InterlockedDecrement(const_cast<long*>(&x._value));
}
atomic_t::value_type swap(atomic_t& x, atomic_t::value_type y)
{
return InterlockedExchange(const_cast<long*>(&x._value), y);
}
atomic_t::value_type compare_swap(atomic_t& x, atomic_t::value_type y, atomic_t::value_type z)
{
return InterlockedCompareExchange(const_cast<long*>(&x._value), y, z);
}
#else
atomic_t::value_type increment(atomic_t& x)
{
mutex::lock lock(x._mutex);
return ++x._value;
}
atomic_t::value_type decrement(atomic_t& x)
{
mutex::lock lock(x._mutex);
return --x._value;
}
atomic_t::value_type swap(atomic_t& x, atomic_t::value_type y)
{
mutex::lock lock(x._mutex);
atomic_t::value_type temp = x._value;
x._value = y;
return temp;
}
atomic_t::value_type compare_swap(atomic_t& x, atomic_t::value_type y, atomic_t::value_type z)
{
mutex::lock lock(x._mutex);
atomic_t::value_type temp = x._value;
if (temp == z)
x._value = y;
return temp;
}
#endif
} // namespace boost

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2001-2003 // Copyright (C) 2001
// William E. Kempf // William E. Kempf
// //
// Permission to use, copy, modify, distribute and sell this software // Permission to use, copy, modify, distribute and sell this software
@@ -6,68 +6,58 @@
// 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>
#include "timeconv.inl" #include "timeconv.inl"
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
# ifndef NOMINMAX # define NOMINMAX
# define NOMINMAX
# endif
# include <windows.h> # include <windows.h>
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
# include <errno.h> # include <errno.h>
#elif defined(BOOST_HAS_MPTASKS)
# include <MacErrors.h>
# include "mac/init.hpp"
# include "mac/safe.hpp"
#endif #endif
namespace boost { namespace boost {
namespace detail {
#if defined(BOOST_HAS_WINTHREADS) #if defined(BOOST_HAS_WINTHREADS)
condition_impl::condition_impl() 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, m_queue = reinterpret_cast<unsigned long>(CreateSemaphore(0, 0, std::numeric_limits<long>::max(), 0));
std::numeric_limits<long>::max(), m_mutex = reinterpret_cast<unsigned long>(CreateMutex(0, 0, 0));
0));
m_mutex = reinterpret_cast<void*>(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();
} }
} }
condition_impl::~condition_impl() condition::~condition()
{ {
int res = 0; int res = 0;
res = CloseHandle(reinterpret_cast<HANDLE>(m_gate)); res = CloseHandle(reinterpret_cast<HANDLE>(m_gate));
@@ -78,7 +68,7 @@ condition_impl::~condition_impl()
assert(res); assert(res);
} }
void condition_impl::notify_one() void condition::notify_one()
{ {
unsigned signals = 0; unsigned signals = 0;
@@ -87,50 +77,49 @@ void condition_impl::notify_one()
assert(res == WAIT_OBJECT_0); assert(res == WAIT_OBJECT_0);
if (m_waiting != 0) // the m_gate is already closed if (m_waiting != 0) // the m_gate is already closed
{
if (m_blocked == 0)
{ {
if (m_blocked == 0) res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
{ assert(res);
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex)); return;
assert(res);
return;
}
++m_waiting;
--m_blocked;
signals = 1;
} }
++m_waiting;
--m_blocked;
}
else else
{
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
assert(res == WAIT_OBJECT_0);
if (m_blocked > m_gone)
{ {
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE); if (m_gone != 0)
assert(res == WAIT_OBJECT_0); {
if (m_blocked > m_gone) m_blocked -= m_gone;
{ m_gone = 0;
if (m_gone != 0) }
{ signals = m_waiting = 1;
m_blocked -= m_gone; --m_blocked;
m_gone = 0; }
} else
signals = m_waiting = 1; {
--m_blocked; res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
} assert(res);
else
{
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
assert(res);
}
} }
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex)); res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res); assert(res);
if (signals) if (signals)
{ {
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0); res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0);
assert(res); assert(res);
} }
}
} }
void condition_impl::notify_all() void condition::notify_all()
{ {
unsigned signals = 0; unsigned signals = 0;
@@ -139,50 +128,49 @@ void condition_impl::notify_all()
assert(res == WAIT_OBJECT_0); assert(res == WAIT_OBJECT_0);
if (m_waiting != 0) // the m_gate is already closed if (m_waiting != 0) // the m_gate is already closed
{
if (m_blocked == 0)
{ {
if (m_blocked == 0) res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
{ assert(res);
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex)); return;
assert(res); }
return;
}
m_waiting += (signals = m_blocked); m_waiting += (signals = m_blocked);
m_blocked = 0;
}
else
{
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
assert(res == WAIT_OBJECT_0);
if (m_blocked > m_gone)
{
if (m_gone != 0)
{
m_blocked -= m_gone;
m_gone = 0;
}
signals = m_waiting = m_blocked;
m_blocked = 0; m_blocked = 0;
} }
else else
{ {
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE); res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
assert(res == WAIT_OBJECT_0);
if (m_blocked > m_gone)
{
if (m_gone != 0)
{
m_blocked -= m_gone;
m_gone = 0;
}
signals = m_waiting = m_blocked;
m_blocked = 0;
}
else
{
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
assert(res);
}
}
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
if (signals)
{
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals,
0);
assert(res); assert(res);
} }
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res);
if (signals)
{
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_queue), signals, 0);
assert(res);
}
}
} }
void condition_impl::enter_wait() void condition::enter_wait()
{ {
int res = 0; int res = 0;
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE); res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
@@ -192,12 +180,12 @@ void condition_impl::enter_wait()
assert(res); assert(res);
} }
void condition_impl::do_wait() 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;
@@ -206,75 +194,58 @@ void condition_impl::do_wait()
was_waiting = m_waiting; was_waiting = m_waiting;
was_gone = m_gone; was_gone = m_gone;
if (was_waiting != 0) if (was_waiting != 0)
{
if (--m_waiting == 0)
{ {
if (--m_waiting == 0) if (m_blocked != 0)
{ {
if (m_blocked != 0) res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0); // open m_gate
{ assert(res);
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, was_waiting = 0;
0); // open m_gate }
assert(res); else if (m_gone != 0)
was_waiting = 0; m_gone = 0;
}
else if (m_gone != 0)
m_gone = 0;
}
} }
}
else if (++m_gone == (std::numeric_limits<unsigned>::max() / 2)) else if (++m_gone == (std::numeric_limits<unsigned>::max() / 2))
{ {
// timeout occured, normalize the m_gone count // timeout occured, normalize the m_gone count
// this may occur if many calls to wait with a timeout are made and // this may occur if many calls to wait with a timeout are made and
// no call to notify_* is made // no call to notify_* is made
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE); res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
assert(res == WAIT_OBJECT_0); assert(res == WAIT_OBJECT_0);
m_blocked -= m_gone; m_blocked -= m_gone;
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0); res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
assert(res); assert(res);
m_gone = 0; m_gone = 0;
} }
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex)); res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res); assert(res);
if (was_waiting == 1) if (was_waiting == 1)
{
for (/**/ ; was_gone; --was_gone)
{ {
for (/**/ ; was_gone; --was_gone) // better now than spurious later
{ res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), INFINITE);
// better now than spurious later assert(res == WAIT_OBJECT_0);
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue),
INFINITE);
assert(res == WAIT_OBJECT_0);
}
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
assert(res);
} }
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
assert(res);
}
} }
bool condition_impl::do_timed_wait(const xtime& xt) bool condition::do_timed_wait(const xtime& xt)
{ {
bool ret = false; unsigned milliseconds;
unsigned int res = 0; to_duration(xt, milliseconds);
for (;;) int res = 0;
{ res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), milliseconds);
int milliseconds; assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
to_duration(xt, milliseconds);
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue),
milliseconds);
assert(res != WAIT_FAILED && res != WAIT_ABANDONED);
ret = (res == WAIT_OBJECT_0);
if (res == WAIT_TIMEOUT)
{
xtime cur;
xtime_get(&cur, TIME_UTC);
if (xtime_cmp(xt, cur) > 0)
continue;
}
break;
}
bool ret = (res == WAIT_OBJECT_0);
unsigned was_waiting=0; unsigned was_waiting=0;
unsigned was_gone=0; unsigned was_gone=0;
@@ -283,59 +254,57 @@ bool condition_impl::do_timed_wait(const xtime& xt)
was_waiting = m_waiting; was_waiting = m_waiting;
was_gone = m_gone; was_gone = m_gone;
if (was_waiting != 0) if (was_waiting != 0)
{
if (!ret) // timeout
{ {
if (!ret) // timeout if (m_blocked != 0)
{ --m_blocked;
if (m_blocked != 0) else
--m_blocked; ++m_gone; // count spurious wakeups
else
++m_gone; // count spurious wakeups
}
if (--m_waiting == 0)
{
if (m_blocked != 0)
{
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1,
0); // open m_gate
assert(res);
was_waiting = 0;
}
else if (m_gone != 0)
m_gone = 0;
}
} }
if (--m_waiting == 0)
{
if (m_blocked != 0)
{
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0); // open m_gate
assert(res);
was_waiting = 0;
}
else if (m_gone != 0)
m_gone = 0;
}
}
else if (++m_gone == (std::numeric_limits<unsigned>::max() / 2)) else if (++m_gone == (std::numeric_limits<unsigned>::max() / 2))
{ {
// timeout occured, normalize the m_gone count // timeout occured, normalize the m_gone count
// this may occur if many calls to wait with a timeout are made and // this may occur if many calls to wait with a timeout are made and
// no call to notify_* is made // no call to notify_* is made
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE); res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_gate), INFINITE);
assert(res == WAIT_OBJECT_0); assert(res == WAIT_OBJECT_0);
m_blocked -= m_gone; m_blocked -= m_gone;
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0); res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
assert(res); assert(res);
m_gone = 0; m_gone = 0;
} }
res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex)); res = ReleaseMutex(reinterpret_cast<HANDLE>(m_mutex));
assert(res); assert(res);
if (was_waiting == 1) if (was_waiting == 1)
{
for (/**/ ; was_gone; --was_gone)
{ {
for (/**/ ; was_gone; --was_gone) // better now than spurious later
{ res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue), INFINITE);
// better now than spurious later assert(res == WAIT_OBJECT_0);
res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_queue),
INFINITE);
assert(res == WAIT_OBJECT_0);
}
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
assert(res);
} }
res = ReleaseSemaphore(reinterpret_cast<HANDLE>(m_gate), 1, 0);
assert(res);
}
return ret; return ret;
} }
#elif defined(BOOST_HAS_PTHREADS) #elif defined(BOOST_HAS_PTHREADS)
condition_impl::condition_impl() condition::condition()
{ {
int res = 0; int res = 0;
res = pthread_cond_init(&m_condition, 0); res = pthread_cond_init(&m_condition, 0);
@@ -343,35 +312,35 @@ condition_impl::condition_impl()
throw thread_resource_error(); throw thread_resource_error();
} }
condition_impl::~condition_impl() condition::~condition()
{ {
int res = 0; int res = 0;
res = pthread_cond_destroy(&m_condition); res = pthread_cond_destroy(&m_condition);
assert(res == 0); assert(res == 0);
} }
void condition_impl::notify_one() void condition::notify_one()
{ {
int res = 0; int res = 0;
res = pthread_cond_signal(&m_condition); res = pthread_cond_signal(&m_condition);
assert(res == 0); assert(res == 0);
} }
void condition_impl::notify_all() void condition::notify_all()
{ {
int res = 0; int res = 0;
res = pthread_cond_broadcast(&m_condition); res = pthread_cond_broadcast(&m_condition);
assert(res == 0); assert(res == 0);
} }
void condition_impl::do_wait(pthread_mutex_t* pmutex) void condition::do_wait(pthread_mutex_t* pmutex)
{ {
int res = 0; int res = 0;
res = pthread_cond_wait(&m_condition, pmutex); res = pthread_cond_wait(&m_condition, pmutex);
assert(res == 0); assert(res == 0);
} }
bool condition_impl::do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex) bool condition::do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex)
{ {
timespec ts; timespec ts;
to_timespec(xt, ts); to_timespec(xt, ts);
@@ -382,296 +351,10 @@ bool condition_impl::do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex)
return res != ETIMEDOUT; return res != ETIMEDOUT;
} }
#elif defined(BOOST_HAS_MPTASKS)
using threads::mac::detail::safe_enter_critical_region;
using threads::mac::detail::safe_wait_on_semaphore;
condition_impl::condition_impl()
: m_gone(0), m_blocked(0), m_waiting(0)
{
threads::mac::detail::thread_init();
OSStatus lStatus = noErr;
lStatus = MPCreateSemaphore(1, 1, &m_gate);
if(lStatus == noErr)
lStatus = MPCreateSemaphore(ULONG_MAX, 0, &m_queue);
if(lStatus != noErr || !m_gate || !m_queue)
{
if (m_gate)
{
lStatus = MPDeleteSemaphore(m_gate);
assert(lStatus == noErr);
}
if (m_queue)
{
lStatus = MPDeleteSemaphore(m_queue);
assert(lStatus == noErr);
}
throw thread_resource_error();
}
}
condition_impl::~condition_impl()
{
OSStatus lStatus = noErr;
lStatus = MPDeleteSemaphore(m_gate);
assert(lStatus == noErr);
lStatus = MPDeleteSemaphore(m_queue);
assert(lStatus == noErr);
}
void condition_impl::notify_one()
{
unsigned signals = 0;
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
m_mutex_mutex);
assert(lStatus == noErr);
if (m_waiting != 0) // the m_gate is already closed
{
if (m_blocked == 0)
{
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
return;
}
++m_waiting;
--m_blocked;
}
else
{
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
assert(lStatus == noErr);
if (m_blocked > m_gone)
{
if (m_gone != 0)
{
m_blocked -= m_gone;
m_gone = 0;
}
signals = m_waiting = 1;
--m_blocked;
}
else
{
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
}
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
while (signals)
{
lStatus = MPSignalSemaphore(m_queue);
assert(lStatus == noErr);
--signals;
}
}
}
void condition_impl::notify_all()
{
unsigned signals = 0;
OSStatus lStatus = noErr;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
m_mutex_mutex);
assert(lStatus == noErr);
if (m_waiting != 0) // the m_gate is already closed
{
if (m_blocked == 0)
{
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
return;
}
m_waiting += (signals = m_blocked);
m_blocked = 0;
}
else
{
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
assert(lStatus == noErr);
if (m_blocked > m_gone)
{
if (m_gone != 0)
{
m_blocked -= m_gone;
m_gone = 0;
}
signals = m_waiting = m_blocked;
m_blocked = 0;
}
else
{
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
}
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
while (signals)
{
lStatus = MPSignalSemaphore(m_queue);
assert(lStatus == noErr);
--signals;
}
}
}
void condition_impl::enter_wait()
{
OSStatus lStatus = noErr;
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
assert(lStatus == noErr);
++m_blocked;
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
}
void condition_impl::do_wait()
{
OSStatus lStatus = noErr;
lStatus = safe_wait_on_semaphore(m_queue, kDurationForever);
assert(lStatus == noErr);
unsigned was_waiting=0;
unsigned was_gone=0;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
m_mutex_mutex);
assert(lStatus == noErr);
was_waiting = m_waiting;
was_gone = m_gone;
if (was_waiting != 0)
{
if (--m_waiting == 0)
{
if (m_blocked != 0)
{
lStatus = MPSignalSemaphore(m_gate); // open m_gate
assert(lStatus == noErr);
was_waiting = 0;
}
else if (m_gone != 0)
m_gone = 0;
}
}
else if (++m_gone == (std::numeric_limits<unsigned>::max() / 2))
{
// timeout occured, normalize the m_gone count
// this may occur if many calls to wait with a timeout are made and
// no call to notify_* is made
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
assert(lStatus == noErr);
m_blocked -= m_gone;
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
m_gone = 0;
}
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
if (was_waiting == 1)
{
for (/**/ ; was_gone; --was_gone)
{
// better now than spurious later
lStatus = safe_wait_on_semaphore(m_queue, kDurationForever);
assert(lStatus == noErr);
}
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
}
}
bool condition_impl::do_timed_wait(const xtime& xt)
{
int milliseconds;
to_duration(xt, milliseconds);
OSStatus lStatus = noErr;
lStatus = safe_wait_on_semaphore(m_queue, milliseconds);
assert(lStatus == noErr || lStatus == kMPTimeoutErr);
bool ret = (lStatus == noErr);
unsigned was_waiting=0;
unsigned was_gone=0;
lStatus = safe_enter_critical_region(m_mutex, kDurationForever,
m_mutex_mutex);
assert(lStatus == noErr);
was_waiting = m_waiting;
was_gone = m_gone;
if (was_waiting != 0)
{
if (!ret) // timeout
{
if (m_blocked != 0)
--m_blocked;
else
++m_gone; // count spurious wakeups
}
if (--m_waiting == 0)
{
if (m_blocked != 0)
{
lStatus = MPSignalSemaphore(m_gate); // open m_gate
assert(lStatus == noErr);
was_waiting = 0;
}
else if (m_gone != 0)
m_gone = 0;
}
}
else if (++m_gone == (std::numeric_limits<unsigned>::max() / 2))
{
// timeout occured, normalize the m_gone count
// this may occur if many calls to wait with a timeout are made and
// no call to notify_* is made
lStatus = safe_wait_on_semaphore(m_gate, kDurationForever);
assert(lStatus == noErr);
m_blocked -= m_gone;
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
m_gone = 0;
}
lStatus = MPExitCriticalRegion(m_mutex);
assert(lStatus == noErr);
if (was_waiting == 1)
{
for (/**/ ; was_gone; --was_gone)
{
// better now than spurious later
lStatus = safe_wait_on_semaphore(m_queue, kDurationForever);
assert(lStatus == noErr);
}
lStatus = MPSignalSemaphore(m_gate);
assert(lStatus == noErr);
}
return ret;
}
#endif #endif
} // namespace detail
} // namespace boost } // namespace boost
// Change Log: // Change Log:
// 8 Feb 01 WEKEMPF Initial version. // 8 Feb 01 WEKEMPF Initial version.
// 22 May 01 WEKEMPF Modified to use xtime for time outs. // 22 May 01 WEKEMPF Modified to use xtime for time outs.
// 3 Jan 03 WEKEMPF Modified for DLL implementation.

View File

@@ -1,27 +0,0 @@
// Copyright (C) 2001-2003
// William E. Kempf
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. William E. Kempf makes no representations
// about the suitability of this software for any purpose.
// It is provided "as is" without express or implied warranty.
#include <boost/thread/exceptions.hpp>
#include <string>
namespace boost {
lock_error::lock_error()
: std::logic_error("thread lock error")
{
}
thread_resource_error::thread_resource_error()
: std::runtime_error("thread resource error")
{
}
} // namespace boost

View File

@@ -1,14 +0,0 @@
// Copyright (C) 2001
// Mac Murrett
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#define TARGET_CARBON 1

View File

@@ -1,72 +0,0 @@
// Copyright (C) 2001
// Mac Murrett
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#include "delivery_man.hpp"
#include "os.hpp"
#include "execution_context.hpp"
namespace boost {
namespace threads {
namespace mac {
namespace detail {
delivery_man::delivery_man():
m_pPackage(NULL),
m_pSemaphore(kInvalidID),
m_bPackageWaiting(false)
{
assert(at_st());
OSStatus lStatus = MPCreateSemaphore(1UL, 0UL, &m_pSemaphore);
// TODO - throw on error here
assert(lStatus == noErr);
}
delivery_man::~delivery_man()
{
assert(m_bPackageWaiting == false);
OSStatus lStatus = MPDeleteSemaphore(m_pSemaphore);
assert(lStatus == noErr);
}
void delivery_man::accept_deliveries()
{
if(m_bPackageWaiting)
{
assert(m_pPackage != NULL);
m_pPackage->accept();
m_pPackage = NULL;
m_bPackageWaiting = false;
// signal to the thread making the call that we're done
OSStatus lStatus = MPSignalSemaphore(m_pSemaphore);
assert(lStatus == noErr);
}
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost

View File

@@ -1,90 +0,0 @@
// Copyright (C) 2001
// Mac Murrett
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_DELIVERY_MAN_MJM012402_HPP
#define BOOST_DELIVERY_MAN_MJM012402_HPP
#include <boost/function.hpp>
#include <boost/utility.hpp>
#include <boost/thread/mutex.hpp>
#include "package.hpp"
#include <Multiprocessing.h>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
// class delivery_man is intended to move boost::function objects from MP tasks to
// other execution contexts (such as deferred task time or system task time).
class delivery_man: private noncopyable
{
public:
delivery_man();
~delivery_man();
public:
template<class R>
R deliver(function<R> &rFunctor);
void accept_deliveries();
private:
base_package *m_pPackage;
mutex m_oMutex;
MPSemaphoreID m_pSemaphore;
bool m_bPackageWaiting;
};
template<class R>
R delivery_man::deliver(function<R> &rFunctor)
{
assert(at_mp());
// lock our mutex
mutex::scoped_lock oLock(m_oMutex);
// create a package and save it
package<R> oPackage(rFunctor);
m_pPackage = &oPackage;
m_bPackageWaiting = true;
// wait on the semaphore
OSStatus lStatus = MPWaitOnSemaphore(m_pSemaphore, kDurationForever);
assert(lStatus == noErr);
return(oPackage.return_value());
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_DELIVERY_MAN_MJM012402_HPP

View File

@@ -1,99 +0,0 @@
// Copyright (C) 2001
// Mac Murrett
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#include "dt_scheduler.hpp"
#include "ot_context.hpp"
#include <boost/thread/detail/singleton.hpp>
#include <OpenTransportProtocol.h>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
const OTTimeout k_ulTimerTaskDelay = 1UL;
dt_scheduler::dt_scheduler():
m_bReschedule(false),
m_uppTask(NULL),
m_lTask(0UL)
{
using ::boost::detail::thread::singleton;
ot_context &rContext(singleton<ot_context>::instance());
m_uppTask = NewOTProcessUPP(task_entry);
m_lTask = OTCreateTimerTaskInContext(m_uppTask, this, rContext.get_context());
}
dt_scheduler::~dt_scheduler()
{
OTDestroyTimerTask(m_lTask);
m_lTask = 0UL;
DisposeOTProcessUPP(m_uppTask);
m_uppTask = NULL;
}
void dt_scheduler::start_polling()
{
m_bReschedule = true;
schedule_task();
}
void dt_scheduler::stop_polling()
{
m_bReschedule = false;
}
void dt_scheduler::schedule_task()
{
if(m_bReschedule)
{
OTScheduleTimerTask(m_lTask, k_ulTimerTaskDelay);
}
}
/*static*/ pascal void dt_scheduler::task_entry(void *pRefCon)
{
dt_scheduler *pThis = reinterpret_cast<dt_scheduler *>(pRefCon);
assert(pThis != NULL);
pThis->task();
}
void dt_scheduler::task()
{
periodic_function();
schedule_task();
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost

View File

@@ -1,69 +0,0 @@
// Copyright (C) 2001
// Mac Murrett
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_DT_SCHEDULER_MJM012402_HPP
#define BOOST_DT_SCHEDULER_MJM012402_HPP
#include "periodical.hpp"
#include <OpenTransport.h>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
// class dt_scheduler calls its pure-virtual periodic_function method periodically at
// deferred task time. This is generally 1kHz under Mac OS 9.
class dt_scheduler
{
public:
dt_scheduler();
virtual ~dt_scheduler();
protected:
void start_polling();
void stop_polling();
private:
virtual void periodic_function() = 0;
private:
void schedule_task();
static pascal void task_entry(void *pRefCon);
void task();
private:
bool m_bReschedule;
OTProcessUPP m_uppTask;
long m_lTask;
};
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_DT_SCHEDULER_MJM012402_HPP

View File

@@ -1,66 +0,0 @@
// Copyright (C) 2001
// Mac Murrett
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#include <Debugging.h>
#include <Multiprocessing.h>
#include "execution_context.hpp"
#include "init.hpp"
namespace boost {
namespace threads {
namespace mac {
execution_context_t execution_context()
{
// make sure that MP services are available the first time through
static bool bIgnored = detail::thread_init();
// first check if we're an MP task
if(MPTaskIsPreemptive(kInvalidID))
{
return(k_eExecutionContextMPTask);
}
#if TARGET_CARBON
// Carbon has TaskLevel
UInt32 ulLevel = TaskLevel();
if(ulLevel == 0UL)
{
return(k_eExecutionContextSystemTask);
}
if(ulLevel & kInDeferredTaskMask)
{
return(k_eExecutionContextDeferredTask);
}
return(k_eExecutionContextOther);
#else
// this can be implemented using TaskLevel if you don't mind linking against
// DebugLib (and therefore breaking Mac OS 8.6 support), or CurrentExecutionLevel.
# error execution_context unimplimented
#endif
}
} // namespace mac
} // namespace threads
} // namespace boost

View File

@@ -1,53 +0,0 @@
// Copyright (C) 2001
// Mac Murrett
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_EXECUTION_CONTEXT_MJM012402_HPP
#define BOOST_EXECUTION_CONTEXT_MJM012402_HPP
namespace boost {
namespace threads {
namespace mac {
// utility functions for figuring out what context your code is executing in.
// Bear in mind that at_mp and in_blue are the only functions guarenteed by
// Apple to work. There is simply no way of being sure that you will not get
// false readings about task level at interrupt time in blue.
typedef enum {
k_eExecutionContextSystemTask,
k_eExecutionContextDeferredTask,
k_eExecutionContextMPTask,
k_eExecutionContextOther
} execution_context_t;
execution_context_t execution_context();
inline bool at_st()
{ return(execution_context() == k_eExecutionContextSystemTask); }
inline bool at_mp()
{ return(execution_context() == k_eExecutionContextMPTask); }
inline bool in_blue()
{ return(!at_mp()); }
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_EXECUTION_CONTEXT_MJM012402_HPP

View File

@@ -1,64 +0,0 @@
// Copyright (C) 2001
// Mac Murrett
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#include "init.hpp"
#include "remote_call_manager.hpp"
#include <boost/thread/detail/singleton.hpp>
#include <Multiprocessing.h>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
namespace {
// force these to get called by the end of static initialization time.
static bool g_bInitialized = (thread_init() && create_singletons());
}
bool thread_init()
{
static bool bResult = MPLibraryIsLoaded();
return(bResult);
}
bool create_singletons()
{
using ::boost::detail::thread::singleton;
singleton<remote_call_manager>::instance();
return(true);
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost

View File

@@ -1,40 +0,0 @@
// Copyright (C) 2001
// Mac Murrett
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_INIT_MJM012402_HPP
#define BOOST_INIT_MJM012402_HPP
namespace boost {
namespace threads {
namespace mac {
namespace detail {
bool thread_init();
bool create_singletons();
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_INIT_MJM012402_HPP

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,63 +0,0 @@
// Copyright (C) 2001
// Mac Murrett
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#include "os.hpp"
#include <cassert>
#include <Gestalt.h>
namespace boost {
namespace threads {
namespace mac {
namespace os {
// read the OS version from Gestalt
static inline long get_version()
{
long lVersion;
OSErr nErr = Gestalt(gestaltSystemVersion, &lVersion);
assert(nErr == noErr);
return(lVersion);
}
// check if we're running under Mac OS X and cache that information
bool x()
{
static bool bX = (version() >= 0x1000);
return(bX);
}
// read the OS version and cache it
long version()
{
static long lVersion = get_version();
return(lVersion);
}
} // namespace os
} // namespace mac
} // namespace threads
} // namespace boost

View File

@@ -1,43 +0,0 @@
// Copyright (C) 2001
// Mac Murrett
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_OS_MJM012402_HPP
#define BOOST_OS_MJM012402_HPP
namespace boost {
namespace threads {
namespace mac {
namespace os {
// functions to determine the OS environment. With namespaces, you get a cute call:
// mac::os::x
bool x();
long version();
} // namespace os
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_OS_MJM012402_HPP

View File

@@ -1,52 +0,0 @@
// Copyright (C) 2001
// Mac Murrett
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#include "ot_context.hpp"
#include "execution_context.hpp"
#include <cassert>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
ot_context::ot_context()
{
assert(at_st());
OSStatus lStatus = InitOpenTransportInContext(0UL, &m_pContext);
// TODO - throw on error
assert(lStatus == noErr);
}
ot_context::~ot_context()
{
CloseOpenTransportInContext(m_pContext);
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost

View File

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

View File

@@ -1,82 +0,0 @@
// Copyright (C) 2001
// Mac Murrett
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_PACKAGE_MJM012402_HPP
#define BOOST_PACKAGE_MJM012402_HPP
namespace boost {
namespace threads {
namespace mac {
namespace detail {
class base_package: private noncopyable
{
public:
virtual void accept() = 0;
};
template<class R>
class package: public base_package
{
public:
inline package(function<R> &rFunctor):
m_rFunctor(rFunctor)
{ /* no-op */ }
inline ~package()
{ /* no-op */ }
virtual void accept()
{ m_oR = m_rFunctor(); }
inline R return_value()
{ return(m_oR); }
private:
function<R> &m_rFunctor;
R m_oR;
};
template<>
class package<void>: public base_package
{
public:
inline package(function<void> &rFunctor):
m_rFunctor(rFunctor)
{ /* no-op */ }
inline ~package()
{ /* no-op */ }
virtual void accept()
{ m_rFunctor(); }
inline void return_value()
{ return; }
private:
function<void> &m_rFunctor;
};
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost
#endif // BOOST_PACKAGE_MJM012402_HPP

View File

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

View File

@@ -1,15 +0,0 @@
// Copyright (C) 2001
// Mac Murrett
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#define NDEBUG
#define TARGET_CARBON 1

View File

@@ -1,54 +0,0 @@
// Copyright (C) 2001
// Mac Murrett
//
// Permission to use, copy, modify, distribute and sell this software
// and its documentation for any purpose is hereby granted without fee,
// provided that the above copyright notice appear in all copies and
// that both that copyright notice and this permission notice appear
// in supporting documentation. Mac Murrett makes no representations
// about the suitability of this software for any purpose. It is
// provided "as is" without express or implied warranty.
//
// See http://www.boost.org for most recent version including documentation.
#include "remote_call_manager.hpp"
#include <boost/bind.hpp>
namespace boost {
namespace threads {
namespace mac {
namespace detail {
using detail::delivery_man;
remote_call_manager::remote_call_manager():
m_oDTDeliveryMan(),
m_oSTDeliveryMan(),
m_oDTFunction(bind(&delivery_man::accept_deliveries, &m_oDTDeliveryMan)),
m_oSTFunction(bind(&delivery_man::accept_deliveries, &m_oSTDeliveryMan)),
m_oDTPeriodical(m_oDTFunction),
m_oSTPeriodical(m_oSTFunction)
{
m_oDTPeriodical.start();
m_oSTPeriodical.start();
}
remote_call_manager::~remote_call_manager()
{
}
} // namespace detail
} // namespace mac
} // namespace threads
} // namespace boost

View File

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

View File

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

View File

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

View File

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

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