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

Compare commits

...

8 Commits

Author SHA1 Message Date
Daniel James
c86959afb7 Fix links to the license text file.
[SVN r43289]
2008-02-17 12:49:59 +00:00
Daniel James
8b302dbb4f More fixed links.
[SVN r43279]
2008-02-16 11:39:55 +00:00
Daniel James
43943faf5c Merge.
[SVN r43162]
2008-02-07 18:54:14 +00:00
Daniel James
f934c01bdf Merge.
[SVN r42905]
2008-01-21 20:15:02 +00:00
Daniel James
5af025cdce Merge from trunk.
[SVN r42243]
2007-12-22 15:36:31 +00:00
Daniel James
1b56fe63d1 Merge from trunk.
[SVN r41865]
2007-12-08 11:05:02 +00:00
Daniel James
d460417a09 Merge from trunk, finally.
[SVN r41817]
2007-12-07 01:12:02 +00:00
Daniel James
67ce920ab8 Create a branch to fix links on.
[SVN r41573]
2007-12-02 10:07:42 +00:00
53 changed files with 970 additions and 451 deletions

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<section id="thread.acknowledgements" <section id="thread.acknowledgements"
last-revision="$Date$"> last-revision="$Date$">

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<header name="boost/thread/barrier.hpp" <header name="boost/thread/barrier.hpp"
last-revision="$Date$"> last-revision="$Date$">

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<bibliography id="thread.bibliography" <bibliography id="thread.bibliography"
last-revision="$Date$"> last-revision="$Date$">
@@ -45,7 +45,7 @@ last-revision="$Date$">
<biblioentry id="thread.bib.Boost"> <biblioentry id="thread.bib.Boost">
<abbrev id="thread.bib.Boost.abbrev">Boost</abbrev> <abbrev id="thread.bib.Boost.abbrev">Boost</abbrev>
<bibliomisc>The <emphasis>Boost</emphasis> world wide web site. <bibliomisc>The <emphasis>Boost</emphasis> world wide web site.
<ulink url="http:/www.boost.org">http://www.boost.org</ulink></bibliomisc> <ulink url="http://www.boost.org">http://www.boost.org</ulink></bibliomisc>
<para>&Boost.Thread; is one of many Boost libraries. The Boost web <para>&Boost.Thread; is one of many Boost libraries. The Boost web
site includes a great deal of documentation and general information which site includes a great deal of documentation and general information which
applies to all Boost libraries. Current copies of the libraries including applies to all Boost libraries. Current copies of the libraries including

View File

@@ -7,7 +7,7 @@
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Copyright (c) 2007 Roland Schwarz Copyright (c) 2007 Roland Schwarz
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<section id="thread.build" last-revision="$Date$"> <section id="thread.build" last-revision="$Date$">
<title>Build</title> <title>Build</title>

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<section id="thread.concepts" last-revision="$Date$"> <section id="thread.concepts" last-revision="$Date$">
<title>Concepts</title> <title>Concepts</title>

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<header name="boost/thread/condition.hpp" <header name="boost/thread/condition.hpp"
last-revision="$Date$"> last-revision="$Date$">

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<section id="thread.configuration" last-revision="$Date$"> <section id="thread.configuration" last-revision="$Date$">
<title>Configuration</title> <title>Configuration</title>

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<section id="thread.design" last-revision="$Date$"> <section id="thread.design" last-revision="$Date$">
<title>Design</title> <title>Design</title>

View File

@@ -1,6 +1,6 @@
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<!ENTITY Boost "<emphasis role='bold'>Boost</emphasis>"> <!ENTITY Boost "<emphasis role='bold'>Boost</emphasis>">
<!ENTITY Boost.Thread "<emphasis role='bold'>Boost.Thread</emphasis>"> <!ENTITY Boost.Thread "<emphasis role='bold'>Boost.Thread</emphasis>">

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<header name="boost/thread/exceptions.hpp" <header name="boost/thread/exceptions.hpp"
last-revision="$Date$"> last-revision="$Date$">

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<section id="thread.faq" last-revision="$Date$"> <section id="thread.faq" last-revision="$Date$">
<title>Frequently Asked Questions</title> <title>Frequently Asked Questions</title>

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<glossary id="thread.glossary" last-revision="$Date$"> <glossary id="thread.glossary" last-revision="$Date$">
<title>Glossary</title> <title>Glossary</title>

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<section id="thread.implementation_notes" last-revision="$Date$"> <section id="thread.implementation_notes" last-revision="$Date$">
<title>Implementation Notes</title> <title>Implementation Notes</title>

View File

@@ -1,6 +1,6 @@
<!-- Copyright (c) 2002-2003 Beman Dawes, William E. Kempf. <!-- Copyright (c) 2002-2003 Beman Dawes, William E. Kempf.
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<html> <html>
<head> <head>

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<header name="boost/thread/mutex.hpp" <header name="boost/thread/mutex.hpp"
last-revision="$Date$"> last-revision="$Date$">

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<header name="boost/thread/once.hpp" <header name="boost/thread/once.hpp"
last-revision="$Date$"> last-revision="$Date$">

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<section id="thread.overview" last-revision="$Date$"> <section id="thread.overview" last-revision="$Date$">
<title>Overview</title> <title>Overview</title>

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<section id="thread.rationale" last-revision="$Date$"> <section id="thread.rationale" last-revision="$Date$">
<title>Rationale</title> <title>Rationale</title>

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<header name="boost/thread/read_write_mutex.hpp" <header name="boost/thread/read_write_mutex.hpp"
last-revision="$Date$"> last-revision="$Date$">

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<header name="boost/thread/recursive_mutex.hpp" <header name="boost/thread/recursive_mutex.hpp"
last-revision="$Date$"> last-revision="$Date$">

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<library-reference id="thread.reference" <library-reference id="thread.reference"
last-revision="$Date$" last-revision="$Date$"

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<section id="thread.release_notes" last-revision="$Date$"> <section id="thread.release_notes" last-revision="$Date$">
<title>Release Notes</title> <title>Release Notes</title>

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<header name="boost/thread/thread.hpp" <header name="boost/thread/thread.hpp"
last-revision="$Date$"> last-revision="$Date$">

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<library name="Thread" dirname="thread" id="thread" <library name="Thread" dirname="thread" id="thread"
last-revision="$Date$" last-revision="$Date$"
@@ -25,7 +25,7 @@ xmlns:xi="http://www.w3.org/2001/XInclude">
</copyright> </copyright>
<legalnotice> <legalnotice>
<para>Subject to the Boost Software License, Version 1.0. <para>Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0)</para> (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)</para>
</legalnotice> </legalnotice>
<librarypurpose>Portable C++ multi-threading</librarypurpose> <librarypurpose>Portable C++ multi-threading</librarypurpose>
<librarycategory name="category:concurrent" /> <librarycategory name="category:concurrent" />

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<header name="boost/thread/tss.hpp" <header name="boost/thread/tss.hpp"
last-revision="$Date$"> last-revision="$Date$">

View File

@@ -6,7 +6,7 @@
]> ]>
<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford <!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<header name="boost/thread/xtime.hpp" <header name="boost/thread/xtime.hpp"
last-revision="$Date$"> last-revision="$Date$">

View File

@@ -8,25 +8,23 @@
namespace boost namespace boost
{ {
template<typename T> namespace detail
struct move_t
{ {
T& t; template<typename T>
move_t(T& t_): struct thread_move_t
t(t_)
{}
T* operator->() const
{ {
return &t; T& t;
} thread_move_t(T& t_):
}; t(t_)
{}
template<typename T> T* operator->() const
move_t<T> move(T& t) {
{ return &t;
return move_t<T>(t); }
};
} }
} }

View File

