mirror of
https://github.com/boostorg/thread.git
synced 2026-02-03 09:42:16 +00:00
Compare commits
3 Commits
svn-tags/m
...
boost-1.30
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7795156c5d | ||
|
|
7a982cb083 | ||
|
|
215ae5dd53 |
@@ -1,13 +1,8 @@
|
||||
# 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.
|
||||
# (C) Copyright William E. Kempf 2001. Permission to copy, use, modify,
|
||||
# sell and distribute this software is granted provided this copyright
|
||||
# notice appears in all copies. This software is provided "as is" without
|
||||
# express or implied warranty, and with no claim as to its suitability for
|
||||
# any purpose.
|
||||
#
|
||||
# Boost.Threads build Jamfile
|
||||
#
|
||||
@@ -27,30 +22,26 @@ 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 ;
|
||||
SEARCH on <module@>threads.jam = $(SUBDIR) ;
|
||||
include <module@>threads.jam ;
|
||||
|
||||
{
|
||||
template thread_libs
|
||||
## sources ##
|
||||
: <template>thread_base
|
||||
## requirements ##
|
||||
: <sysinclude>$(BOOST_ROOT)
|
||||
## default build ##
|
||||
:
|
||||
## default build ##
|
||||
: debug release
|
||||
;
|
||||
|
||||
# Base names of the source files for libboost_thread.
|
||||
CPP_SOURCES = condition mutex recursive_mutex thread tss xtime once
|
||||
exceptions barrier threadmon ;
|
||||
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
|
||||
@@ -59,8 +50,4 @@ import ./threads ;
|
||||
<tag><debug>"d"
|
||||
: debug release
|
||||
;
|
||||
|
||||
install thread lib
|
||||
: <dll>boost_thread
|
||||
;
|
||||
}
|
||||
|
||||
@@ -1,26 +1,12 @@
|
||||
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 ;
|
||||
}
|
||||
# Declare the uses system library
|
||||
lib pthread : : <name>pthread ;
|
||||
|
||||
project boost/thread
|
||||
: source-location ../src
|
||||
: usage-requirements $(usage)
|
||||
: requirements $(reqts) <threading>multi
|
||||
: default-build <threading>multi
|
||||
: usage-requirements <library>pthread
|
||||
;
|
||||
|
||||
CPP_SOURCES = condition mutex recursive_mutex thread tss xtime once
|
||||
exceptions threadmon ;
|
||||
CPP_SOURCES = condition mutex recursive_mutex thread tss xtime once exceptions ;
|
||||
|
||||
lib boost_thread
|
||||
: $(CPP_SOURCES).cpp
|
||||
;
|
||||
lib boost_thread : $(CPP_SOURCES).cpp ;
|
||||
|
||||
@@ -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.
|
||||
|
||||
# Do some OS-specific setup
|
||||
{
|
||||
pthreads-win32 = ;
|
||||
@@ -33,7 +22,7 @@
|
||||
:
|
||||
## requirements ##
|
||||
: <sysinclude>$(BOOST_ROOT) <threading>multi $(pthreads-win32)
|
||||
<borland><*><cxxflags>-w-8004 <borland><*><cxxflags>-w-8057
|
||||
<borland><*><cxxflags>-w-8004
|
||||
## default build ##
|
||||
:
|
||||
;
|
||||
|
||||
168
doc/barrier.html
168
doc/barrier.html
@@ -1,168 +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 <boost/thread/barrier.hpp></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 <<a href="../../../boost/thread/barrier.hpp">boost/thread/barrier.hpp</a>></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-barrier">Class <code>barrier</code></a></dt>
|
||||
<dl class="page-index">
|
||||
<dt><a href="#class-barrier-synopsis">Class <code>barrier</code> synopsis</a></dt>
|
||||
<dt><a href="#class-barrier-ctors">Class <code>barrier</code> constructors
|
||||
and destructor</a></dt>
|
||||
<dt><a href="#class-barrier-modifiers">Class <code>barrier</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 <<a href="../../../boost/thread/barrier.hpp">boost/thread/barrier.hpp</a>>
|
||||
to define the class <code>boost::barrier</code>.</p>
|
||||
<h2><a name="classes"></a>Classes</h2>
|
||||
<h3><a name="class-barrier"></a>Class <code>barrier</code></h3>
|
||||
<p>An object of class <code>barrier</code> is a synchronization primitive used
|
||||
to cause a set of threads to wait until they each perform a certain function
|
||||
or each reach a particular point in their execution. When a barrier is created,
|
||||
it is initialized with a thread count "N". The first N-1 calls to wait() will
|
||||
all cause their threads to be blocked. The Nth call to wait() will allow all
|
||||
of the waiting threads, including the Nth thread, to be placed in a ready state.
|
||||
Should an additional thread make an N+1th call to wait() on the barrier, it
|
||||
will be as though this was the first call to wait(), and the process will be
|
||||
repeated until another N threads call wait(). This functionality allows the
|
||||
same set of N threads to re-use a barrier object to synchronize their execution
|
||||
at multiple points during their execution.</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>
|
||||
<h4><a name="class-barrier-synopsis"></a>Class <code>barrier</code> synopsis</h4>
|
||||
<pre>
|
||||
namespace boost
|
||||
{
|
||||
class barrier : private <A href="../../utility/utility.htm#Class noncopyable">boost::noncopyable</A> // Exposition only.
|
||||
// Class barrier meets the <A href="overview.html#NonCopyable" .. utility.htm#Class? utility>NonCopyable</A> requirement.
|
||||
{
|
||||
public:
|
||||
barrier(size_t count);
|
||||
~barrier();
|
||||
|
||||
bool wait();
|
||||
};
|
||||
};
|
||||
</pre>
|
||||
<h4><a name="class-barrier-ctors"></a>Class <code>barrier</code> constructors
|
||||
and destructor</h4>
|
||||
<pre>
|
||||
barrier(size_t count);
|
||||
</pre>
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> Constructs a <code>barrier</code> object that will cause
|
||||
count threads to block on a call to <code>wait()</code>.</dt>
|
||||
</dl>
|
||||
<pre>
|
||||
~barrier();
|
||||
</pre>
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> Destroys <code>*this</code>. If threads are still executing
|
||||
their <code>wait()</code> operations, the behavior for these threads is undefined.</dt>
|
||||
</dl>
|
||||
<h4><a name="class-barrier-modifiers"></a>Class <code>barrier</code> modifier
|
||||
functions</h4>
|
||||
<pre>
|
||||
bool wait();
|
||||
</pre>
|
||||
<dl class="function-semantics">
|
||||
<dt><b>Effects:</b> Wait until N threads call wait(), where N equals the count
|
||||
provided to the constructor for the barrier object.</dt>
|
||||
<dt><b>Returns:</b> Exactly one of the N threads will receive a return value
|
||||
of <code>true</code>, the others will receive a value of <code>false</code>.
|
||||
Precisely which thread receives the return value of <code>true</code> will
|
||||
be implementation defined. Applications can use this value to designate one
|
||||
thread as a leader that will take a certain action, and the other threads
|
||||
emerging from the barrier can wait for that action to take place.</dt>
|
||||
<dt><b>Danger:</b> If the barrier is destroyed before <code>wait()</code> can
|
||||
return, the behavior is undefined.</dt>
|
||||
</dl>
|
||||
<h2><a name="examples"></a>Example(s)</h2>
|
||||
<pre>
|
||||
#include <a href="../../../boost/thread/condition.hpp"><boost/thread/barrier.hpp></a>
|
||||
#include <a href="../../../boost/thread/thread.hpp"><boost/thread/thread.hpp></a>
|
||||
#include <a href="../../../boost/thread/mutex.hpp"><boost/thread/mutex.hpp></a>
|
||||
#include <iostream>
|
||||
|
||||
const int N_THREADS = 10;
|
||||
boost::barrier gen_barrier(N_THREADS);
|
||||
int global_parameter = 0;
|
||||
boost::mutex mutex;
|
||||
|
||||
static void worker()
|
||||
{
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
// Simulate 5 cycles of computation...
|
||||
if (gen_barrier.wait())
|
||||
{
|
||||
boost::mutex::scoped_lock lock(mutex);
|
||||
global_parameter++;
|
||||
}
|
||||
}
|
||||
|
||||
// Let one worker "report" the results
|
||||
if (gen_barrier.wait())
|
||||
{
|
||||
boost::mutex::scoped_lock lock(lock);
|
||||
std::cout << "Global Parameter=" << global_parameter << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
boost::thread_group g;
|
||||
global_parameter = 0;
|
||||
|
||||
for (int i = 0; i < N_THREADS; ++i)
|
||||
g.create_thread(&worker);
|
||||
|
||||
g.join_all();
|
||||
|
||||
}
|
||||
</pre>
|
||||
<p>The output is:</p>
|
||||
<pre>
|
||||
Global Parameter=5
|
||||
</pre>
|
||||
<hr>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
05 November, 2001
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="mailto:jdmoore99@comcast.net">Dave Moore</a> and <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 "as is" without express or implied warranty.</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -28,8 +28,7 @@
|
||||
"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>
|
||||
Message Passing, and Remote Procedure Call in addition to the basics.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -54,28 +53,12 @@
|
||||
from event queues and semaphores to critical regions and monitors."
|
||||
Includes analysis of why <i>events</i> are considered error-prone. Also
|
||||
noteworthy because of an introductory quotation from Christopher Alexander;
|
||||
Brinch Hansen was years ahead of others in recognizing that pattern concepts
|
||||
Brinch Hansen was years ahead of others in recognizing pattern concepts
|
||||
applied to software too.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="102" valign="top" align="left"><b>[<a name="Brinch-Hansen-02">Brinch
|
||||
Hansen 02</a>]</b></td>
|
||||
<td width="645">
|
||||
Per Brinch Hansen, Ed., <i>The Origin of Concurrent Programming,
|
||||
from Semaphores to Remote Procedure Calls</i>, Springer-Verlag, 2002. ISBN
|
||||
0-387-95401-5.
|
||||
<a href="http://www.springer-ny.com/detail.tpl?isbn=0387954015">
|
||||
http://www.springer-ny.com/detail.tpl?isbn=0387954015</a><p>Nineteen of
|
||||
the original seminal papers by Dijkstra, Brinch Hansen, and Hoare, plus a
|
||||
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>
|
||||
<td width="102" valign="top" align="left"><b>[<a name=
|
||||
<td width="102" valign="top" align="left"><b>]<a name=
|
||||
"Butenhof-97">Butenhof 97</a>]</b></td>
|
||||
<td width="645">
|
||||
<p>David R. Butenhof, <cite>Programming with POSIX Threads</cite>, Addison-Wesley
|
||||
@@ -97,8 +80,7 @@
|
||||
"http://www.acm.org/classics/feb96/"> http://www.acm.org/classics/feb96/</a></p>
|
||||
<p>Hoare and Brinch Hansen's work on Monitors is the basis for reliable
|
||||
multithreading patterns. This is one of the most often referenced papers
|
||||
in all of computer science, and with good reason. It is included in [<a href="#Brinch-Hansen-02">Brinch
|
||||
Hansen 02</a>]</p>
|
||||
in all of computer science, and with good reason.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -167,10 +149,12 @@
|
||||
be visible on printed copies of this document.</p>
|
||||
<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" -->
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->
|
||||
05 November, 2001
|
||||
<!--webbot bot="Timestamp" endspan i-checksum="39359" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="mailto:wekempf@cox.net">William E. Kempf</a> and
|
||||
<a href="../../../people/beman_dawes.html">Beman Dawes</a> 2001-2003. All Rights Reserved.</i></p>
|
||||
Beman Dawes 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
|
||||
@@ -178,4 +162,4 @@
|
||||
makes no representations about the suitability of this software for any purpose.
|
||||
It is provided "as is" without express or implied warranty.</p>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
13
doc/faq.html
13
doc/faq.html
@@ -163,19 +163,10 @@ private:
|
||||
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 "semaphores ... are not suitable for higher level
|
||||
languages." [<a href="bibliography.html#Andrews-83">Andrews-83]</a>
|
||||
summarizes typical errors as "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", forgetting to
|
||||
include all references to shared objects in critical sections, and confusion
|
||||
caused by using the same primitive for "both condition synchronization and
|
||||
mutual exclusion".</p>
|
||||
greater safety by the combination of a mutex and a condition variable.</p>
|
||||
<hr>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->19 July, 2003<!--webbot bot="Timestamp" endspan i-checksum="21111" -->
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->09 January, 2003<!--webbot bot="Timestamp" endspan i-checksum="38582" -->
|
||||
</p>
|
||||
<p><i>© Copyright <a href="mailto:wekempf@cox.net">William E. Kempf</a> 2001-2002.
|
||||
All Rights Reserved.</i></p>
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
<p><b>Recommendation:</b> For the most portable, yet thread-safe code, use Boost
|
||||
replacements for the problem functions. See the <a href=
|
||||
"../../random/index.html">Boost Random Number Library</a> and <a href=
|
||||
"../../tokenizer/index.html">Boost Tokenizer Library</a>.</p>
|
||||
"../../tokenizer/index.htm">Boost Tokenizer Library</a>.</p>
|
||||
<h2><a name="common-gaurantees"></a>Common guarantees for all Boost.Threads components</h2>
|
||||
<h3><a name="exceptions"></a>Exceptions</h3>
|
||||
<p><b>Boost.Threads</b> destructors never throw exceptions. Unless otherwise specified,
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
# 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.
|
||||
# (C) Copyright William E. Kempf 2001. Permission to copy, use, modify, sell
|
||||
# and distribute this software is granted provided this copyright notice
|
||||
# appears in all copies. This software is provided "as is" without express or
|
||||
# implied warranty, and with no claim as to its suitability for any purpose.
|
||||
#
|
||||
# Boost.Threads example Jamfile
|
||||
#
|
||||
@@ -27,7 +21,8 @@ subproject libs/thread/example ;
|
||||
# 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 ../build/threads ;
|
||||
SEARCH on <module@>threads.jam = $(BOOST_ROOT)/libs/thread/build ;
|
||||
include <module@>threads.jam ;
|
||||
|
||||
{
|
||||
template example
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
#include <boost/thread/thread.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
const int ITERS = 100;
|
||||
boost::mutex io_mutex;
|
||||
|
||||
} // namespace
|
||||
|
||||
template <typename M>
|
||||
|
||||
@@ -16,10 +16,11 @@
|
||||
#include <iostream>
|
||||
#include <time.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
|
||||
boost::mutex iomx;
|
||||
} // namespace
|
||||
|
||||
}
|
||||
|
||||
class canteen
|
||||
{
|
||||
|
||||
@@ -60,10 +60,8 @@ void player(void* param)
|
||||
{
|
||||
cond.wait(lock);
|
||||
if (state == other)
|
||||
{
|
||||
std::cout << "---" << player_name(active)
|
||||
<< ": Spurious wakeup!" << std::endl;
|
||||
}
|
||||
} while (state == other);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
// Copyright (C) 2002-2003
|
||||
// David Moore, 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_BARRIER_JDM030602_HPP
|
||||
#define BOOST_BARRIER_JDM030602_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
// insist on threading support being available:
|
||||
#include <boost/config/requires_threads.hpp>
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
class BOOST_THREAD_DECL barrier
|
||||
{
|
||||
public:
|
||||
barrier(unsigned int count);
|
||||
~barrier();
|
||||
|
||||
bool wait();
|
||||
|
||||
private:
|
||||
mutex m_mutex;
|
||||
condition m_cond;
|
||||
unsigned int m_threshold;
|
||||
unsigned int m_count;
|
||||
unsigned int m_generation;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
@@ -13,9 +13,9 @@
|
||||
#define BOOST_CONDITION_WEK070601_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
// insist on threading support being available:
|
||||
#include <boost/config/requires_threads.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
# error Thread support is unavailable!
|
||||
#endif
|
||||
|
||||
#include <boost/thread/exceptions.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
@@ -12,11 +12,6 @@
|
||||
#ifndef BOOST_THREAD_CONFIG_WEK01032003_HPP
|
||||
#define BOOST_THREAD_CONFIG_WEK01032003_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
// insist on threading support being available:
|
||||
#include <boost/config/requires_threads.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_WINTHREADS)
|
||||
# if defined(BOOST_THREAD_BUILD_DLL)
|
||||
# define BOOST_THREAD_DECL __declspec(dllexport)
|
||||
@@ -27,23 +22,4 @@
|
||||
# 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// Copyright (C) 2001
|
||||
// Mac Murrett
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
@@ -15,27 +15,30 @@
|
||||
#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));
|
||||
}
|
||||
{ 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));
|
||||
}
|
||||
{ return(*reinterpret_cast<const Return_Type *>(&rSrc)); }
|
||||
|
||||
|
||||
} // namespace thread
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_FORCE_CAST_MJM012402_HPP
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// Copyright (C) 2001
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
@@ -198,10 +198,10 @@ private:
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_XLOCK_WEK070601_HPP
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
|
||||
// 30 Jul 01 WEKEMPF Moved lock types into boost::detail::thread. Renamed
|
||||
// some types. Added locked() methods.
|
||||
// 30 Jul 01 WEKEMPF Moved lock types into boost::detail::thread. Renamed some types.
|
||||
// Added locked() methods.
|
||||
|
||||
#endif // BOOST_XLOCK_WEK070601_HPP
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2001-2003
|
||||
// Copyright (C) 2001
|
||||
// Mac Murrett
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
@@ -15,14 +15,16 @@
|
||||
#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.
|
||||
// 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
|
||||
template<class T>
|
||||
class singleton: private T
|
||||
{
|
||||
private:
|
||||
singleton();
|
||||
@@ -33,19 +35,16 @@ public:
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
template<class T>
|
||||
inline singleton<T>::singleton()
|
||||
{
|
||||
/* no-op */
|
||||
}
|
||||
{ /* no-op */ }
|
||||
|
||||
template <class T>
|
||||
template<class T>
|
||||
inline singleton<T>::~singleton()
|
||||
{
|
||||
/* no-op */
|
||||
}
|
||||
{ /* no-op */ }
|
||||
|
||||
template <class T>
|
||||
|
||||
template<class T>
|
||||
/*static*/ T &singleton<T>::instance()
|
||||
{
|
||||
// function-local static to force this to work correctly at static
|
||||
@@ -54,8 +53,12 @@ template <class T>
|
||||
return(s_oT);
|
||||
}
|
||||
|
||||
|
||||
} // namespace thread
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_SINGLETON_MJM012402_HPP
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
// 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>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
# error Thread support is unavailable!
|
||||
#endif
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
|
||||
@@ -13,8 +13,9 @@
|
||||
#define BOOST_MUTEX_WEK070601_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
// insist on threading support being available:
|
||||
#include <boost/config/requires_threads.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
# error Thread support is unavailable!
|
||||
#endif
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/detail/lock.hpp>
|
||||
|
||||
@@ -13,8 +13,9 @@
|
||||
#define BOOST_ONCE_WEK080101_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
// insist on threading support being available:
|
||||
#include <boost/config/requires_threads.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
# error Thread support is unavailable!
|
||||
#endif
|
||||
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
#define BOOST_RECURSIVE_MUTEX_WEK070601_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
// insist on threading support being available:
|
||||
#include <boost/config/requires_threads.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
# error Thread support is unavailable!
|
||||
#endif
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/detail/lock.hpp>
|
||||
@@ -169,11 +169,12 @@ private:
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_RECURSIVE_MUTEX_WEK070601_HPP
|
||||
|
||||
// Change Log:
|
||||
// 8 Feb 01 WEKEMPF Initial version.
|
||||
// 1 Jun 01 WEKEMPF Modified to use xtime for time outs. Factored out
|
||||
// to three classes, mutex, try_mutex and timed_mutex.
|
||||
// 11 Jun 01 WEKEMPF Modified to use PTHREAD_MUTEX_RECURSIVE if available.
|
||||
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
|
||||
|
||||
|
||||
#endif // BOOST_RECURSIVE_MUTEX_WEK070601_HPP
|
||||
|
||||
@@ -13,8 +13,9 @@
|
||||
#define BOOST_THREAD_WEK070601_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
// insist on threading support being available:
|
||||
#include <boost/config/requires_threads.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
# error Thread support is unavailable!
|
||||
#endif
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/function.hpp>
|
||||
|
||||
@@ -13,8 +13,9 @@
|
||||
#define BOOST_TSS_WEK070601_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
// insist on threading support being available:
|
||||
#include <boost/config/requires_threads.hpp>
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
# error Thread support is unavailable!
|
||||
#endif
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/thread/detail/config.hpp>
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
// Copyright (C) 2002-2003
|
||||
// David Moore, 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/barrier.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
barrier::barrier(unsigned int count)
|
||||
: m_threshold(count), m_count(count), m_generation(0)
|
||||
{
|
||||
if (count == 0)
|
||||
throw std::invalid_argument("count cannot be zero.");
|
||||
}
|
||||
|
||||
barrier::~barrier()
|
||||
{
|
||||
}
|
||||
|
||||
bool barrier::wait()
|
||||
{
|
||||
boost::mutex::scoped_lock lock(m_mutex);
|
||||
unsigned int gen = m_generation;
|
||||
|
||||
if (--m_count == 0)
|
||||
{
|
||||
m_generation++;
|
||||
m_count = m_threshold;
|
||||
m_cond.notify_all();
|
||||
return true;
|
||||
}
|
||||
|
||||
while (gen == m_generation)
|
||||
m_cond.wait(lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
15
src/once.cpp
15
src/once.cpp
@@ -127,7 +127,7 @@ void call_once(void (*func)(), once_flag& flag)
|
||||
strm << "2AC1A572DB6944B0A65C38C4140AF2F4" << std::hex
|
||||
<< GetCurrentProcessId() << &flag << std::ends;
|
||||
unfreezer unfreeze(strm);
|
||||
HANDLE mutex = CreateMutexA(NULL, FALSE, strm.str());
|
||||
HANDLE mutex = CreateMutex(NULL, FALSE, strm.str());
|
||||
#else
|
||||
std::ostringstream strm;
|
||||
strm << "2AC1A572DB6944B0A65C38C4140AF2F4" << std::hex
|
||||
@@ -142,18 +142,7 @@ void call_once(void (*func)(), once_flag& flag)
|
||||
|
||||
if (compare_exchange(&flag, 1, 1) == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
func();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
res = ReleaseMutex(mutex);
|
||||
assert(res);
|
||||
res = CloseHandle(mutex);
|
||||
assert(res);
|
||||
throw;
|
||||
}
|
||||
func();
|
||||
InterlockedExchange(&flag, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,12 +34,12 @@ recursive_mutex::recursive_mutex()
|
||||
: m_mutex(0), m_count(0)
|
||||
{
|
||||
try
|
||||
{
|
||||
{
|
||||
m_mutex = reinterpret_cast<void*>(new CRITICAL_SECTION);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
if (!m_mutex)
|
||||
throw thread_resource_error();
|
||||
InitializeCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(m_mutex));
|
||||
|
||||
21
test/Jamfile
21
test/Jamfile
@@ -1,13 +1,7 @@
|
||||
# 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.
|
||||
# (C) Copyright William E. Kempf 2001. Permission to copy, use, modify, sell
|
||||
# and distribute this software is granted provided this copyright notice
|
||||
# appears in all copies. This software is provided "as is" without express or
|
||||
# implied warranty, and with no claim as to its suitability for any purpose.
|
||||
#
|
||||
# Boost.Threads test Jamfile
|
||||
#
|
||||
@@ -27,10 +21,12 @@ subproject libs/thread/test ;
|
||||
# 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 ../build/threads ;
|
||||
SEARCH on threads.jam = $(BOOST_ROOT)/libs/thread/build ;
|
||||
include threads.jam ;
|
||||
|
||||
# bring in rules for testing
|
||||
import testing ;
|
||||
SEARCH on testing.jam = $(BOOST_BUILD_PATH) ;
|
||||
include testing.jam ;
|
||||
|
||||
{
|
||||
template test
|
||||
@@ -51,6 +47,5 @@ import testing ;
|
||||
[ run test_tss.cpp <template>test ]
|
||||
[ run test_once.cpp <template>test ]
|
||||
[ run test_xtime.cpp <template>test ]
|
||||
[ run test_barrier.cpp <template>test ]
|
||||
;
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
# (C) Copyright William E. Kempf 2001. Permission to copy, use, modify, sell
|
||||
# and distribute this software is granted provided this copyright notice
|
||||
# appears in all copies. This software is provided "as is" without express or
|
||||
# implied warranty, and with no claim as to its suitability for any purpose.
|
||||
#
|
||||
# Boost.Threads test Jamfile
|
||||
#
|
||||
# Additional configuration variables used:
|
||||
# 1. PTW32 may be used on Win32 platforms to specify that the pthreads-win32
|
||||
# library should be used instead of "native" threads. This feature is
|
||||
# mostly used for testing and it's generally recommended you use the
|
||||
# native threading libraries instead. PTW32 should be set to be a list
|
||||
# of two strings, the first specifying the installation path of the
|
||||
# pthreads-win32 library and the second specifying which library
|
||||
# variant to link against (see the pthreads-win32 documentation).
|
||||
# Example: jam -sPTW32="c:\pthreads-win32 pthreadVCE.lib"
|
||||
|
||||
# bring in rules for testing
|
||||
import testing ;
|
||||
|
||||
project
|
||||
: requirements <library>../build//boost_thread
|
||||
<library>../../test/build//boost_unit_test_framework
|
||||
<threading>multi
|
||||
;
|
||||
{
|
||||
test-suite "threads"
|
||||
: [ run test_thread.cpp ]
|
||||
[ run test_mutex.cpp ]
|
||||
[ run test_condition.cpp ]
|
||||
[ run test_tss.cpp ]
|
||||
[ run test_once.cpp ]
|
||||
[ run test_xtime.cpp ]
|
||||
;
|
||||
}
|
||||
@@ -1,60 +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/barrier.hpp>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
// Shared variables for generation barrier test
|
||||
const int N_THREADS=10;
|
||||
boost::barrier gen_barrier(N_THREADS);
|
||||
boost::mutex mutex;
|
||||
long global_parameter;
|
||||
|
||||
void barrier_thread()
|
||||
{
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
if (gen_barrier.wait())
|
||||
{
|
||||
boost::mutex::scoped_lock lock(mutex);
|
||||
global_parameter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void test_barrier()
|
||||
{
|
||||
boost::thread_group g;
|
||||
global_parameter = 0;
|
||||
|
||||
for (int i = 0; i < N_THREADS; ++i)
|
||||
g.create_thread(&barrier_thread);
|
||||
|
||||
g.join_all();
|
||||
|
||||
BOOST_TEST(global_parameter == 5);
|
||||
}
|
||||
|
||||
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
|
||||
{
|
||||
boost::unit_test_framework::test_suite* test =
|
||||
BOOST_TEST_SUITE("Boost.Threads: barrier test suite");
|
||||
|
||||
test->add(BOOST_TEST_CASE(&test_barrier));
|
||||
|
||||
return test;
|
||||
}
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
#include "util.inl"
|
||||
|
||||
boost::mutex check_mutex;
|
||||
boost::mutex tss_mutex;
|
||||
int tss_instances = 0;
|
||||
|
||||
@@ -45,13 +44,7 @@ void test_tss_thread()
|
||||
for (int i=0; i<1000; ++i)
|
||||
{
|
||||
int& n = tss_value->value;
|
||||
// Don't call BOOST_CHECK_EQUAL directly, as it doesn't appear to
|
||||
// be thread safe. Must evaluate further.
|
||||
if (n != i)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(check_mutex);
|
||||
BOOST_CHECK_EQUAL(n, i);
|
||||
}
|
||||
BOOST_CHECK_EQUAL(n, i);
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
# Copyright (C) 2001-2003
|
||||
# William E. Kempf
|
||||
# (C) Copyright William E. Kempf 2001. Permission to copy, use, modify, sell
|
||||
# and distribute this software is granted provided this copyright notice
|
||||
# appears in all copies. This software is provided "as is" without express or
|
||||
# implied warranty, and with no claim as to its suitability for any purpose.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Boost.Threads tutorial Jamfile
|
||||
# Boost.Threads example Jamfile
|
||||
#
|
||||
# Additional configuration variables used:
|
||||
# 1. PTW32 may be used on Win32 platforms to specify that the pthreads-win32
|
||||
@@ -28,7 +22,8 @@ subproject libs/thread/tutorial ;
|
||||
# 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 ../build/threads ;
|
||||
SEARCH on <module@>threads.jam = $(BOOST_ROOT)/libs/thread/build ;
|
||||
include <module@>threads.jam ;
|
||||
|
||||
{
|
||||
template tutorial
|
||||
|
||||
@@ -14,16 +14,12 @@
|
||||
|
||||
struct helloworld
|
||||
{
|
||||
helloworld(const char* who) : m_who(who) { }
|
||||
void operator()()
|
||||
{
|
||||
std::cout << m_who << "says, \"Hello World.\"" << std::endl;
|
||||
}
|
||||
const char* m_who;
|
||||
helloworld() { }
|
||||
void operator()() { std::cout << "Hello World." << std::endl; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::thread thrd(helloworld("Bob"));
|
||||
boost::thread thrd(helloworld());
|
||||
thrd.join();
|
||||
}
|
||||
|
||||
@@ -10,16 +10,17 @@
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <iostream>
|
||||
|
||||
void helloworld(const char* who)
|
||||
struct helloworld
|
||||
{
|
||||
std::cout << who << "says, \"Hello World.\"" << std::endl;
|
||||
}
|
||||
helloworld(const char* who) : m_who(who) { }
|
||||
void operator()() { std::cout << m_who << "says, \"Hello World.\"" << std::endl; }
|
||||
const char* m_who;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
boost::thread thrd(boost::bind(&helloworld, "Bob"));
|
||||
boost::thread thrd(helloworld("Bob"));
|
||||
thrd.join();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user