@@ -86,21 +86,32 @@ namespace boost
{ {
timed_lock(target_time); timed_lock(target_time);
} }
unique_lock(boost::move_t<unique_lock<Mutex> > other): unique_lock(detail::thread_move_t<unique_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked) m(other->m),is_locked(other->is_locked)
{ {
other->is_locked=false; other->is_locked=false;
other->m=0;
} }
unique_lock(boost::move_t<upgrade_lock<Mutex> > other); unique_lock(detail::thread_move_t<upgrade_lock<Mutex> > other);
unique_lock& operator=(boost::move_t<unique_lock<Mutex> > other) operator detail::thread_move_t<unique_lock<Mutex> >()
{
return move();
}
detail::thread_move_t<unique_lock<Mutex> > move()
{
return detail::thread_move_t<unique_lock<Mutex> >(*this);
}
unique_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other)
{ {
unique_lock temp(other); unique_lock temp(other);
swap(temp); swap(temp);
return *this; return *this;
} }
unique_lock& operator=(boost::move_t<upgrade_lock<Mutex> > other) unique_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other)
{ {
unique_lock temp(other); unique_lock temp(other);
swap(temp); swap(temp);
@@ -112,7 +123,7 @@ namespace boost
std::swap(m,other.m); std::swap(m,other.m);
std::swap(is_locked,other.is_locked); std::swap(is_locked,other.is_locked);
} }
void swap(boost::move_t<unique_lock<Mutex> > other) void swap(detail::thread_move_t<unique_lock<Mutex> > other)
{ {
std::swap(m,other->m); std::swap(m,other->m);
std::swap(is_locked,other->is_locked); std::swap(is_locked,other->is_locked);
@@ -196,6 +207,18 @@ namespace boost
friend class upgrade_lock<Mutex>; friend class upgrade_lock<Mutex>;
}; };
template<typename Mutex>
inline detail::thread_move_t<unique_lock<Mutex> > move(unique_lock<Mutex> & x)
{
return x.move();
}
template<typename Mutex>
inline detail::thread_move_t<unique_lock<Mutex> > move(detail::thread_move_t<unique_lock<Mutex> > x)
{
return x;
}
template<typename Mutex> template<typename Mutex>
class shared_lock class shared_lock
{ {
@@ -228,13 +251,13 @@ namespace boost
timed_lock(target_time); timed_lock(target_time);
} }
shared_lock(boost::move_t<shared_lock<Mutex> > other): shared_lock(detail::thread_move_t<shared_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked) m(other->m),is_locked(other->is_locked)
{ {
other->is_locked=false; other->is_locked=false;
} }
shared_lock(boost::move_t<unique_lock<Mutex> > other): shared_lock(detail::thread_move_t<unique_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked) m(other->m),is_locked(other->is_locked)
{ {
other->is_locked=false; other->is_locked=false;
@@ -244,7 +267,7 @@ namespace boost
} }
} }
shared_lock(boost::move_t<upgrade_lock<Mutex> > other): shared_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked) m(other->m),is_locked(other->is_locked)
{ {
other->is_locked=false; other->is_locked=false;
@@ -254,21 +277,32 @@ namespace boost
} }
} }
shared_lock& operator=(boost::move_t<shared_lock<Mutex> > other) operator detail::thread_move_t<shared_lock<Mutex> >()
{
return move();
}
detail::thread_move_t<shared_lock<Mutex> > move()
{
return detail::thread_move_t<shared_lock<Mutex> >(*this);
}
shared_lock& operator=(detail::thread_move_t<shared_lock<Mutex> > other)
{ {
shared_lock temp(other); shared_lock temp(other);
swap(temp); swap(temp);
return *this; return *this;
} }
shared_lock& operator=(boost::move_t<unique_lock<Mutex> > other) shared_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other)
{ {
shared_lock temp(other); shared_lock temp(other);
swap(temp); swap(temp);
return *this; return *this;
} }
shared_lock& operator=(boost::move_t<upgrade_lock<Mutex> > other) shared_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other)
{ {
shared_lock temp(other); shared_lock temp(other);
swap(temp); swap(temp);
@@ -341,6 +375,19 @@ namespace boost
}; };
template<typename Mutex>
inline detail::thread_move_t<shared_lock<Mutex> > move(shared_lock<Mutex> & x)
{
return x.move();
}
template<typename Mutex>
inline detail::thread_move_t<shared_lock<Mutex> > move(detail::thread_move_t<shared_lock<Mutex> > x)
{
return x;
}
template<typename Mutex> template<typename Mutex>
class upgrade_lock class upgrade_lock
{ {
@@ -364,13 +411,13 @@ namespace boost
lock(); lock();
} }
} }
upgrade_lock(boost::move_t<upgrade_lock<Mutex> > other): upgrade_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked) m(other->m),is_locked(other->is_locked)
{ {
other->is_locked=false; other->is_locked=false;
} }
upgrade_lock(boost::move_t<unique_lock<Mutex> > other): upgrade_lock(detail::thread_move_t<unique_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked) m(other->m),is_locked(other->is_locked)
{ {
other->is_locked=false; other->is_locked=false;
@@ -380,14 +427,25 @@ namespace boost
} }
} }
upgrade_lock& operator=(boost::move_t<upgrade_lock<Mutex> > other) operator detail::thread_move_t<upgrade_lock<Mutex> >()
{
return move();
}
detail::thread_move_t<upgrade_lock<Mutex> > move()
{
return detail::thread_move_t<upgrade_lock<Mutex> >(*this);
}
upgrade_lock& operator=(detail::thread_move_t<upgrade_lock<Mutex> > other)
{ {
upgrade_lock temp(other); upgrade_lock temp(other);
swap(temp); swap(temp);
return *this; return *this;
} }
upgrade_lock& operator=(boost::move_t<unique_lock<Mutex> > other) upgrade_lock& operator=(detail::thread_move_t<unique_lock<Mutex> > other)
{ {
upgrade_lock temp(other); upgrade_lock temp(other);
swap(temp); swap(temp);
@@ -452,8 +510,21 @@ namespace boost
friend class unique_lock<Mutex>; friend class unique_lock<Mutex>;
}; };
template<typename Mutex> template<typename Mutex>
unique_lock<Mutex>::unique_lock(boost::move_t<upgrade_lock<Mutex> > other): inline detail::thread_move_t<upgrade_lock<Mutex> > move(upgrade_lock<Mutex> & x)
{
return x.move();
}
template<typename Mutex>
inline detail::thread_move_t<upgrade_lock<Mutex> > move(detail::thread_move_t<upgrade_lock<Mutex> > x)
{
return x;
}
template<typename Mutex>
unique_lock<Mutex>::unique_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked) m(other->m),is_locked(other->is_locked)
{ {
other->is_locked=false; other->is_locked=false;
@@ -474,23 +545,23 @@ namespace boost
upgrade_to_unique_lock& operator=(upgrade_to_unique_lock&); upgrade_to_unique_lock& operator=(upgrade_to_unique_lock&);
public: public:
explicit upgrade_to_unique_lock(upgrade_lock<Mutex>& m_): explicit upgrade_to_unique_lock(upgrade_lock<Mutex>& m_):
source(&m_),exclusive(boost::move(*source)) source(&m_),exclusive(move(*source))
{} {}
~upgrade_to_unique_lock() ~upgrade_to_unique_lock()
{ {
if(source) if(source)
{ {
*source=boost::move(exclusive); *source=move(exclusive);
} }
} }
upgrade_to_unique_lock(boost::move_t<upgrade_to_unique_lock<Mutex> > other): upgrade_to_unique_lock(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other):
source(other->source),exclusive(boost::move(other->exclusive)) source(other->source),exclusive(move(other->exclusive))
{ {
other->source=0; other->source=0;
} }
upgrade_to_unique_lock& operator=(boost::move_t<upgrade_to_unique_lock<Mutex> > other) upgrade_to_unique_lock& operator=(detail::thread_move_t<upgrade_to_unique_lock<Mutex> > other)
{ {
upgrade_to_unique_lock temp(other); upgrade_to_unique_lock temp(other);
swap(temp); swap(temp);
@@ -515,6 +586,7 @@ namespace boost
return exclusive.owns_lock(); return exclusive.owns_lock();
} }
}; };
} }
#endif #endif

View File

@@ -143,7 +143,7 @@ namespace boost
while (!pred()) while (!pred())
{ {
if(!timed_wait(m, wait_until)) if(!timed_wait(m, wait_until))
return false; return pred();
} }
return true; return true;
} }

View File

@@ -41,7 +41,7 @@ namespace boost
while (!pred()) while (!pred())
{ {
if(!timed_wait(m, wait_until)) if(!timed_wait(m, wait_until))
return false; return pred();
} }
return true; return true;
} }

View File

@@ -40,44 +40,62 @@ namespace boost
{ {
class thread_id class thread_id
{ {
boost::optional<pthread_t> id; private:
detail::thread_data_ptr thread_data;
thread_id(detail::thread_data_ptr thread_data_):
thread_data(thread_data_)
{}
friend class boost::thread; friend class boost::thread;
friend thread_id this_thread::get_id(); friend thread_id this_thread::get_id();
thread_id(pthread_t id_):
id(id_)
{}
public: public:
thread_id() thread_id():
thread_data()
{} {}
bool operator==(const thread_id& y) const bool operator==(const thread_id& y) const
{ {
return (id && y.id) && (pthread_equal(*id,*y.id)!=0); return thread_data==y.thread_data;
} }
bool operator!=(const thread_id& y) const bool operator!=(const thread_id& y) const
{ {
return !(*this==y); return thread_data!=y.thread_data;
}
bool operator<(const thread_id& y) const
{
return thread_data<y.thread_data;
}
bool operator>(const thread_id& y) const
{
return y.thread_data<thread_data;
}
bool operator<=(const thread_id& y) const
{
return !(y.thread_data<thread_data);
}
bool operator>=(const thread_id& y) const
{
return !(thread_data<y.thread_data);
} }
template<class charT, class traits> template<class charT, class traits>
friend std::basic_ostream<charT, traits>& friend std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const thread_id& x) operator<<(std::basic_ostream<charT, traits>& os, const thread_id& x)
{ {
if(x.id) if(x.thread_data)
{ {
return os<<*x.id; return os<<x.thread_data;
} }
else else
{ {
return os<<"{Not-any-thread}"; return os<<"{Not-any-thread}";
} }
} }
}; };
} }
@@ -97,7 +115,7 @@ namespace boost
thread_data(F f_): thread_data(F f_):
f(f_) f(f_)
{} {}
thread_data(boost::move_t<F> f_): thread_data(detail::thread_move_t<F> f_):
f(f_) f(f_)
{} {}
@@ -108,13 +126,13 @@ namespace boost
}; };
mutable boost::mutex thread_info_mutex; mutable boost::mutex thread_info_mutex;
boost::shared_ptr<detail::thread_data_base> thread_info; detail::thread_data_ptr thread_info;
void start_thread(); void start_thread();
explicit thread(boost::shared_ptr<detail::thread_data_base> data); explicit thread(detail::thread_data_ptr data);
boost::shared_ptr<detail::thread_data_base> get_thread_info() const; detail::thread_data_ptr get_thread_info() const;
public: public:
thread(); thread();
@@ -127,16 +145,16 @@ namespace boost
start_thread(); start_thread();
} }
template <class F> template <class F>
thread(boost::move_t<F> f): thread(detail::thread_move_t<F> f):
thread_info(new thread_data<F>(f)) thread_info(new thread_data<F>(f))
{ {
start_thread(); start_thread();
} }
explicit thread(boost::move_t<thread> x); thread(detail::thread_move_t<thread> x);
thread& operator=(boost::move_t<thread> x); thread& operator=(detail::thread_move_t<thread> x);
operator boost::move_t<thread>(); operator detail::thread_move_t<thread>();
boost::move_t<thread> move(); detail::thread_move_t<thread> move();
void swap(thread& x); void swap(thread& x);
@@ -169,6 +187,17 @@ namespace boost
bool interruption_requested() const; bool interruption_requested() const;
}; };
inline detail::thread_move_t<thread> move(thread& x)
{
return x.move();
}
inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> x)
{
return x;
}
template<typename F> template<typename F>
struct thread::thread_data<boost::reference_wrapper<F> >: struct thread::thread_data<boost::reference_wrapper<F> >:
detail::thread_data_base detail::thread_data_base
@@ -208,22 +237,19 @@ namespace boost
~restore_interruption(); ~restore_interruption();
}; };
BOOST_THREAD_DECL inline thread::id get_id() BOOST_THREAD_DECL thread::id get_id();
{
return thread::id(pthread_self());
}
BOOST_THREAD_DECL void interruption_point(); BOOST_THREAD_DECL void interruption_point();
BOOST_THREAD_DECL bool interruption_enabled(); BOOST_THREAD_DECL bool interruption_enabled();
BOOST_THREAD_DECL bool interruption_requested(); BOOST_THREAD_DECL bool interruption_requested();
BOOST_THREAD_DECL inline void yield() inline void yield()
{ {
thread::yield(); thread::yield();
} }
template<typename TimeDuration> template<typename TimeDuration>
BOOST_THREAD_DECL inline void sleep(TimeDuration const& rel_time) inline void sleep(TimeDuration const& rel_time)
{ {
thread::sleep(get_system_time()+rel_time); thread::sleep(get_system_time()+rel_time);
} }

View File

@@ -7,6 +7,7 @@
#include <boost/thread/detail/config.hpp> #include <boost/thread/detail/config.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <pthread.h> #include <pthread.h>
@@ -21,10 +22,14 @@ namespace boost
{ {
struct thread_exit_callback_node; struct thread_exit_callback_node;
struct tss_data_node; struct tss_data_node;
struct thread_data_base;
typedef boost::shared_ptr<thread_data_base> thread_data_ptr;
struct thread_data_base struct thread_data_base:
enable_shared_from_this<thread_data_base>
{ {
boost::shared_ptr<thread_data_base> self; thread_data_ptr self;
pthread_t thread_handle; pthread_t thread_handle;
boost::mutex data_mutex; boost::mutex data_mutex;
boost::condition_variable done_condition; boost::condition_variable done_condition;

View File

@@ -6,6 +6,7 @@
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007 Anthony Williams // (C) Copyright 2007 Anthony Williams
#include <boost/thread/detail/config.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
namespace boost namespace boost

View File

@@ -56,6 +56,12 @@ namespace boost
long const current_thread_id=win32::GetCurrentThreadId(); long const current_thread_id=win32::GetCurrentThreadId();
return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target); return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target);
} }
template<typename Duration>
bool timed_lock(Duration const& timeout)
{
return timed_lock(get_system_time()+timeout);
}
long get_active_count() long get_active_count()
{ {
return mutex.get_active_count(); return mutex.get_active_count();

View File

@@ -104,6 +104,12 @@ namespace boost
return true; return true;
} }
template<typename Duration>
bool timed_lock(Duration const& timeout)
{
return timed_lock(get_system_time()+timeout);
}
long get_active_count() long get_active_count()
{ {
return ::boost::detail::interlocked_read_acquire(&active_count); return ::boost::detail::interlocked_read_acquire(&active_count);

View File

@@ -186,7 +186,7 @@ namespace boost
while (!pred()) while (!pred())
{ {
if(!do_wait(m, wait_until)) if(!do_wait(m, wait_until))
return false; return pred();
} }
return true; return true;
} }
@@ -276,6 +276,16 @@ namespace boost
return do_wait(m,wait_until); return do_wait(m,wait_until);
} }
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& wait_until)
{
return do_wait(m,system_time(wait_until));
}
template<typename duration_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration)
{
return do_wait(m,wait_duration.total_milliseconds());
}
template<typename predicate_type> template<typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until,predicate_type pred) bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until,predicate_type pred)
{ {
@@ -315,6 +325,18 @@ namespace boost
return do_wait(m,wait_until); return do_wait(m,wait_until);
} }
template<typename lock_type>
bool timed_wait(lock_type& m,boost::xtime const& wait_until)
{
return do_wait(m,system_time(wait_until));
}
template<typename lock_type,typename duration_type>
bool timed_wait(lock_type& m,duration_type const& wait_duration)
{
return do_wait(m,wait_duration.total_milliseconds());
}
template<typename lock_type,typename predicate_type> template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred) bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred)
{ {
@@ -330,7 +352,7 @@ namespace boost
template<typename lock_type,typename duration_type,typename predicate_type> template<typename lock_type,typename duration_type,typename predicate_type>
bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred) bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
{ {
return timed_wait(m,wait_duration.total_milliseconds(),pred); return do_wait(m,wait_duration.total_milliseconds(),pred);
} }
}; };

View File

@@ -94,9 +94,9 @@ namespace boost
detail::int_to_string(win32::GetCurrentProcessId(), mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2); detail::int_to_string(win32::GetCurrentProcessId(), mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2);
#ifdef BOOST_NO_ANSI_APIS #ifdef BOOST_NO_ANSI_APIS
return win32::CreateMutexW(NULL, 0, mutex_name); return win32::CreateMutexW(0, 0, mutex_name);
#else #else
return win32::CreateMutexA(NULL, 0, mutex_name); return win32::CreateMutexA(0, 0, mutex_name);
#endif #endif
} }

View File

@@ -57,12 +57,12 @@ namespace boost
{ {
if(old_state.exclusive_waiting) if(old_state.exclusive_waiting)
{ {
BOOST_VERIFY(detail::win32::ReleaseSemaphore(exclusive_sem,1,NULL)!=0); BOOST_VERIFY(detail::win32::ReleaseSemaphore(exclusive_sem,1,0)!=0);
} }
if(old_state.shared_waiting || old_state.exclusive_waiting) if(old_state.shared_waiting || old_state.exclusive_waiting)
{ {
BOOST_VERIFY(detail::win32::ReleaseSemaphore(unlock_sem,old_state.shared_waiting + (old_state.exclusive_waiting?1:0),NULL)!=0); BOOST_VERIFY(detail::win32::ReleaseSemaphore(unlock_sem,old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
} }
} }
@@ -215,7 +215,7 @@ namespace boost
{ {
if(old_state.upgrade) if(old_state.upgrade)
{ {
BOOST_VERIFY(detail::win32::ReleaseSemaphore(upgrade_sem,1,NULL)!=0); BOOST_VERIFY(detail::win32::ReleaseSemaphore(upgrade_sem,1,0)!=0);
} }
else else
{ {

View File

@@ -169,7 +169,7 @@ namespace boost
thread_data(F f_): thread_data(F f_):
f(f_) f(f_)
{} {}
thread_data(boost::move_t<F> f_): thread_data(detail::thread_move_t<F> f_):
f(f_) f(f_)
{} {}
@@ -200,16 +200,16 @@ namespace boost
start_thread(); start_thread();
} }
template <class F> template <class F>
explicit thread(boost::move_t<F> f): thread(detail::thread_move_t<F> f):
thread_info(detail::heap_new<thread_data<F> >(f)) thread_info(detail::heap_new<thread_data<F> >(f))
{ {
start_thread(); start_thread();
} }
thread(boost::move_t<thread> x); thread(detail::thread_move_t<thread> x);
thread& operator=(boost::move_t<thread> x); thread& operator=(detail::thread_move_t<thread> x);
operator boost::move_t<thread>(); operator detail::thread_move_t<thread>();
boost::move_t<thread> move(); detail::thread_move_t<thread> move();
void swap(thread& x); void swap(thread& x);
@@ -245,6 +245,16 @@ namespace boost
bool interruption_requested() const; bool interruption_requested() const;
}; };
inline detail::thread_move_t<thread> move(thread& x)
{
return x.move();
}
inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> x)
{
return x;
}
template<typename F> template<typename F>
struct thread::thread_data<boost::reference_wrapper<F> >: struct thread::thread_data<boost::reference_wrapper<F> >:
detail::thread_data_base detail::thread_data_base
@@ -354,7 +364,14 @@ namespace boost
friend std::basic_ostream<charT, traits>& friend std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const id& x) operator<<(std::basic_ostream<charT, traits>& os, const id& x)
{ {
return os<<x.thread_data; if(x.thread_data)
{
return os<<x.thread_data;
}
else
{
return os<<"{Not-any-thread}";
}
} }
void interrupt() void interrupt()

View File

@@ -181,9 +181,9 @@ namespace boost
inline handle create_anonymous_semaphore(long initial_count,long max_count) inline handle create_anonymous_semaphore(long initial_count,long max_count)
{ {
#if !defined(BOOST_NO_ANSI_APIS) #if !defined(BOOST_NO_ANSI_APIS)
handle const res=CreateSemaphoreA(NULL,initial_count,max_count,NULL); handle const res=CreateSemaphoreA(0,initial_count,max_count,0);
#else #else
handle const res=CreateSemaphoreW(NULL,initial_count,max_count,NULL); handle const res=CreateSemaphoreW(0,initial_count,max_count,0);
#endif #endif
if(!res) if(!res)
{ {

View File

@@ -1,6 +1,6 @@
<!-- Copyright (c) 2002-2003 William E. Kempf. <!-- Copyright (c) 2002-2003 William E. Kempf.
Subject to the Boost Software License, Version 1.0. Subject to the Boost Software License, Version 1.0.
(See accompanying file LICENSE-1.0 or http://www.boost.org/LICENSE-1.0) (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
--> -->
<html> <html>

View File

@@ -13,6 +13,14 @@
#include <boost/thread/locks.hpp> #include <boost/thread/locks.hpp>
#include <boost/thread/once.hpp> #include <boost/thread/once.hpp>
#include <boost/thread/tss.hpp> #include <boost/thread/tss.hpp>
#ifdef __linux__
#include <sys/sysinfo.h>
#elif defined(__APPLE__) || defined(__FreeBSD__)
#include <sys/types.h>
#include <sys/sysctl.h>
#elif defined(__sun)
#include <unistd.h>
#endif
#include "timeconv.inl" #include "timeconv.inl"
@@ -188,6 +196,37 @@ namespace boost
detach(); detach();
} }
thread::thread(detail::thread_move_t<thread> x)
{
lock_guard<mutex> lock(x->thread_info_mutex);
thread_info=x->thread_info;
x->thread_info.reset();
}
thread& thread::operator=(detail::thread_move_t<thread> x)
{
thread new_thread(x);
swap(new_thread);
return *this;
}
thread::operator detail::thread_move_t<thread>()
{
return move();
}
detail::thread_move_t<thread> thread::move()
{
detail::thread_move_t<thread> x(*this);
return x;
}
void thread::swap(thread& x)
{
thread_info.swap(x.thread_info);
}
bool thread::operator==(const thread& other) const bool thread::operator==(const thread& other) const
{ {
return get_id()==other.get_id(); return get_id()==other.get_id();
@@ -198,7 +237,7 @@ namespace boost
return !operator==(other); return !operator==(other);
} }
boost::shared_ptr<detail::thread_data_base> thread::get_thread_info() const detail::thread_data_ptr thread::get_thread_info() const
{ {
lock_guard<mutex> l(thread_info_mutex); lock_guard<mutex> l(thread_info_mutex);
return thread_info; return thread_info;
@@ -206,7 +245,7 @@ namespace boost
void thread::join() void thread::join()
{ {
boost::shared_ptr<detail::thread_data_base> const local_thread_info=get_thread_info(); detail::thread_data_ptr const local_thread_info=get_thread_info();
if(local_thread_info) if(local_thread_info)
{ {
bool do_join=false; bool do_join=false;
@@ -250,7 +289,7 @@ namespace boost
bool thread::timed_join(system_time const& wait_until) bool thread::timed_join(system_time const& wait_until)
{ {
boost::shared_ptr<detail::thread_data_base> const local_thread_info=get_thread_info(); detail::thread_data_ptr const local_thread_info=get_thread_info();
if(local_thread_info) if(local_thread_info)
{ {
bool do_join=false; bool do_join=false;
@@ -304,7 +343,7 @@ namespace boost
void thread::detach() void thread::detach()
{ {
boost::shared_ptr<detail::thread_data_base> local_thread_info; detail::thread_data_ptr local_thread_info;
{ {
lock_guard<mutex> l1(thread_info_mutex); lock_guard<mutex> l1(thread_info_mutex);
thread_info.swap(local_thread_info); thread_info.swap(local_thread_info);
@@ -377,15 +416,28 @@ namespace boost
unsigned thread::hardware_concurrency() unsigned thread::hardware_concurrency()
{ {
return 1; #if defined(PTW32_VERSION) || defined(__hpux)
return pthread_num_processors_np();
#elif defined(__linux__)
return get_nprocs();
#elif defined(__APPLE__) || defined(__FreeBSD__)
int count;
size_t size=sizeof(count);
return sysctlbyname("hw.ncpu",&count,&size,NULL,0)?0:count;
#elif defined(__sun)
int const count=sysconf(_SC_NPROCESSORS_ONLN);
return (count>0)?count:0;
#else
return 0;
#endif
} }
thread::id thread::get_id() const thread::id thread::get_id() const
{ {
boost::shared_ptr<detail::thread_data_base> local_thread_info=get_thread_info(); detail::thread_data_ptr const local_thread_info=get_thread_info();
if(local_thread_info) if(local_thread_info)
{ {
return id(local_thread_info->thread_handle); return id(local_thread_info);
} }
else else
{ {
@@ -395,7 +447,7 @@ namespace boost
void thread::interrupt() void thread::interrupt()
{ {
boost::shared_ptr<detail::thread_data_base> local_thread_info=get_thread_info(); detail::thread_data_ptr const local_thread_info=get_thread_info();
if(local_thread_info) if(local_thread_info)
{ {
lock_guard<mutex> lk(local_thread_info->data_mutex); lock_guard<mutex> lk(local_thread_info->data_mutex);
@@ -409,7 +461,7 @@ namespace boost
bool thread::interruption_requested() const bool thread::interruption_requested() const
{ {
boost::shared_ptr<detail::thread_data_base> local_thread_info=get_thread_info(); detail::thread_data_ptr const local_thread_info=get_thread_info();
if(local_thread_info) if(local_thread_info)
{ {
lock_guard<mutex> lk(local_thread_info->data_mutex); lock_guard<mutex> lk(local_thread_info->data_mutex);
@@ -424,6 +476,12 @@ namespace boost
namespace this_thread namespace this_thread
{ {
thread::id get_id()
{
boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data();
return thread::id(thread_info?thread_info->shared_from_this():detail::thread_data_ptr());
}
void interruption_point() void interruption_point()
{ {
boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data(); boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data();

View File

@@ -6,7 +6,7 @@
#include <boost/thread/detail/config.hpp> #include <boost/thread/detail/config.hpp>
#if defined(BOOST_HAS_WINTHREADS) && (defined(BOOST_THREAD_BUILD_LIB) || defined(BOOST_THREAD_TEST)) && (!defined(_MSC_VER) || defined(UNDER_CE)) #if defined(BOOST_HAS_WINTHREADS) && (defined(BOOST_THREAD_BUILD_LIB) || defined(BOOST_THREAD_TEST) || defined(UNDER_CE)) && (!defined(_MSC_VER) || defined(UNDER_CE))
/* /*
This file is a "null" implementation of tss cleanup; it's This file is a "null" implementation of tss cleanup; it's

View File

@@ -244,30 +244,28 @@ namespace boost
detach(); detach();
} }
thread::thread(boost::move_t<thread> x) thread::thread(detail::thread_move_t<thread> x)
{ {
{ lock_guard<mutex> lock(x->thread_info_mutex);
boost::mutex::scoped_lock l(x->thread_info_mutex); thread_info=x->thread_info;
thread_info=x->thread_info; x->thread_info=0;
}
x->release_handle();
} }
thread& thread::operator=(boost::move_t<thread> x) thread& thread::operator=(detail::thread_move_t<thread> x)
{ {
thread new_thread(x); thread new_thread(x);
swap(new_thread); swap(new_thread);
return *this; return *this;
} }
thread::operator boost::move_t<thread>() thread::operator detail::thread_move_t<thread>()
{ {
return move(); return move();
} }
boost::move_t<thread> thread::move() detail::thread_move_t<thread> thread::move()
{ {
boost::move_t<thread> x(*this); detail::thread_move_t<thread> x(*this);
return x; return x;
} }
@@ -317,7 +315,7 @@ namespace boost
void thread::release_handle() void thread::release_handle()
{ {
boost::mutex::scoped_lock l1(thread_info_mutex); lock_guard<mutex> l1(thread_info_mutex);
thread_info=0; thread_info=0;
} }
@@ -379,9 +377,9 @@ namespace boost
target_system_time.wYear=target_time.abs_time.date().year(); target_system_time.wYear=target_time.abs_time.date().year();
target_system_time.wMonth=target_time.abs_time.date().month(); target_system_time.wMonth=target_time.abs_time.date().month();
target_system_time.wDay=target_time.abs_time.date().day(); target_system_time.wDay=target_time.abs_time.date().day();
target_system_time.wHour=target_time.abs_time.time_of_day().hours(); target_system_time.wHour=(WORD)target_time.abs_time.time_of_day().hours();
target_system_time.wMinute=target_time.abs_time.time_of_day().minutes(); target_system_time.wMinute=(WORD)target_time.abs_time.time_of_day().minutes();
target_system_time.wSecond=target_time.abs_time.time_of_day().seconds(); target_system_time.wSecond=(WORD)target_time.abs_time.time_of_day().seconds();
if(!SystemTimeToFileTime(&target_system_time,((FILETIME*)&due_time))) if(!SystemTimeToFileTime(&target_system_time,((FILETIME*)&due_time)))
{ {

View File

@@ -35,6 +35,10 @@ rule thread-run ( sources )
{ {
test-suite "threads" test-suite "threads"
: [ thread-run test_thread.cpp ] : [ thread-run test_thread.cpp ]
[ thread-run test_thread_id.cpp ]
[ thread-run test_hardware_concurrency.cpp ]
[ thread-run test_thread_move.cpp ]
[ thread-run test_move_function.cpp ]
[ thread-run test_mutex.cpp ] [ thread-run test_mutex.cpp ]
[ thread-run test_condition_notify_one.cpp ] [ thread-run test_condition_notify_one.cpp ]
[ thread-run test_condition_timed_wait_times_out.cpp ] [ thread-run test_condition_timed_wait_times_out.cpp ]
@@ -45,6 +49,7 @@ rule thread-run ( sources )
[ thread-run test_xtime.cpp ] [ thread-run test_xtime.cpp ]
[ thread-run test_barrier.cpp ] [ thread-run test_barrier.cpp ]
[ thread-run test_shared_mutex.cpp ] [ thread-run test_shared_mutex.cpp ]
[ thread-run test_shared_mutex_part_2.cpp ]
[ thread-run test_lock_concept.cpp ] [ thread-run test_lock_concept.cpp ]
; ;
} }

View File

@@ -0,0 +1,62 @@
#ifndef SHARED_MUTEX_LOCKING_THREAD_HPP
#define SHARED_MUTEX_LOCKING_THREAD_HPP
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/shared_mutex.hpp>
template<typename lock_type>
class locking_thread
{
boost::shared_mutex& rw_mutex;
unsigned& unblocked_count;
boost::condition_variable& unblocked_condition;
unsigned& simultaneous_running_count;
unsigned& max_simultaneous_running;
boost::mutex& unblocked_count_mutex;
boost::mutex& finish_mutex;
public:
locking_thread(boost::shared_mutex& rw_mutex_,
unsigned& unblocked_count_,
boost::mutex& unblocked_count_mutex_,
boost::condition_variable& unblocked_condition_,
boost::mutex& finish_mutex_,
unsigned& simultaneous_running_count_,
unsigned& max_simultaneous_running_):
rw_mutex(rw_mutex_),
unblocked_count(unblocked_count_),
unblocked_condition(unblocked_condition_),
simultaneous_running_count(simultaneous_running_count_),
max_simultaneous_running(max_simultaneous_running_),
unblocked_count_mutex(unblocked_count_mutex_),
finish_mutex(finish_mutex_)
{}
void operator()()
{
// acquire lock
lock_type lock(rw_mutex);
// increment count to show we're unblocked
{
boost::mutex::scoped_lock ublock(unblocked_count_mutex);
++unblocked_count;
unblocked_condition.notify_one();
++simultaneous_running_count;
if(simultaneous_running_count>max_simultaneous_running)
{
max_simultaneous_running=simultaneous_running_count;
}
}
// wait to finish
boost::mutex::scoped_lock finish_lock(finish_mutex);
{
boost::mutex::scoped_lock ublock(unblocked_count_mutex);
--simultaneous_running_count;
}
}
};
#endif

View File

@@ -0,0 +1,21 @@
// Copyright (C) 2007 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/thread.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread/mutex.hpp>
void test_hardware_concurrency_is_non_zero()
{
BOOST_CHECK(boost::thread::hardware_concurrency()!=0);
}
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test_framework::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: hardware concurrency test suite");
test->add(BOOST_TEST_CASE(test_hardware_concurrency_is_non_zero));
return test;
}

View File

@@ -0,0 +1,54 @@
// Copyright (C) 2007 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/thread.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread/mutex.hpp>
void do_nothing()
{}
void test_thread_move_from_lvalue_on_construction()
{
boost::thread src(do_nothing);
boost::thread::id src_id=src.get_id();
boost::thread dest(boost::move(src));
boost::thread::id dest_id=dest.get_id();
BOOST_CHECK(src_id==dest_id);
BOOST_CHECK(src.get_id()==boost::thread::id());
dest.join();
}
void test_thread_move_from_rvalue_on_construction()
{
boost::thread x(boost::move(boost::thread(do_nothing)));
BOOST_CHECK(x.get_id()!=boost::thread::id());
x.join();
}
void test_unique_lock_move_from_lvalue_on_construction()
{
boost::mutex m;
boost::unique_lock<boost::mutex> l(m);
BOOST_CHECK(l.owns_lock());
BOOST_CHECK(l.mutex()==&m);
boost::unique_lock<boost::mutex> l2(boost::move(l));
BOOST_CHECK(!l.owns_lock());
BOOST_CHECK(!l.mutex());
BOOST_CHECK(l2.owns_lock());
BOOST_CHECK(l2.mutex()==&m);
}
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test_framework::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: thread move test suite");
test->add(BOOST_TEST_CASE(test_thread_move_from_lvalue_on_construction));
test->add(BOOST_TEST_CASE(test_thread_move_from_rvalue_on_construction));
test->add(BOOST_TEST_CASE(test_unique_lock_move_from_lvalue_on_construction));
return test;
}

View File

@@ -102,6 +102,11 @@ struct test_timedlock
typedef M mutex_type; typedef M mutex_type;
typedef typename M::scoped_timed_lock timed_lock_type; typedef typename M::scoped_timed_lock timed_lock_type;
static bool fake_predicate()
{
return false;
}
void operator()() void operator()()
{ {
mutex_type mutex; mutex_type mutex;
@@ -123,14 +128,17 @@ struct test_timedlock
BOOST_CHECK(lock ? true : false); BOOST_CHECK(lock ? true : false);
// Construct and initialize an xtime for a fast time out. // Construct and initialize an xtime for a fast time out.
boost::xtime xt = delay(0, 100); boost::system_time timeout = boost::get_system_time()+boost::posix_time::milliseconds(100);
// Test the lock and the mutex with condition variables. // Test the lock and the mutex with condition variables.
// No one is going to notify this condition variable. We expect to // No one is going to notify this condition variable. We expect to
// time out. // time out.
BOOST_CHECK(!condition.timed_wait(lock, xt)); BOOST_CHECK(!condition.timed_wait(lock, timeout, fake_predicate));
BOOST_CHECK(lock ? true : false); BOOST_CHECK(lock ? true : false);
BOOST_CHECK(in_range(xt));
boost::system_time now=boost::get_system_time();
boost::posix_time::milliseconds const timeout_resolution(20);
BOOST_CHECK((timeout-timeout_resolution)<now);
// Test the lock, unlock and timedlock methods. // Test the lock, unlock and timedlock methods.
lock.unlock(); lock.unlock();
@@ -142,6 +150,17 @@ struct test_timedlock
boost::system_time target = boost::get_system_time()+boost::posix_time::milliseconds(100); boost::system_time target = boost::get_system_time()+boost::posix_time::milliseconds(100);
BOOST_CHECK(lock.timed_lock(target)); BOOST_CHECK(lock.timed_lock(target));
BOOST_CHECK(lock ? true : false); BOOST_CHECK(lock ? true : false);
lock.unlock();
BOOST_CHECK(!lock);
BOOST_CHECK(mutex.timed_lock(boost::posix_time::milliseconds(100)));
mutex.unlock();
BOOST_CHECK(lock.timed_lock(boost::posix_time::milliseconds(100)));
BOOST_CHECK(lock ? true : false);
lock.unlock();
BOOST_CHECK(!lock);
} }
}; };

View File

@@ -5,13 +5,9 @@
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
#include <boost/thread/thread.hpp> #include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/xtime.hpp> #include <boost/thread/xtime.hpp>
#include "util.inl" #include "util.inl"
#include <iostream> #include "shared_mutex_locking_thread.hpp"
#include <boost/date_time/posix_time/posix_time_io.hpp>
#define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \ #define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \
{ \ { \
@@ -19,65 +15,6 @@
BOOST_CHECK_EQUAL(value,expected_value); \ BOOST_CHECK_EQUAL(value,expected_value); \
} }
namespace
{
template<typename lock_type>
class locking_thread
{
boost::shared_mutex& rw_mutex;
unsigned& unblocked_count;
unsigned& simultaneous_running_count;
unsigned& max_simultaneous_running;
boost::mutex& unblocked_count_mutex;
boost::condition_variable& unblocked_condition;
boost::mutex& finish_mutex;
public:
locking_thread(boost::shared_mutex& rw_mutex_,
unsigned& unblocked_count_,
boost::mutex& unblocked_count_mutex_,
boost::condition_variable& unblocked_condition_,
boost::mutex& finish_mutex_,
unsigned& simultaneous_running_count_,
unsigned& max_simultaneous_running_):
rw_mutex(rw_mutex_),
unblocked_count(unblocked_count_),
unblocked_condition(unblocked_condition_),
simultaneous_running_count(simultaneous_running_count_),
max_simultaneous_running(max_simultaneous_running_),
unblocked_count_mutex(unblocked_count_mutex_),
finish_mutex(finish_mutex_)
{}
void operator()()
{
// acquire lock
lock_type lock(rw_mutex);
// increment count to show we're unblocked
{
boost::mutex::scoped_lock ublock(unblocked_count_mutex);
++unblocked_count;
unblocked_condition.notify_one();
++simultaneous_running_count;
if(simultaneous_running_count>max_simultaneous_running)
{
max_simultaneous_running=simultaneous_running_count;
}
}
// wait to finish
boost::mutex::scoped_lock finish_lock(finish_mutex);
{
boost::mutex::scoped_lock ublock(unblocked_count_mutex);
--simultaneous_running_count;
}
}
};
}
void test_multiple_readers() void test_multiple_readers()
{ {
unsigned const number_of_threads=100; unsigned const number_of_threads=100;
@@ -328,250 +265,11 @@ void test_unlocking_last_reader_only_unblocks_one_writer()
throw; throw;
} }
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+writer_count); CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+writer_count);
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_readers,reader_count); CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_readers,reader_count);
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_writers,1u); CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_writers,1u);
} }
void test_only_one_upgrade_lock_permitted()
{
unsigned const number_of_threads=100;
boost::thread_group pool;
boost::shared_mutex rw_mutex;
unsigned unblocked_count=0;
unsigned simultaneous_running_count=0;
unsigned max_simultaneous_running=0;
boost::mutex unblocked_count_mutex;
boost::condition_variable unblocked_condition;
boost::mutex finish_mutex;
boost::mutex::scoped_lock finish_lock(finish_mutex);
try
{
for(unsigned i=0;i<number_of_threads;++i)
{
pool.create_thread(locking_thread<boost::upgrade_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
finish_mutex,simultaneous_running_count,max_simultaneous_running));
}
boost::thread::sleep(delay(1));
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U);
finish_lock.unlock();
pool.join_all();
}
catch(...)
{
pool.interrupt_all();
pool.join_all();
throw;
}
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads);
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u);
}
void test_can_lock_upgrade_if_currently_locked_shared()
{
boost::thread_group pool;
boost::shared_mutex rw_mutex;
unsigned unblocked_count=0;
unsigned simultaneous_running_count=0;
unsigned max_simultaneous_running=0;
boost::mutex unblocked_count_mutex;
boost::condition_variable unblocked_condition;
boost::mutex finish_mutex;
boost::mutex::scoped_lock finish_lock(finish_mutex);
unsigned const reader_count=100;
try
{
for(unsigned i=0;i<reader_count;++i)
{
pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
finish_mutex,simultaneous_running_count,max_simultaneous_running));
}
boost::thread::sleep(delay(1));
pool.create_thread(locking_thread<boost::upgrade_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
finish_mutex,simultaneous_running_count,max_simultaneous_running));
{
boost::mutex::scoped_lock lk(unblocked_count_mutex);
while(unblocked_count<(reader_count+1))
{
unblocked_condition.wait(lk);
}
}
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1);
finish_lock.unlock();
pool.join_all();
}
catch(...)
{
pool.interrupt_all();
pool.join_all();
throw;
}
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1);
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,reader_count+1);
}
namespace
{
class simple_writing_thread
{
boost::shared_mutex& rwm;
boost::mutex& finish_mutex;
boost::mutex& unblocked_mutex;
unsigned& unblocked_count;
public:
simple_writing_thread(boost::shared_mutex& rwm_,
boost::mutex& finish_mutex_,
boost::mutex& unblocked_mutex_,
unsigned& unblocked_count_):
rwm(rwm_),finish_mutex(finish_mutex_),
unblocked_mutex(unblocked_mutex_),unblocked_count(unblocked_count_)
{}
void operator()()
{
boost::unique_lock<boost::shared_mutex> lk(rwm);
{
boost::mutex::scoped_lock ulk(unblocked_mutex);
++unblocked_count;
}
boost::mutex::scoped_lock flk(finish_mutex);
}
};
}
void test_if_other_thread_has_write_lock_try_lock_shared_returns_false()
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
boost::mutex unblocked_mutex;
unsigned unblocked_count=0;
boost::mutex::scoped_lock finish_lock(finish_mutex);
boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
boost::this_thread::sleep(boost::posix_time::seconds(1));
CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
bool const try_succeeded=rw_mutex.try_lock_shared();
BOOST_CHECK(!try_succeeded);
if(try_succeeded)
{
rw_mutex.unlock_shared();
}
finish_lock.unlock();
writer.join();
}
void test_if_no_thread_has_lock_try_lock_shared_returns_true()
{
boost::shared_mutex rw_mutex;
bool const try_succeeded=rw_mutex.try_lock_shared();
BOOST_CHECK(try_succeeded);
if(try_succeeded)
{
rw_mutex.unlock_shared();
}
}
namespace
{
class simple_reading_thread
{
boost::shared_mutex& rwm;
boost::mutex& finish_mutex;
boost::mutex& unblocked_mutex;
unsigned& unblocked_count;
public:
simple_reading_thread(boost::shared_mutex& rwm_,
boost::mutex& finish_mutex_,
boost::mutex& unblocked_mutex_,
unsigned& unblocked_count_):
rwm(rwm_),finish_mutex(finish_mutex_),
unblocked_mutex(unblocked_mutex_),unblocked_count(unblocked_count_)
{}
void operator()()
{
boost::shared_lock<boost::shared_mutex> lk(rwm);
{
boost::mutex::scoped_lock ulk(unblocked_mutex);
++unblocked_count;
}
boost::mutex::scoped_lock flk(finish_mutex);
}
};
}
void test_if_other_thread_has_shared_lock_try_lock_shared_returns_true()
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
boost::mutex unblocked_mutex;
unsigned unblocked_count=0;
boost::mutex::scoped_lock finish_lock(finish_mutex);
boost::thread writer(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
boost::thread::sleep(delay(1));
CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
bool const try_succeeded=rw_mutex.try_lock_shared();
BOOST_CHECK(try_succeeded);
if(try_succeeded)
{
rw_mutex.unlock_shared();
}
finish_lock.unlock();
writer.join();
}
void test_timed_lock_shared_times_out_if_write_lock_held()
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
boost::mutex unblocked_mutex;
unsigned unblocked_count=0;
boost::mutex::scoped_lock finish_lock(finish_mutex);
boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
boost::thread::sleep(delay(1));
CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
boost::system_time const start=boost::get_system_time();
boost::system_time const timeout=start+boost::posix_time::milliseconds(2000);
bool const timed_lock_succeeded=rw_mutex.timed_lock_shared(timeout);
BOOST_CHECK(in_range(boost::get_xtime(timeout),1));
BOOST_CHECK(!timed_lock_succeeded);
if(timed_lock_succeeded)
{
rw_mutex.unlock_shared();
}
finish_lock.unlock();
writer.join();
}
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{ {
boost::unit_test_framework::test_suite* test = boost::unit_test_framework::test_suite* test =
@@ -582,12 +280,6 @@ boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
test->add(BOOST_TEST_CASE(&test_reader_blocks_writer)); test->add(BOOST_TEST_CASE(&test_reader_blocks_writer));
test->add(BOOST_TEST_CASE(&test_unlocking_writer_unblocks_all_readers)); test->add(BOOST_TEST_CASE(&test_unlocking_writer_unblocks_all_readers));
test->add(BOOST_TEST_CASE(&test_unlocking_last_reader_only_unblocks_one_writer)); test->add(BOOST_TEST_CASE(&test_unlocking_last_reader_only_unblocks_one_writer));
test->add(BOOST_TEST_CASE(&test_only_one_upgrade_lock_permitted));
test->add(BOOST_TEST_CASE(&test_can_lock_upgrade_if_currently_locked_shared));
test->add(BOOST_TEST_CASE(&test_if_other_thread_has_write_lock_try_lock_shared_returns_false));
test->add(BOOST_TEST_CASE(&test_if_no_thread_has_lock_try_lock_shared_returns_true));
test->add(BOOST_TEST_CASE(&test_if_other_thread_has_shared_lock_try_lock_shared_returns_true));
test->add(BOOST_TEST_CASE(&test_timed_lock_shared_times_out_if_write_lock_held));
return test; return test;
} }

View File

@@ -0,0 +1,271 @@
// (C) Copyright 2006-7 Anthony Williams
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/test/unit_test.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
#include "util.inl"
#include "shared_mutex_locking_thread.hpp"
#define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \
{ \
boost::mutex::scoped_lock lock(mutex_name); \
BOOST_CHECK_EQUAL(value,expected_value); \
}
void test_only_one_upgrade_lock_permitted()
{
unsigned const number_of_threads=100;
boost::thread_group pool;
boost::shared_mutex rw_mutex;
unsigned unblocked_count=0;
unsigned simultaneous_running_count=0;
unsigned max_simultaneous_running=0;
boost::mutex unblocked_count_mutex;
boost::condition_variable unblocked_condition;
boost::mutex finish_mutex;
boost::mutex::scoped_lock finish_lock(finish_mutex);
try
{
for(unsigned i=0;i<number_of_threads;++i)
{
pool.create_thread(locking_thread<boost::upgrade_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
finish_mutex,simultaneous_running_count,max_simultaneous_running));
}
boost::thread::sleep(delay(1));
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,1U);
finish_lock.unlock();
pool.join_all();
}
catch(...)
{
pool.interrupt_all();
pool.join_all();
throw;
}
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads);
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u);
}
void test_can_lock_upgrade_if_currently_locked_shared()
{
boost::thread_group pool;
boost::shared_mutex rw_mutex;
unsigned unblocked_count=0;
unsigned simultaneous_running_count=0;
unsigned max_simultaneous_running=0;
boost::mutex unblocked_count_mutex;
boost::condition_variable unblocked_condition;
boost::mutex finish_mutex;
boost::mutex::scoped_lock finish_lock(finish_mutex);
unsigned const reader_count=100;
try
{
for(unsigned i=0;i<reader_count;++i)
{
pool.create_thread(locking_thread<boost::shared_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
finish_mutex,simultaneous_running_count,max_simultaneous_running));
}
boost::thread::sleep(delay(1));
pool.create_thread(locking_thread<boost::upgrade_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,unblocked_condition,
finish_mutex,simultaneous_running_count,max_simultaneous_running));
{
boost::mutex::scoped_lock lk(unblocked_count_mutex);
while(unblocked_count<(reader_count+1))
{
unblocked_condition.wait(lk);
}
}
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1);
finish_lock.unlock();
pool.join_all();
}
catch(...)
{
pool.interrupt_all();
pool.join_all();
throw;
}
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1);
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,reader_count+1);
}
namespace
{
class simple_writing_thread
{
boost::shared_mutex& rwm;
boost::mutex& finish_mutex;
boost::mutex& unblocked_mutex;
unsigned& unblocked_count;
public:
simple_writing_thread(boost::shared_mutex& rwm_,
boost::mutex& finish_mutex_,
boost::mutex& unblocked_mutex_,
unsigned& unblocked_count_):
rwm(rwm_),finish_mutex(finish_mutex_),
unblocked_mutex(unblocked_mutex_),unblocked_count(unblocked_count_)
{}
void operator()()
{
boost::unique_lock<boost::shared_mutex> lk(rwm);
{
boost::mutex::scoped_lock ulk(unblocked_mutex);
++unblocked_count;
}
boost::mutex::scoped_lock flk(finish_mutex);
}
};
}
void test_if_other_thread_has_write_lock_try_lock_shared_returns_false()
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
boost::mutex unblocked_mutex;
unsigned unblocked_count=0;
boost::mutex::scoped_lock finish_lock(finish_mutex);
boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
boost::this_thread::sleep(boost::posix_time::seconds(1));
CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
bool const try_succeeded=rw_mutex.try_lock_shared();
BOOST_CHECK(!try_succeeded);
if(try_succeeded)
{
rw_mutex.unlock_shared();
}
finish_lock.unlock();
writer.join();
}
void test_if_no_thread_has_lock_try_lock_shared_returns_true()
{
boost::shared_mutex rw_mutex;
bool const try_succeeded=rw_mutex.try_lock_shared();
BOOST_CHECK(try_succeeded);
if(try_succeeded)
{
rw_mutex.unlock_shared();
}
}
namespace
{
class simple_reading_thread
{
boost::shared_mutex& rwm;
boost::mutex& finish_mutex;
boost::mutex& unblocked_mutex;
unsigned& unblocked_count;
public:
simple_reading_thread(boost::shared_mutex& rwm_,
boost::mutex& finish_mutex_,
boost::mutex& unblocked_mutex_,
unsigned& unblocked_count_):
rwm(rwm_),finish_mutex(finish_mutex_),
unblocked_mutex(unblocked_mutex_),unblocked_count(unblocked_count_)
{}
void operator()()
{
boost::shared_lock<boost::shared_mutex> lk(rwm);
{
boost::mutex::scoped_lock ulk(unblocked_mutex);
++unblocked_count;
}
boost::mutex::scoped_lock flk(finish_mutex);
}
};
}
void test_if_other_thread_has_shared_lock_try_lock_shared_returns_true()
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
boost::mutex unblocked_mutex;
unsigned unblocked_count=0;
boost::mutex::scoped_lock finish_lock(finish_mutex);
boost::thread writer(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
boost::thread::sleep(delay(1));
CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
bool const try_succeeded=rw_mutex.try_lock_shared();
BOOST_CHECK(try_succeeded);
if(try_succeeded)
{
rw_mutex.unlock_shared();
}
finish_lock.unlock();
writer.join();
}
void test_timed_lock_shared_times_out_if_write_lock_held()
{
boost::shared_mutex rw_mutex;
boost::mutex finish_mutex;
boost::mutex unblocked_mutex;
unsigned unblocked_count=0;
boost::mutex::scoped_lock finish_lock(finish_mutex);
boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
boost::thread::sleep(delay(1));
CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
boost::system_time const start=boost::get_system_time();
boost::system_time const timeout=start+boost::posix_time::milliseconds(2000);
boost::posix_time::milliseconds const timeout_resolution(20);
bool const timed_lock_succeeded=rw_mutex.timed_lock_shared(timeout);
BOOST_CHECK((timeout-timeout_resolution)<boost::get_system_time());
BOOST_CHECK(!timed_lock_succeeded);
if(timed_lock_succeeded)
{
rw_mutex.unlock_shared();
}
finish_lock.unlock();
writer.join();
}
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test_framework::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: shared_mutex test suite");
test->add(BOOST_TEST_CASE(&test_only_one_upgrade_lock_permitted));
test->add(BOOST_TEST_CASE(&test_can_lock_upgrade_if_currently_locked_shared));
test->add(BOOST_TEST_CASE(&test_if_other_thread_has_write_lock_try_lock_shared_returns_false));
test->add(BOOST_TEST_CASE(&test_if_no_thread_has_lock_try_lock_shared_returns_true));
test->add(BOOST_TEST_CASE(&test_if_other_thread_has_shared_lock_try_lock_shared_returns_true));
test->add(BOOST_TEST_CASE(&test_timed_lock_shared_times_out_if_write_lock_held));
return test;
}

149
test/test_thread_id.cpp Normal file
View File

@@ -0,0 +1,149 @@
// Copyright (C) 2007 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/thread.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/bind.hpp>
void do_nothing()
{}
void test_thread_id_for_default_constructed_thread_is_default_constructed_id()
{
boost::thread t;
BOOST_CHECK(t.get_id()==boost::thread::id());
}
void test_thread_id_for_running_thread_is_not_default_constructed_id()
{
boost::thread t(do_nothing);
BOOST_CHECK(t.get_id()!=boost::thread::id());
t.join();
}
void test_different_threads_have_different_ids()
{
boost::thread t(do_nothing);
boost::thread t2(do_nothing);
BOOST_CHECK(t.get_id()!=t2.get_id());
t.join();
t2.join();
}
void test_thread_ids_have_a_total_order()
{
boost::thread t(do_nothing);
boost::thread t2(do_nothing);
boost::thread t3(do_nothing);
BOOST_CHECK(t.get_id()!=t2.get_id());
BOOST_CHECK(t.get_id()!=t3.get_id());
BOOST_CHECK(t2.get_id()!=t3.get_id());
BOOST_CHECK((t.get_id()<t2.get_id()) != (t2.get_id()<t.get_id()));
BOOST_CHECK((t.get_id()<t3.get_id()) != (t3.get_id()<t.get_id()));
BOOST_CHECK((t2.get_id()<t3.get_id()) != (t3.get_id()<t2.get_id()));
BOOST_CHECK((t.get_id()>t2.get_id()) != (t2.get_id()>t.get_id()));
BOOST_CHECK((t.get_id()>t3.get_id()) != (t3.get_id()>t.get_id()));
BOOST_CHECK((t2.get_id()>t3.get_id()) != (t3.get_id()>t2.get_id()));
BOOST_CHECK((t.get_id()<t2.get_id()) == (t2.get_id()>t.get_id()));
BOOST_CHECK((t2.get_id()<t.get_id()) == (t.get_id()>t2.get_id()));
BOOST_CHECK((t.get_id()<t3.get_id()) == (t3.get_id()>t.get_id()));
BOOST_CHECK((t3.get_id()<t.get_id()) == (t.get_id()>t3.get_id()));
BOOST_CHECK((t2.get_id()<t3.get_id()) == (t3.get_id()>t2.get_id()));
BOOST_CHECK((t3.get_id()<t2.get_id()) == (t2.get_id()>t3.get_id()));
BOOST_CHECK((t.get_id()<t2.get_id()) == (t2.get_id()>=t.get_id()));
BOOST_CHECK((t2.get_id()<t.get_id()) == (t.get_id()>=t2.get_id()));
BOOST_CHECK((t.get_id()<t3.get_id()) == (t3.get_id()>=t.get_id()));
BOOST_CHECK((t3.get_id()<t.get_id()) == (t.get_id()>=t3.get_id()));
BOOST_CHECK((t2.get_id()<t3.get_id()) == (t3.get_id()>=t2.get_id()));
BOOST_CHECK((t3.get_id()<t2.get_id()) == (t2.get_id()>=t3.get_id()));
BOOST_CHECK((t.get_id()<=t2.get_id()) == (t2.get_id()>t.get_id()));
BOOST_CHECK((t2.get_id()<=t.get_id()) == (t.get_id()>t2.get_id()));
BOOST_CHECK((t.get_id()<=t3.get_id()) == (t3.get_id()>t.get_id()));
BOOST_CHECK((t3.get_id()<=t.get_id()) == (t.get_id()>t3.get_id()));
BOOST_CHECK((t2.get_id()<=t3.get_id()) == (t3.get_id()>t2.get_id()));
BOOST_CHECK((t3.get_id()<=t2.get_id()) == (t2.get_id()>t3.get_id()));
if((t.get_id()<t2.get_id()) && (t2.get_id()<t3.get_id()))
{
BOOST_CHECK(t.get_id()<t3.get_id());
}
else if((t.get_id()<t3.get_id()) && (t3.get_id()<t2.get_id()))
{
BOOST_CHECK(t.get_id()<t2.get_id());
}
else if((t2.get_id()<t3.get_id()) && (t3.get_id()<t.get_id()))
{
BOOST_CHECK(t2.get_id()<t.get_id());
}
else if((t2.get_id()<t.get_id()) && (t.get_id()<t3.get_id()))
{
BOOST_CHECK(t2.get_id()<t3.get_id());
}
else if((t3.get_id()<t.get_id()) && (t.get_id()<t2.get_id()))
{
BOOST_CHECK(t3.get_id()<t2.get_id());
}
else if((t3.get_id()<t2.get_id()) && (t2.get_id()<t.get_id()))
{
BOOST_CHECK(t3.get_id()<t.get_id());
}
else
{
BOOST_CHECK(false);
}
boost::thread::id default_id;
BOOST_CHECK(default_id < t.get_id());
BOOST_CHECK(default_id < t2.get_id());
BOOST_CHECK(default_id < t3.get_id());
BOOST_CHECK(default_id <= t.get_id());
BOOST_CHECK(default_id <= t2.get_id());
BOOST_CHECK(default_id <= t3.get_id());
BOOST_CHECK(!(default_id > t.get_id()));
BOOST_CHECK(!(default_id > t2.get_id()));
BOOST_CHECK(!(default_id > t3.get_id()));
BOOST_CHECK(!(default_id >= t.get_id()));
BOOST_CHECK(!(default_id >= t2.get_id()));
BOOST_CHECK(!(default_id >= t3.get_id()));
t.join();
t2.join();
t3.join();
}
void get_thread_id(boost::thread::id* id)
{
*id=boost::this_thread::get_id();
}
void test_thread_id_of_running_thread_returned_by_this_thread_get_id()
{
boost::thread::id id;
boost::thread t(boost::bind(get_thread_id,&id));
boost::thread::id t_id=t.get_id();
t.join();
BOOST_CHECK(id==t_id);
}
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test_framework::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: thread move test suite");
test->add(BOOST_TEST_CASE(test_thread_id_for_default_constructed_thread_is_default_constructed_id));
test->add(BOOST_TEST_CASE(test_thread_id_for_running_thread_is_not_default_constructed_id));
test->add(BOOST_TEST_CASE(test_different_threads_have_different_ids));
test->add(BOOST_TEST_CASE(test_thread_ids_have_a_total_order));
test->add(BOOST_TEST_CASE(test_thread_id_of_running_thread_returned_by_this_thread_get_id));
return test;
}

37
test/test_thread_move.cpp Normal file
View File

@@ -0,0 +1,37 @@
// Copyright (C) 2007 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/thread.hpp>
#include <boost/test/unit_test.hpp>
void do_nothing()
{}
void test_move_on_construction()
{
boost::thread x=boost::thread(do_nothing);
x.join();
}
boost::thread make_thread()
{
return boost::thread(do_nothing);
}
void test_move_from_function_return()
{
boost::thread x=make_thread();
x.join();
}
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test_framework::test_suite* test =
BOOST_TEST_SUITE("Boost.Threads: thread move test suite");
test->add(BOOST_TEST_CASE(test_move_on_construction));
test->add(BOOST_TEST_CASE(test_move_from_function_return));
return test;
}