|
Boost-Commit : |
From: anthony_at_[hidden]
Date: 2008-06-18 09:01:13
Author: anthonyw
Date: 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
New Revision: 46474
URL: http://svn.boost.org/trac/boost/changeset/46474
Log:
Merge of new boost.thread code along with required changes from boost.bind
Added:
branches/release/boost/bind/bind_mf2_cc.hpp
- copied unchanged from r46473, /trunk/boost/bind/bind_mf2_cc.hpp
branches/release/boost/thread/detail/thread.hpp
- copied, changed from r46368, /trunk/boost/thread/detail/thread.hpp
branches/release/boost/thread/detail/thread_heap_alloc.hpp
- copied unchanged from r46368, /trunk/boost/thread/detail/thread_heap_alloc.hpp
branches/release/boost/thread/pthread/thread_heap_alloc.hpp
- copied unchanged from r46368, /trunk/boost/thread/pthread/thread_heap_alloc.hpp
branches/release/boost/thread/tss.hpp
- copied unchanged from r46368, /trunk/boost/thread/tss.hpp
branches/release/boost/thread/win32/thread_data.hpp
- copied unchanged from r46368, /trunk/boost/thread/win32/thread_data.hpp
branches/release/libs/bind/test/bind_and_or_test.cpp
- copied unchanged from r46473, /trunk/libs/bind/test/bind_and_or_test.cpp
branches/release/libs/bind/test/bind_fn2_test.cpp
- copied unchanged from r46473, /trunk/libs/bind/test/bind_fn2_test.cpp
branches/release/libs/bind/test/bind_fnobj2_test.cpp
- copied unchanged from r46473, /trunk/libs/bind/test/bind_fnobj2_test.cpp
branches/release/libs/bind/test/bind_mf2_test.cpp
- copied unchanged from r46473, /trunk/libs/bind/test/bind_mf2_test.cpp
branches/release/libs/bind/test/ref_fn_test.cpp
- copied unchanged from r46473, /trunk/libs/bind/test/ref_fn_test.cpp
branches/release/libs/thread/doc/time.qbk
- copied unchanged from r46368, /trunk/libs/thread/doc/time.qbk
branches/release/libs/thread/test/no_implicit_assign_from_lvalue_thread.cpp
- copied unchanged from r46368, /trunk/libs/thread/test/no_implicit_assign_from_lvalue_thread.cpp
branches/release/libs/thread/test/no_implicit_move_from_lvalue_thread.cpp
- copied unchanged from r46368, /trunk/libs/thread/test/no_implicit_move_from_lvalue_thread.cpp
branches/release/libs/thread/test/test_generic_locks.cpp
- copied unchanged from r46368, /trunk/libs/thread/test/test_generic_locks.cpp
branches/release/libs/thread/test/test_shared_mutex_timed_locks.cpp
- copied unchanged from r46368, /trunk/libs/thread/test/test_shared_mutex_timed_locks.cpp
branches/release/libs/thread/test/test_thread_launching.cpp
- copied unchanged from r46368, /trunk/libs/thread/test/test_thread_launching.cpp
branches/release/libs/thread/test/test_thread_mf.cpp
- copied unchanged from r46368, /trunk/libs/thread/test/test_thread_mf.cpp
Removed:
branches/release/boost/thread/pthread/thread.hpp
branches/release/boost/thread/pthread/tss.hpp
branches/release/boost/thread/win32/thread.hpp
branches/release/boost/thread/win32/tss.hpp
Text files modified:
branches/release/boost/bind.hpp | 30 +
branches/release/boost/thread.hpp | 8
branches/release/boost/thread/barrier.hpp | 6
branches/release/boost/thread/detail/move.hpp | 27 +
branches/release/boost/thread/detail/thread.hpp | 4
branches/release/boost/thread/detail/tss_hooks.hpp | 6
branches/release/boost/thread/exceptions.hpp | 12
branches/release/boost/thread/locks.hpp | 628 +++++++++++++++++++++++++++++++++++++--
branches/release/boost/thread/once.hpp | 4
branches/release/boost/thread/pthread/condition_variable.hpp | 23 -
branches/release/boost/thread/pthread/condition_variable_fwd.hpp | 27 +
branches/release/boost/thread/pthread/mutex.hpp | 22
branches/release/boost/thread/pthread/once.hpp | 9
branches/release/boost/thread/pthread/pthread_mutex_scoped_lock.hpp | 6
branches/release/boost/thread/pthread/recursive_mutex.hpp | 25 +
branches/release/boost/thread/pthread/shared_mutex.hpp | 169 +++-------
branches/release/boost/thread/pthread/thread_data.hpp | 29 +
branches/release/boost/thread/pthread/timespec.hpp | 14
branches/release/boost/thread/thread.hpp | 9
branches/release/boost/thread/thread_time.hpp | 4
branches/release/boost/thread/win32/basic_recursive_mutex.hpp | 6
branches/release/boost/thread/win32/basic_timed_mutex.hpp | 71 ++--
branches/release/boost/thread/win32/condition_variable.hpp | 304 +++++++++++--------
branches/release/boost/thread/win32/interlocked_read.hpp | 9
branches/release/boost/thread/win32/mutex.hpp | 8
branches/release/boost/thread/win32/once.hpp | 4
branches/release/boost/thread/win32/recursive_mutex.hpp | 7
branches/release/boost/thread/win32/shared_mutex.hpp | 32 +
branches/release/boost/thread/win32/thread_heap_alloc.hpp | 243 ++++++++++++++
branches/release/boost/thread/win32/thread_primitives.hpp | 116 +++++++
branches/release/boost/thread/xtime.hpp | 8
branches/release/boost/utility/addressof.hpp | 39 +-
branches/release/libs/bind/bind.html | 99 ++++-
branches/release/libs/bind/test/Jamfile.v2 | 5
branches/release/libs/bind/test/bind_lookup_problem_test.cpp | 2
branches/release/libs/thread/doc/changes.qbk | 7
branches/release/libs/thread/doc/mutex_concepts.qbk | 30 +
branches/release/libs/thread/doc/mutexes.qbk | 77 ++++
branches/release/libs/thread/doc/thread.qbk | 2
branches/release/libs/thread/doc/thread_ref.qbk | 77 ++++
branches/release/libs/thread/example/condition.cpp | 12
branches/release/libs/thread/src/pthread/thread.cpp | 299 +++++++++----------
branches/release/libs/thread/src/tss_null.cpp | 2
branches/release/libs/thread/src/win32/thread.cpp | 86 +----
branches/release/libs/thread/test/Jamfile.v2 | 20
branches/release/libs/thread/test/shared_mutex_locking_thread.hpp | 62 +++
branches/release/libs/thread/test/test_condition_notify_all.cpp | 42 ++
branches/release/libs/thread/test/test_condition_notify_one.cpp | 42 ++
branches/release/libs/thread/test/test_lock_concept.cpp | 106 ++++++
branches/release/libs/thread/test/test_move_function.cpp | 74 ++++
branches/release/libs/thread/test/test_shared_mutex_part_2.cpp | 96 ------
branches/release/libs/thread/test/test_thread.cpp | 18 +
branches/release/libs/thread/test/test_tss.cpp | 48 +++
53 files changed, 2339 insertions(+), 776 deletions(-)
Modified: branches/release/boost/bind.hpp
==============================================================================
--- branches/release/boost/bind.hpp (original)
+++ branches/release/boost/bind.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -248,6 +248,9 @@
}
};
+struct logical_and;
+struct logical_or;
+
template< class A1, class A2 > class list2: private storage2< A1, A2 >
{
private:
@@ -294,6 +297,26 @@
unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]);
}
+ template<class A> bool operator()( type<bool>, logical_and & /*f*/, A & a, int )
+ {
+ return a[ base_type::a1_ ] && a[ base_type::a2_ ];
+ }
+
+ template<class A> bool operator()( type<bool>, logical_and const & /*f*/, A & a, int ) const
+ {
+ return a[ base_type::a1_ ] && a[ base_type::a2_ ];
+ }
+
+ template<class A> bool operator()( type<bool>, logical_or & /*f*/, A & a, int )
+ {
+ return a[ base_type::a1_ ] || a[ base_type::a2_ ];
+ }
+
+ template<class A> bool operator()( type<bool>, logical_or const & /*f*/, A & a, int ) const
+ {
+ return a[ base_type::a1_ ] || a[ base_type::a2_ ];
+ }
+
template<class V> void accept(V & v) const
{
base_type::accept(v);
@@ -1158,6 +1181,9 @@
BOOST_BIND_OPERATOR( >, greater )
BOOST_BIND_OPERATOR( >=, greater_equal )
+BOOST_BIND_OPERATOR( &&, logical_and )
+BOOST_BIND_OPERATOR( ||, logical_or )
+
#undef BOOST_BIND_OPERATOR
#if defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3)
@@ -1542,6 +1568,7 @@
#define BOOST_BIND_MF_CC
#include <boost/bind/bind_mf_cc.hpp>
+#include <boost/bind/bind_mf2_cc.hpp>
#undef BOOST_BIND_MF_NAME
#undef BOOST_BIND_MF_CC
@@ -1552,6 +1579,7 @@
#define BOOST_BIND_MF_CC __cdecl
#include <boost/bind/bind_mf_cc.hpp>
+#include <boost/bind/bind_mf2_cc.hpp>
#undef BOOST_BIND_MF_NAME
#undef BOOST_BIND_MF_CC
@@ -1564,6 +1592,7 @@
#define BOOST_BIND_MF_CC __stdcall
#include <boost/bind/bind_mf_cc.hpp>
+#include <boost/bind/bind_mf2_cc.hpp>
#undef BOOST_BIND_MF_NAME
#undef BOOST_BIND_MF_CC
@@ -1576,6 +1605,7 @@
#define BOOST_BIND_MF_CC __fastcall
#include <boost/bind/bind_mf_cc.hpp>
+#include <boost/bind/bind_mf2_cc.hpp>
#undef BOOST_BIND_MF_NAME
#undef BOOST_BIND_MF_CC
Modified: branches/release/boost/thread.hpp
==============================================================================
--- branches/release/boost/thread.hpp (original)
+++ branches/release/boost/thread.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -1,5 +1,6 @@
// Copyright (C) 2001-2003
// William E. Kempf
+// (C) Copyright 2008 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)
@@ -10,12 +11,15 @@
#define BOOST_THREAD_WEK01082003_HPP
#include <boost/thread/thread.hpp>
-#include <boost/thread/condition.hpp>
+#include <boost/thread/condition_variable.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/once.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/tss.hpp>
-#include <boost/thread/xtime.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/barrier.hpp>
#endif
Modified: branches/release/boost/thread/barrier.hpp
==============================================================================
--- branches/release/boost/thread/barrier.hpp (original)
+++ branches/release/boost/thread/barrier.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -1,6 +1,6 @@
// Copyright (C) 2002-2003
// David Moore, William E. Kempf
-// Copyright (C) 2007 Anthony Williams
+// Copyright (C) 2007-8 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)
@@ -15,6 +15,8 @@
#include <string>
#include <stdexcept>
+#include <boost/config/abi_prefix.hpp>
+
namespace boost
{
@@ -56,4 +58,6 @@
} // namespace boost
+#include <boost/config/abi_suffix.hpp>
+
#endif
Modified: branches/release/boost/thread/detail/move.hpp
==============================================================================
--- branches/release/boost/thread/detail/move.hpp (original)
+++ branches/release/boost/thread/detail/move.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -1,11 +1,16 @@
// 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)
-// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2007-8 Anthony Williams
#ifndef BOOST_THREAD_MOVE_HPP
#define BOOST_THREAD_MOVE_HPP
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
namespace boost
{
namespace detail
@@ -14,10 +19,15 @@
struct thread_move_t
{
T& t;
- thread_move_t(T& t_):
+ explicit thread_move_t(T& t_):
t(t_)
{}
+ T& operator*() const
+ {
+ return t;
+ }
+
T* operator->() const
{
return &t;
@@ -26,8 +36,21 @@
void operator=(thread_move_t&);
};
}
+
+ template<typename T>
+ typename enable_if<boost::is_convertible<T&,detail::thread_move_t<T> >, detail::thread_move_t<T> >::type move(T& t)
+ {
+ return t;
+ }
+
+ template<typename T>
+ detail::thread_move_t<T> move(detail::thread_move_t<T> t)
+ {
+ return t;
+ }
}
+#include <boost/config/abi_suffix.hpp>
#endif
Copied: branches/release/boost/thread/detail/thread.hpp (from r46368, /trunk/boost/thread/detail/thread.hpp)
==============================================================================
--- /trunk/boost/thread/detail/thread.hpp (original)
+++ branches/release/boost/thread/detail/thread.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -163,7 +163,7 @@
thread& operator=(thread&& other)
{
thread_info=other.thread_info;
- other.thread_info.reset();
+ other.thread_info.reset((detail::thread_data_base*)0);
return *this;
}
@@ -190,7 +190,7 @@
thread(detail::thread_move_t<thread> x)
{
thread_info=x->thread_info;
- x->thread_info.reset();
+ x->thread_info.reset((detail::thread_data_base*)0);
}
thread& operator=(detail::thread_move_t<thread> x)
Modified: branches/release/boost/thread/detail/tss_hooks.hpp
==============================================================================
--- branches/release/boost/thread/detail/tss_hooks.hpp (original)
+++ branches/release/boost/thread/detail/tss_hooks.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -8,6 +8,8 @@
#include <boost/thread/detail/config.hpp>
+#include <boost/config/abi_prefix.hpp>
+
#if defined(BOOST_HAS_WINTHREADS)
typedef void (__cdecl *thread_exit_handler)(void);
@@ -59,7 +61,7 @@
//a method for doing so has been discovered.
//May be omitted; may be called multiple times.
- extern "C" BOOST_THREAD_DECL void on_thread_exit(void);
+ extern "C" BOOST_THREAD_DECL void __cdecl on_thread_exit(void);
//Function to be called just be fore a thread ends
//in an exe or dll that uses Boost.Threads.
//Must be called in the context of the thread
@@ -75,4 +77,6 @@
#endif //defined(BOOST_HAS_WINTHREADS)
+#include <boost/config/abi_suffix.hpp>
+
#endif //!defined(BOOST_TLS_HOOKS_HPP)
Modified: branches/release/boost/thread/exceptions.hpp
==============================================================================
--- branches/release/boost/thread/exceptions.hpp (original)
+++ branches/release/boost/thread/exceptions.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -1,6 +1,6 @@
// Copyright (C) 2001-2003
// William E. Kempf
-// Copyright (C) 2007 Anthony Williams
+// Copyright (C) 2007-8 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)
@@ -19,7 +19,13 @@
#include <string>
#include <stdexcept>
-namespace boost {
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
+
+ class BOOST_THREAD_DECL thread_interrupted
+ {};
class BOOST_THREAD_DECL thread_exception : public std::exception
{
@@ -99,6 +105,8 @@
} // namespace boost
+#include <boost/config/abi_suffix.hpp>
+
#endif // BOOST_THREAD_CONFIG_PDM070801_H
// Change log:
Modified: branches/release/boost/thread/locks.hpp
==============================================================================
--- branches/release/boost/thread/locks.hpp (original)
+++ branches/release/boost/thread/locks.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -8,10 +8,77 @@
#include <boost/thread/exceptions.hpp>
#include <boost/thread/detail/move.hpp>
#include <algorithm>
+#include <iterator>
#include <boost/thread/thread_time.hpp>
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/config/abi_prefix.hpp>
namespace boost
{
+ namespace detail
+ {
+ template<typename T>
+ struct has_member_lock
+ {
+ typedef char true_type;
+ struct false_type
+ {
+ true_type dummy[2];
+ };
+
+ template<typename U>
+ static true_type has_member(U*,void (U::*dummy)()=&U::lock);
+ static false_type has_member(void*);
+
+ BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_lock<T>::has_member((T*)NULL))==sizeof(true_type));
+ };
+
+ template<typename T>
+ struct has_member_unlock
+ {
+ typedef char true_type;
+ struct false_type
+ {
+ true_type dummy[2];
+ };
+
+ template<typename U>
+ static true_type has_member(U*,void (U::*dummy)()=&U::unlock);
+ static false_type has_member(void*);
+
+ BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_unlock<T>::has_member((T*)NULL))==sizeof(true_type));
+ };
+
+ template<typename T>
+ struct has_member_try_lock
+ {
+ typedef char true_type;
+ struct false_type
+ {
+ true_type dummy[2];
+ };
+
+ template<typename U>
+ static true_type has_member(U*,bool (U::*dummy)()=&U::try_lock);
+ static false_type has_member(void*);
+
+ BOOST_STATIC_CONSTANT(bool, value=sizeof(has_member_try_lock<T>::has_member((T*)NULL))==sizeof(true_type));
+ };
+
+ }
+
+
+ template<typename T>
+ struct is_mutex_type
+ {
+ BOOST_STATIC_CONSTANT(bool, value = detail::has_member_lock<T>::value &&
+ detail::has_member_unlock<T>::value &&
+ detail::has_member_try_lock<T>::value);
+
+ };
+
+
struct defer_lock_t
{};
struct try_to_lock_t
@@ -62,6 +129,10 @@
explicit unique_lock(unique_lock&);
unique_lock& operator=(unique_lock&);
public:
+ unique_lock():
+ m(0),is_locked(false)
+ {}
+
explicit unique_lock(Mutex& m_):
m(&m_),is_locked(false)
{
@@ -205,15 +276,9 @@
};
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)
+ void swap(unique_lock<Mutex>& lhs,unique_lock<Mutex>& rhs)
{
- return x;
+ lhs.swap(rhs);
}
template<typename Mutex>
@@ -226,6 +291,10 @@
explicit shared_lock(shared_lock&);
shared_lock& operator=(shared_lock&);
public:
+ shared_lock():
+ m(0),is_locked(false)
+ {}
+
explicit shared_lock(Mutex& m_):
m(&m_),is_locked(false)
{
@@ -252,26 +321,29 @@
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
+ other->m=0;
}
shared_lock(detail::thread_move_t<unique_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
- other->is_locked=false;
if(is_locked)
{
m->unlock_and_lock_shared();
}
+ other->is_locked=false;
+ other->m=0;
}
shared_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
- other->is_locked=false;
if(is_locked)
{
m->unlock_upgrade_and_lock_shared();
}
+ other->is_locked=false;
+ other->m=0;
}
operator detail::thread_move_t<shared_lock<Mutex> >()
@@ -373,19 +445,6 @@
};
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>
class upgrade_lock
{
protected:
@@ -395,33 +454,42 @@
explicit upgrade_lock(upgrade_lock&);
upgrade_lock& operator=(upgrade_lock&);
public:
+ upgrade_lock():
+ m(0),is_locked(false)
+ {}
+
explicit upgrade_lock(Mutex& m_):
m(&m_),is_locked(false)
{
lock();
}
- upgrade_lock(Mutex& m_,bool do_lock):
+ upgrade_lock(Mutex& m_,adopt_lock_t):
+ m(&m_),is_locked(true)
+ {}
+ upgrade_lock(Mutex& m_,defer_lock_t):
+ m(&m_),is_locked(false)
+ {}
+ upgrade_lock(Mutex& m_,try_to_lock_t):
m(&m_),is_locked(false)
{
- if(do_lock)
- {
- lock();
- }
+ try_lock();
}
upgrade_lock(detail::thread_move_t<upgrade_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
other->is_locked=false;
+ other->m=0;
}
upgrade_lock(detail::thread_move_t<unique_lock<Mutex> > other):
m(other->m),is_locked(other->is_locked)
{
- other->is_locked=false;
if(is_locked)
{
m->unlock_and_lock_upgrade();
}
+ other->is_locked=false;
+ other->m=0;
}
operator detail::thread_move_t<upgrade_lock<Mutex> >()
@@ -509,18 +577,6 @@
template<typename Mutex>
- 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)
{
@@ -584,6 +640,496 @@
}
};
+ namespace detail
+ {
+ template<typename Mutex>
+ class try_lock_wrapper:
+ private unique_lock<Mutex>
+ {
+ typedef unique_lock<Mutex> base;
+ public:
+ try_lock_wrapper()
+ {}
+
+ explicit try_lock_wrapper(Mutex& m):
+ base(m,try_to_lock)
+ {}
+
+ try_lock_wrapper(Mutex& m_,adopt_lock_t):
+ base(m_,adopt_lock)
+ {}
+ try_lock_wrapper(Mutex& m_,defer_lock_t):
+ base(m_,defer_lock)
+ {}
+ try_lock_wrapper(Mutex& m_,try_to_lock_t):
+ base(m_,try_to_lock)
+ {}
+ try_lock_wrapper(detail::thread_move_t<try_lock_wrapper<Mutex> > other):
+ base(detail::thread_move_t<base>(*other))
+ {}
+
+ operator detail::thread_move_t<try_lock_wrapper<Mutex> >()
+ {
+ return move();
+ }
+
+ detail::thread_move_t<try_lock_wrapper<Mutex> > move()
+ {
+ return detail::thread_move_t<try_lock_wrapper<Mutex> >(*this);
+ }
+
+ try_lock_wrapper& operator=(detail::thread_move_t<try_lock_wrapper<Mutex> > other)
+ {
+ try_lock_wrapper temp(other);
+ swap(temp);
+ return *this;
+ }
+
+ void swap(try_lock_wrapper& other)
+ {
+ base::swap(other);
+ }
+ void swap(detail::thread_move_t<try_lock_wrapper<Mutex> > other)
+ {
+ base::swap(*other);
+ }
+
+ void lock()
+ {
+ base::lock();
+ }
+ bool try_lock()
+ {
+ return base::try_lock();
+ }
+ void unlock()
+ {
+ base::unlock();
+ }
+ bool owns_lock() const
+ {
+ return base::owns_lock();
+ }
+ Mutex* mutex() const
+ {
+ return base::mutex();
+ }
+ Mutex* release()
+ {
+ return base::release();
+ }
+ bool operator!() const
+ {
+ return !this->owns_lock();
+ }
+
+ typedef typename base::bool_type bool_type;
+ operator bool_type() const
+ {
+ return static_cast<base const&>(*this);
+ }
+ };
+
+ template<typename Mutex>
+ void swap(try_lock_wrapper<Mutex>& lhs,try_lock_wrapper<Mutex>& rhs)
+ {
+ lhs.swap(rhs);
+ }
+
+ template<typename MutexType1,typename MutexType2>
+ unsigned try_lock_internal(MutexType1& m1,MutexType2& m2)
+ {
+ boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock);
+ if(!l1)
+ {
+ return 1;
+ }
+ if(!m2.try_lock())
+ {
+ return 2;
+ }
+ l1.release();
+ return 0;
+ }
+
+ template<typename MutexType1,typename MutexType2,typename MutexType3>
+ unsigned try_lock_internal(MutexType1& m1,MutexType2& m2,MutexType3& m3)
+ {
+ boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock);
+ if(!l1)
+ {
+ return 1;
+ }
+ if(unsigned const failed_lock=try_lock_internal(m2,m3))
+ {
+ return failed_lock+1;
+ }
+ l1.release();
+ return 0;
+ }
+
+
+ template<typename MutexType1,typename MutexType2,typename MutexType3,
+ typename MutexType4>
+ unsigned try_lock_internal(MutexType1& m1,MutexType2& m2,MutexType3& m3,
+ MutexType4& m4)
+ {
+ boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock);
+ if(!l1)
+ {
+ return 1;
+ }
+ if(unsigned const failed_lock=try_lock_internal(m2,m3,m4))
+ {
+ return failed_lock+1;
+ }
+ l1.release();
+ return 0;
+ }
+
+ template<typename MutexType1,typename MutexType2,typename MutexType3,
+ typename MutexType4,typename MutexType5>
+ unsigned try_lock_internal(MutexType1& m1,MutexType2& m2,MutexType3& m3,
+ MutexType4& m4,MutexType5& m5)
+ {
+ boost::unique_lock<MutexType1> l1(m1,boost::try_to_lock);
+ if(!l1)
+ {
+ return 1;
+ }
+ if(unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5))
+ {
+ return failed_lock+1;
+ }
+ l1.release();
+ return 0;
+ }
+
+
+ template<typename MutexType1,typename MutexType2>
+ unsigned lock_helper(MutexType1& m1,MutexType2& m2)
+ {
+ boost::unique_lock<MutexType1> l1(m1);
+ if(!m2.try_lock())
+ {
+ return 1;
+ }
+ l1.release();
+ return 0;
+ }
+
+ template<typename MutexType1,typename MutexType2,typename MutexType3>
+ unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3)
+ {
+ boost::unique_lock<MutexType1> l1(m1);
+ if(unsigned const failed_lock=try_lock_internal(m2,m3))
+ {
+ return failed_lock;
+ }
+ l1.release();
+ return 0;
+ }
+
+ template<typename MutexType1,typename MutexType2,typename MutexType3,
+ typename MutexType4>
+ unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3,
+ MutexType4& m4)
+ {
+ boost::unique_lock<MutexType1> l1(m1);
+ if(unsigned const failed_lock=try_lock_internal(m2,m3,m4))
+ {
+ return failed_lock;
+ }
+ l1.release();
+ return 0;
+ }
+
+ template<typename MutexType1,typename MutexType2,typename MutexType3,
+ typename MutexType4,typename MutexType5>
+ unsigned lock_helper(MutexType1& m1,MutexType2& m2,MutexType3& m3,
+ MutexType4& m4,MutexType5& m5)
+ {
+ boost::unique_lock<MutexType1> l1(m1);
+ if(unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5))
+ {
+ return failed_lock;
+ }
+ l1.release();
+ return 0;
+ }
+ }
+
+ template<typename MutexType1,typename MutexType2>
+ typename enable_if<is_mutex_type<MutexType1>, void>::type lock(MutexType1& m1,MutexType2& m2)
+ {
+ unsigned const lock_count=2;
+ unsigned lock_first=0;
+ while(true)
+ {
+ switch(lock_first)
+ {
+ case 0:
+ lock_first=detail::lock_helper(m1,m2);
+ if(!lock_first)
+ return;
+ break;
+ case 1:
+ lock_first=detail::lock_helper(m2,m1);
+ if(!lock_first)
+ return;
+ lock_first=(lock_first+1)%lock_count;
+ break;
+ }
+ }
+ }
+
+ template<typename MutexType1,typename MutexType2,typename MutexType3>
+ void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3)
+ {
+ unsigned const lock_count=3;
+ unsigned lock_first=0;
+ while(true)
+ {
+ switch(lock_first)
+ {
+ case 0:
+ lock_first=detail::lock_helper(m1,m2,m3);
+ if(!lock_first)
+ return;
+ break;
+ case 1:
+ lock_first=detail::lock_helper(m2,m3,m1);
+ if(!lock_first)
+ return;
+ lock_first=(lock_first+1)%lock_count;
+ break;
+ case 2:
+ lock_first=detail::lock_helper(m3,m1,m2);
+ if(!lock_first)
+ return;
+ lock_first=(lock_first+2)%lock_count;
+ break;
+ }
+ }
+ }
+
+ template<typename MutexType1,typename MutexType2,typename MutexType3,
+ typename MutexType4>
+ void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,
+ MutexType4& m4)
+ {
+ unsigned const lock_count=4;
+ unsigned lock_first=0;
+ while(true)
+ {
+ switch(lock_first)
+ {
+ case 0:
+ lock_first=detail::lock_helper(m1,m2,m3,m4);
+ if(!lock_first)
+ return;
+ break;
+ case 1:
+ lock_first=detail::lock_helper(m2,m3,m4,m1);
+ if(!lock_first)
+ return;
+ lock_first=(lock_first+1)%lock_count;
+ break;
+ case 2:
+ lock_first=detail::lock_helper(m3,m4,m1,m2);
+ if(!lock_first)
+ return;
+ lock_first=(lock_first+2)%lock_count;
+ break;
+ case 3:
+ lock_first=detail::lock_helper(m4,m1,m2,m3);
+ if(!lock_first)
+ return;
+ lock_first=(lock_first+3)%lock_count;
+ break;
+ }
+ }
+ }
+
+ template<typename MutexType1,typename MutexType2,typename MutexType3,
+ typename MutexType4,typename MutexType5>
+ void lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,
+ MutexType4& m4,MutexType5& m5)
+ {
+ unsigned const lock_count=5;
+ unsigned lock_first=0;
+ while(true)
+ {
+ switch(lock_first)
+ {
+ case 0:
+ lock_first=detail::lock_helper(m1,m2,m3,m4,m5);
+ if(!lock_first)
+ return;
+ break;
+ case 1:
+ lock_first=detail::lock_helper(m2,m3,m4,m5,m1);
+ if(!lock_first)
+ return;
+ lock_first=(lock_first+1)%lock_count;
+ break;
+ case 2:
+ lock_first=detail::lock_helper(m3,m4,m5,m1,m2);
+ if(!lock_first)
+ return;
+ lock_first=(lock_first+2)%lock_count;
+ break;
+ case 3:
+ lock_first=detail::lock_helper(m4,m5,m1,m2,m3);
+ if(!lock_first)
+ return;
+ lock_first=(lock_first+3)%lock_count;
+ break;
+ case 4:
+ lock_first=detail::lock_helper(m5,m1,m2,m3,m4);
+ if(!lock_first)
+ return;
+ lock_first=(lock_first+4)%lock_count;
+ break;
+ }
+ }
+ }
+
+ template<typename MutexType1,typename MutexType2>
+ typename enable_if<is_mutex_type<MutexType1>, int>::type try_lock(MutexType1& m1,MutexType2& m2)
+ {
+ return ((int)detail::try_lock_internal(m1,m2))-1;
+ }
+
+ template<typename MutexType1,typename MutexType2,typename MutexType3>
+ int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3)
+ {
+ return ((int)detail::try_lock_internal(m1,m2,m3))-1;
+ }
+
+ template<typename MutexType1,typename MutexType2,typename MutexType3,typename MutexType4>
+ int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,MutexType4& m4)
+ {
+ return ((int)detail::try_lock_internal(m1,m2,m3,m4))-1;
+ }
+
+ template<typename MutexType1,typename MutexType2,typename MutexType3,typename MutexType4,typename MutexType5>
+ int try_lock(MutexType1& m1,MutexType2& m2,MutexType3& m3,MutexType4& m4,MutexType5& m5)
+ {
+ return ((int)detail::try_lock_internal(m1,m2,m3,m4,m5))-1;
+ }
+
+
+ template<typename Iterator>
+ typename disable_if<is_mutex_type<Iterator>, void>::type lock(Iterator begin,Iterator end);
+
+ namespace detail
+ {
+ template<typename Iterator>
+ struct range_lock_guard
+ {
+ Iterator begin;
+ Iterator end;
+
+ range_lock_guard(Iterator begin_,Iterator end_):
+ begin(begin_),end(end_)
+ {
+ lock(begin,end);
+ }
+
+ void release()
+ {
+ begin=end;
+ }
+
+ ~range_lock_guard()
+ {
+ for(;begin!=end;++begin)
+ {
+ begin->unlock();
+ }
+ }
+ };
+ }
+
+ template<typename Iterator>
+ typename disable_if<is_mutex_type<Iterator>, Iterator>::type try_lock(Iterator begin,Iterator end)
+ {
+ if(begin==end)
+ {
+ return end;
+ }
+ typedef typename std::iterator_traits<Iterator>::value_type lock_type;
+ unique_lock<lock_type> guard(*begin,try_to_lock);
+
+ if(!guard.owns_lock())
+ {
+ return begin;
+ }
+ Iterator const failed=try_lock(++begin,end);
+ if(failed==end)
+ {
+ guard.release();
+ }
+
+ return failed;
+ }
+
+ template<typename Iterator>
+ typename disable_if<is_mutex_type<Iterator>, void>::type lock(Iterator begin,Iterator end)
+ {
+ typedef typename std::iterator_traits<Iterator>::value_type lock_type;
+
+ if(begin==end)
+ {
+ return;
+ }
+ bool start_with_begin=true;
+ Iterator second=begin;
+ ++second;
+ Iterator next=second;
+
+ for(;;)
+ {
+ unique_lock<lock_type> begin_lock(*begin,defer_lock);
+ if(start_with_begin)
+ {
+ begin_lock.lock();
+ Iterator const failed_lock=try_lock(next,end);
+ if(failed_lock==end)
+ {
+ begin_lock.release();
+ return;
+ }
+ start_with_begin=false;
+ next=failed_lock;
+ }
+ else
+ {
+ detail::range_lock_guard<Iterator> guard(next,end);
+ if(begin_lock.try_lock())
+ {
+ Iterator const failed_lock=try_lock(second,next);
+ if(failed_lock==next)
+ {
+ begin_lock.release();
+ guard.release();
+ return;
+ }
+ start_with_begin=false;
+ next=failed_lock;
+ }
+ else
+ {
+ start_with_begin=true;
+ next=second;
+ }
+ }
+ }
+ }
+
}
+#include <boost/config/abi_suffix.hpp>
+
#endif
Modified: branches/release/boost/thread/once.hpp
==============================================================================
--- branches/release/boost/thread/once.hpp (original)
+++ branches/release/boost/thread/once.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -18,6 +18,8 @@
#error "Boost threads unavailable on this platform"
#endif
+#include <boost/config/abi_prefix.hpp>
+
namespace boost
{
inline void call_once(void (*func)(),once_flag& flag)
@@ -26,4 +28,6 @@
}
}
+#include <boost/config/abi_suffix.hpp>
+
#endif
Modified: branches/release/boost/thread/pthread/condition_variable.hpp
==============================================================================
--- branches/release/boost/thread/pthread/condition_variable.hpp (original)
+++ branches/release/boost/thread/pthread/condition_variable.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -3,32 +3,17 @@
// 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)
-// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2007-8 Anthony Williams
-#include <limits.h>
-#include <boost/assert.hpp>
-#include <algorithm>
-#include <pthread.h>
#include "timespec.hpp"
#include "pthread_mutex_scoped_lock.hpp"
#include "thread_data.hpp"
#include "condition_variable_fwd.hpp"
+#include <boost/config/abi_prefix.hpp>
+
namespace boost
{
- inline condition_variable::condition_variable()
- {
- int const res=pthread_cond_init(&cond,NULL);
- if(res)
- {
- throw thread_resource_error();
- }
- }
- inline condition_variable::~condition_variable()
- {
- BOOST_VERIFY(!pthread_cond_destroy(&cond));
- }
-
inline void condition_variable::wait(unique_lock<mutex>& m)
{
detail::interruption_checker check_for_interruption(&cond);
@@ -175,4 +160,6 @@
}
+#include <boost/config/abi_suffix.hpp>
+
#endif
Modified: branches/release/boost/thread/pthread/condition_variable_fwd.hpp
==============================================================================
--- branches/release/boost/thread/pthread/condition_variable_fwd.hpp (original)
+++ branches/release/boost/thread/pthread/condition_variable_fwd.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -3,14 +3,17 @@
// 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)
-// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2007-8 Anthony Williams
+#include <boost/assert.hpp>
#include <pthread.h>
#include <boost/thread/mutex.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/xtime.hpp>
+#include <boost/config/abi_prefix.hpp>
+
namespace boost
{
class condition_variable
@@ -22,8 +25,18 @@
condition_variable& operator=(condition_variable&);
public:
- condition_variable();
- ~condition_variable();
+ condition_variable()
+ {
+ int const res=pthread_cond_init(&cond,NULL);
+ if(res)
+ {
+ throw thread_resource_error();
+ }
+ }
+ ~condition_variable()
+ {
+ BOOST_VERIFY(!pthread_cond_destroy(&cond));
+ }
void wait(unique_lock<mutex>& m);
@@ -58,9 +71,17 @@
return timed_wait(m,get_system_time()+wait_duration,pred);
}
+ typedef pthread_cond_t* native_handle_type;
+ native_handle_type native_handle()
+ {
+ return &cond;
+ }
+
void notify_one();
void notify_all();
};
}
+#include <boost/config/abi_suffix.hpp>
+
#endif
Modified: branches/release/boost/thread/pthread/mutex.hpp
==============================================================================
--- branches/release/boost/thread/pthread/mutex.hpp (original)
+++ branches/release/boost/thread/pthread/mutex.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -1,6 +1,6 @@
#ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_MUTEX_HPP
-// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2007-8 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)
@@ -11,9 +11,6 @@
#include <boost/thread/locks.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/assert.hpp>
-#ifndef WIN32
-#include <unistd.h>
-#endif
#include <errno.h>
#include "timespec.hpp"
#include "pthread_mutex_scoped_lock.hpp"
@@ -24,6 +21,8 @@
#endif
#endif
+#include <boost/config/abi_prefix.hpp>
+
namespace boost
{
class mutex:
@@ -69,7 +68,7 @@
}
typedef unique_lock<mutex> scoped_lock;
- typedef scoped_lock scoped_try_lock;
+ typedef detail::try_lock_wrapper<mutex> scoped_try_lock;
};
typedef mutex try_mutex;
@@ -136,9 +135,16 @@
{
struct timespec const timeout=detail::get_timespec(abs_time);
int const res=pthread_mutex_timedlock(&m,&timeout);
- BOOST_ASSERT(!res || res==EBUSY);
+ BOOST_ASSERT(!res || res==ETIMEDOUT);
return !res;
}
+
+ typedef pthread_mutex_t* native_handle_type;
+ native_handle_type native_handle()
+ {
+ return &m;
+ }
+
#else
void lock()
{
@@ -187,11 +193,13 @@
#endif
typedef unique_lock<timed_mutex> scoped_timed_lock;
- typedef scoped_timed_lock scoped_try_lock;
+ typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
};
}
+#include <boost/config/abi_suffix.hpp>
+
#endif
Modified: branches/release/boost/thread/pthread/once.hpp
==============================================================================
--- branches/release/boost/thread/pthread/once.hpp (original)
+++ branches/release/boost/thread/pthread/once.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -3,7 +3,7 @@
// once.hpp
//
-// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2007-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -17,7 +17,10 @@
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include <boost/cstdint.hpp>
-namespace boost {
+#include <boost/config/abi_prefix.hpp>
+
+namespace boost
+{
struct once_flag
{
@@ -82,4 +85,6 @@
}
}
+#include <boost/config/abi_suffix.hpp>
+
#endif
Modified: branches/release/boost/thread/pthread/pthread_mutex_scoped_lock.hpp
==============================================================================
--- branches/release/boost/thread/pthread/pthread_mutex_scoped_lock.hpp (original)
+++ branches/release/boost/thread/pthread/pthread_mutex_scoped_lock.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -1,6 +1,6 @@
#ifndef BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP
#define BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP
-// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2007-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -9,6 +9,8 @@
#include <pthread.h>
#include <boost/assert.hpp>
+#include <boost/config/abi_prefix.hpp>
+
namespace boost
{
namespace pthread
@@ -47,4 +49,6 @@
}
}
+#include <boost/config/abi_suffix.hpp>
+
#endif
Modified: branches/release/boost/thread/pthread/recursive_mutex.hpp
==============================================================================
--- branches/release/boost/thread/pthread/recursive_mutex.hpp (original)
+++ branches/release/boost/thread/pthread/recursive_mutex.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -1,6 +1,6 @@
#ifndef BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
-// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2007-8 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)
@@ -11,7 +11,7 @@
#include <boost/thread/locks.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/assert.hpp>
-#ifndef WIN32
+#ifndef _WIN32
#include <unistd.h>
#endif
#include <boost/date_time/posix_time/conversion.hpp>
@@ -25,6 +25,8 @@
#endif
#endif
+#include <boost/config/abi_prefix.hpp>
+
namespace boost
{
class recursive_mutex:
@@ -76,8 +78,15 @@
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
+
+ typedef pthread_mutex_t* native_handle_type;
+ native_handle_type native_handle()
+ {
+ return &m;
+ }
+
typedef unique_lock<recursive_mutex> scoped_lock;
- typedef scoped_lock scoped_try_lock;
+ typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
};
typedef recursive_mutex recursive_try_mutex;
@@ -171,6 +180,13 @@
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
+
+ typedef pthread_mutex_t* native_handle_type;
+ native_handle_type native_handle()
+ {
+ return &m;
+ }
+
#else
void lock()
{
@@ -239,11 +255,12 @@
#endif
typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
- typedef scoped_timed_lock scoped_try_lock;
+ typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
};
}
+#include <boost/config/abi_suffix.hpp>
#endif
Modified: branches/release/boost/thread/pthread/shared_mutex.hpp
==============================================================================
--- branches/release/boost/thread/pthread/shared_mutex.hpp (original)
+++ branches/release/boost/thread/pthread/shared_mutex.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -1,7 +1,7 @@
#ifndef BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
-// (C) Copyright 2006-7 Anthony Williams
+// (C) Copyright 2006-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -13,6 +13,8 @@
#include <boost/thread/thread.hpp>
#include <boost/thread/condition_variable.hpp>
+#include <boost/config/abi_prefix.hpp>
+
namespace boost
{
class shared_mutex
@@ -44,7 +46,7 @@
public:
shared_mutex()
{
- state_data state_={0};
+ state_data state_={0,0,0,0};
state=state_;
}
@@ -57,23 +59,11 @@
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lock(state_change);
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true)
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
+ while(state.exclusive || state.exclusive_waiting_blocked)
{
- if(!state.exclusive && !state.exclusive_waiting_blocked)
- {
- ++state.shared_count;
- return;
- }
-
shared_cond.wait(lock);
}
+ ++state.shared_count;
}
bool try_lock_shared()
@@ -96,26 +86,21 @@
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lock(state_change);
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true)
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
+ while(state.exclusive || state.exclusive_waiting_blocked)
{
- if(!state.exclusive && !state.exclusive_waiting_blocked)
- {
- ++state.shared_count;
- return true;
- }
-
if(!shared_cond.timed_wait(lock,timeout))
{
return false;
}
}
+ ++state.shared_count;
+ return true;
+ }
+
+ template<typename TimeDuration>
+ bool timed_lock_shared(TimeDuration const & relative_time)
+ {
+ return timed_lock_shared(get_system_time()+relative_time);
}
void unlock_shared()
@@ -144,56 +129,41 @@
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lock(state_change);
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true)
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
+ while(state.shared_count || state.exclusive)
{
- if(state.shared_count || state.exclusive)
- {
- state.exclusive_waiting_blocked=true;
- }
- else
- {
- state.exclusive=true;
- return;
- }
+ state.exclusive_waiting_blocked=true;
exclusive_cond.wait(lock);
}
+ state.exclusive=true;
}
bool timed_lock(system_time const& timeout)
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lock(state_change);
-
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true)
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
+
+ while(state.shared_count || state.exclusive)
{
- if(state.shared_count || state.exclusive)
- {
- state.exclusive_waiting_blocked=true;
- }
- else
- {
- state.exclusive=true;
- return true;
- }
+ state.exclusive_waiting_blocked=true;
if(!exclusive_cond.timed_wait(lock,timeout))
{
- return false;
+ if(state.shared_count || state.exclusive)
+ {
+ state.exclusive_waiting_blocked=false;
+ exclusive_cond.notify_one();
+ return false;
+ }
+ break;
}
}
+ state.exclusive=true;
+ return true;
+ }
+
+ template<typename TimeDuration>
+ bool timed_lock(TimeDuration const & relative_time)
+ {
+ return timed_lock(get_system_time()+relative_time);
}
bool try_lock()
@@ -224,51 +194,38 @@
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lock(state_change);
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true)
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
+ while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
- if(!state.exclusive && !state.exclusive_waiting_blocked && !state.upgrade)
- {
- ++state.shared_count;
- state.upgrade=true;
- return;
- }
-
shared_cond.wait(lock);
}
+ ++state.shared_count;
+ state.upgrade=true;
}
bool timed_lock_upgrade(system_time const& timeout)
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lock(state_change);
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true)
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
+ while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
- if(!state.exclusive && !state.exclusive_waiting_blocked && !state.upgrade)
- {
- ++state.shared_count;
- state.upgrade=true;
- return true;
- }
-
if(!shared_cond.timed_wait(lock,timeout))
{
- return false;
+ if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
+ {
+ return false;
+ }
+ break;
}
}
+ ++state.shared_count;
+ state.upgrade=true;
+ return true;
+ }
+
+ template<typename TimeDuration>
+ bool timed_lock_upgrade(TimeDuration const & relative_time)
+ {
+ return timed_lock(get_system_time()+relative_time);
}
bool try_lock_upgrade()
@@ -304,23 +261,12 @@
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lock(state_change);
--state.shared_count;
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true)
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
+ while(state.shared_count)
{
- if(!state.shared_count)
- {
- state.upgrade=false;
- state.exclusive=true;
- break;
- }
upgrade_cond.wait(lock);
}
+ state.upgrade=false;
+ state.exclusive=true;
}
void unlock_and_lock_upgrade()
@@ -352,5 +298,6 @@
};
}
+#include <boost/config/abi_suffix.hpp>
#endif
Deleted: branches/release/boost/thread/pthread/thread.hpp
==============================================================================
--- branches/release/boost/thread/pthread/thread.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
+++ (empty file)
@@ -1,329 +0,0 @@
-#ifndef BOOST_THREAD_THREAD_PTHREAD_HPP
-#define BOOST_THREAD_THREAD_PTHREAD_HPP
-// Copyright (C) 2001-2003
-// William E. Kempf
-// 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/detail/config.hpp>
-
-#include <boost/utility.hpp>
-#include <boost/function.hpp>
-#include <boost/thread/mutex.hpp>
-#include <boost/thread/condition_variable.hpp>
-#include <list>
-#include <memory>
-
-#include <pthread.h>
-#include <boost/optional.hpp>
-#include <boost/thread/detail/move.hpp>
-#include <boost/shared_ptr.hpp>
-#include "thread_data.hpp"
-#include <stdlib.h>
-
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4251)
-#endif
-
-namespace boost
-{
- class thread;
-
- namespace detail
- {
- class thread_id;
- }
-
- namespace this_thread
- {
- BOOST_THREAD_DECL detail::thread_id get_id();
- }
-
- namespace detail
- {
- class thread_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 thread_id this_thread::get_id();
- public:
- thread_id():
- thread_data()
- {}
-
- bool operator==(const thread_id& y) const
- {
- 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 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>
- friend std::basic_ostream<charT, traits>&
- operator<<(std::basic_ostream<charT, traits>& os, const thread_id& x)
- {
- if(x.thread_data)
- {
- return os<<x.thread_data;
- }
- else
- {
- return os<<"{Not-any-thread}";
- }
- }
- };
- }
-
- struct xtime;
- class BOOST_THREAD_DECL thread
- {
- private:
- thread(thread&);
- thread& operator=(thread&);
-
- template<typename F>
- struct thread_data:
- detail::thread_data_base
- {
- F f;
-
- thread_data(F f_):
- f(f_)
- {}
- thread_data(detail::thread_move_t<F> f_):
- f(f_)
- {}
-
- void run()
- {
- f();
- }
- };
-
- mutable boost::mutex thread_info_mutex;
- detail::thread_data_ptr thread_info;
-
- void start_thread();
-
- explicit thread(detail::thread_data_ptr data);
-
- detail::thread_data_ptr get_thread_info() const;
-
- public:
- thread();
- ~thread();
-
- template <class F>
- explicit thread(F f):
- thread_info(new thread_data<F>(f))
- {
- start_thread();
- }
- template <class F>
- thread(detail::thread_move_t<F> f):
- thread_info(new thread_data<F>(f))
- {
- start_thread();
- }
-
- thread(detail::thread_move_t<thread> x);
- thread& operator=(detail::thread_move_t<thread> x);
- operator detail::thread_move_t<thread>();
- detail::thread_move_t<thread> move();
-
- void swap(thread& x);
-
- typedef detail::thread_id id;
-
- id get_id() const;
-
- bool joinable() const;
- void join();
- bool timed_join(const system_time& wait_until);
-
- template<typename TimeDuration>
- inline bool timed_join(TimeDuration const& rel_time)
- {
- return timed_join(get_system_time()+rel_time);
- }
- void detach();
-
- static unsigned hardware_concurrency();
-
- // backwards compatibility
- bool operator==(const thread& other) const;
- bool operator!=(const thread& other) const;
-
- static void sleep(const system_time& xt);
- static void yield();
-
- // extensions
- void interrupt();
- 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>
- struct thread::thread_data<boost::reference_wrapper<F> >:
- detail::thread_data_base
- {
- F& f;
-
- thread_data(boost::reference_wrapper<F> f_):
- f(f_)
- {}
-
- void run()
- {
- f();
- }
- };
-
- namespace this_thread
- {
- class BOOST_THREAD_DECL disable_interruption
- {
- disable_interruption(const disable_interruption&);
- disable_interruption& operator=(const disable_interruption&);
-
- bool interruption_was_enabled;
- friend class restore_interruption;
- public:
- disable_interruption();
- ~disable_interruption();
- };
-
- class BOOST_THREAD_DECL restore_interruption
- {
- restore_interruption(const restore_interruption&);
- restore_interruption& operator=(const restore_interruption&);
- public:
- explicit restore_interruption(disable_interruption& d);
- ~restore_interruption();
- };
-
- BOOST_THREAD_DECL thread::id get_id();
-
- BOOST_THREAD_DECL void interruption_point();
- BOOST_THREAD_DECL bool interruption_enabled();
- BOOST_THREAD_DECL bool interruption_requested();
-
- inline void yield()
- {
- thread::yield();
- }
-
- template<typename TimeDuration>
- inline void sleep(TimeDuration const& rel_time)
- {
- thread::sleep(get_system_time()+rel_time);
- }
- }
-
- namespace detail
- {
- struct thread_exit_function_base
- {
- virtual ~thread_exit_function_base()
- {}
- virtual void operator()() const=0;
- };
-
- template<typename F>
- struct thread_exit_function:
- thread_exit_function_base
- {
- F f;
-
- thread_exit_function(F f_):
- f(f_)
- {}
-
- void operator()() const
- {
- f();
- }
- };
-
- BOOST_THREAD_DECL void add_thread_exit_function(thread_exit_function_base*);
- }
-
- namespace this_thread
- {
- template<typename F>
- inline void at_thread_exit(F f)
- {
- detail::thread_exit_function_base* const thread_exit_func=new detail::thread_exit_function<F>(f);
- detail::add_thread_exit_function(thread_exit_func);
- }
- }
-
- class BOOST_THREAD_DECL thread_group
- {
- public:
- thread_group();
- ~thread_group();
-
- thread* create_thread(const function0<void>& threadfunc);
- void add_thread(thread* thrd);
- void remove_thread(thread* thrd);
- void join_all();
- void interrupt_all();
- size_t size() const;
-
- private:
- thread_group(thread_group&);
- void operator=(thread_group&);
-
- std::list<thread*> m_threads;
- mutex m_mutex;
- };
-} // namespace boost
-
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
-
-
-#endif
Modified: branches/release/boost/thread/pthread/thread_data.hpp
==============================================================================
--- branches/release/boost/thread/pthread/thread_data.hpp (original)
+++ branches/release/boost/thread/pthread/thread_data.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -6,6 +6,7 @@
// (C) Copyright 2007 Anthony Williams
#include <boost/thread/detail/config.hpp>
+#include <boost/thread/exceptions.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/thread/mutex.hpp>
@@ -13,11 +14,12 @@
#include <pthread.h>
#include "condition_variable_fwd.hpp"
+#include <boost/config/abi_prefix.hpp>
+
namespace boost
{
- class thread_interrupted
- {};
-
+ class thread;
+
namespace detail
{
struct thread_exit_callback_node;
@@ -26,7 +28,7 @@
struct thread_data_base;
typedef boost::shared_ptr<thread_data_base> thread_data_ptr;
- struct thread_data_base:
+ struct BOOST_THREAD_DECL thread_data_base:
enable_shared_from_this<thread_data_base>
{
thread_data_ptr self;
@@ -51,8 +53,9 @@
interrupt_requested(false),
current_cond(0)
{}
- virtual ~thread_data_base()
- {}
+ virtual ~thread_data_base();
+
+ typedef pthread_t native_handle_type;
virtual void run()=0;
};
@@ -95,7 +98,21 @@
}
};
}
+
+ namespace this_thread
+ {
+ void BOOST_THREAD_DECL yield();
+
+ void BOOST_THREAD_DECL sleep(system_time const& abs_time);
+
+ template<typename TimeDuration>
+ inline void sleep(TimeDuration const& rel_time)
+ {
+ this_thread::sleep(get_system_time()+rel_time);
+ }
+ }
}
+#include <boost/config/abi_suffix.hpp>
#endif
Modified: branches/release/boost/thread/pthread/timespec.hpp
==============================================================================
--- branches/release/boost/thread/pthread/timespec.hpp (original)
+++ branches/release/boost/thread/pthread/timespec.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -1,6 +1,6 @@
#ifndef BOOST_THREAD_PTHREAD_TIMESPEC_HPP
#define BOOST_THREAD_PTHREAD_TIMESPEC_HPP
-// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2007-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -8,6 +8,12 @@
#include <boost/thread/thread_time.hpp>
#include <boost/date_time/posix_time/conversion.hpp>
+#include <pthread.h>
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#include <boost/config/abi_prefix.hpp>
namespace boost
{
@@ -15,14 +21,16 @@
{
inline struct timespec get_timespec(boost::system_time const& abs_time)
{
- struct timespec timeout={0};
+ struct timespec timeout={0,0};
boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0);
timeout.tv_sec=time_since_epoch.total_seconds();
- timeout.tv_nsec=time_since_epoch.fractional_seconds()*(1000000000/time_since_epoch.ticks_per_second());
+ timeout.tv_nsec=(long)(time_since_epoch.fractional_seconds()*(1000000000l/time_since_epoch.ticks_per_second()));
return timeout;
}
}
}
+#include <boost/config/abi_suffix.hpp>
+
#endif
Deleted: branches/release/boost/thread/pthread/tss.hpp
==============================================================================
--- branches/release/boost/thread/pthread/tss.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
+++ (empty file)
@@ -1,103 +0,0 @@
-#ifndef BOOST_THREAD_PTHREAD_TSS_HPP
-#define BOOST_THREAD_PTHREAD_TSS_HPP
-
-// 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)
-// (C) Copyright 2007 Anthony Williams
-
-#include <boost/thread/detail/config.hpp>
-#include <boost/shared_ptr.hpp>
-
-namespace boost
-{
- namespace detail
- {
- struct tss_cleanup_function
- {
- virtual ~tss_cleanup_function()
- {}
-
- virtual void operator()(void* data)=0;
- };
-
- BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
- BOOST_THREAD_DECL void* get_tss_data(void const* key);
- }
-
- template <typename T>
- class thread_specific_ptr
- {
- private:
- thread_specific_ptr(thread_specific_ptr&);
- thread_specific_ptr& operator=(thread_specific_ptr&);
-
- struct delete_data:
- detail::tss_cleanup_function
- {
- void operator()(void* data)
- {
- delete static_cast<T*>(data);
- }
- };
-
- struct run_custom_cleanup_function:
- detail::tss_cleanup_function
- {
- void (*cleanup_function)(T*);
-
- explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)):
- cleanup_function(cleanup_function_)
- {}
-
- void operator()(void* data)
- {
- cleanup_function(static_cast<T*>(data));
- }
- };
-
-
- boost::shared_ptr<detail::tss_cleanup_function> cleanup;
-
- public:
- thread_specific_ptr():
- cleanup(new delete_data)
- {}
- explicit thread_specific_ptr(void (*func_)(T*)):
- cleanup(new run_custom_cleanup_function(func_))
- {}
- ~thread_specific_ptr()
- {
- reset();
- }
-
- T* get() const
- {
- return static_cast<T*>(detail::get_tss_data(this));
- }
- T* operator->() const
- {
- return get();
- }
- T& operator*() const
- {
- return *get();
- }
- T* release()
- {
- T* const temp=get();
- detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,false);
- return temp;
- }
- void reset(T* new_value=0)
- {
- T* const current_value=get();
- if(current_value!=new_value)
- {
- detail::set_tss_data(this,cleanup,new_value,true);
- }
- }
- };
-}
-
-#endif
Modified: branches/release/boost/thread/thread.hpp
==============================================================================
--- branches/release/boost/thread/thread.hpp (original)
+++ branches/release/boost/thread/thread.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -3,7 +3,7 @@
// thread.hpp
//
-// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2007-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -12,11 +12,14 @@
#include <boost/thread/detail/platform.hpp>
#if defined(BOOST_THREAD_PLATFORM_WIN32)
-#include <boost/thread/win32/thread.hpp>
+#include <boost/thread/win32/thread_data.hpp>
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
-#include <boost/thread/pthread/thread.hpp>
+#include <boost/thread/pthread/thread_data.hpp>
#else
#error "Boost threads unavailable on this platform"
#endif
+#include <boost/thread/detail/thread.hpp>
+
+
#endif
Modified: branches/release/boost/thread/thread_time.hpp
==============================================================================
--- branches/release/boost/thread/thread_time.hpp (original)
+++ branches/release/boost/thread/thread_time.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -9,6 +9,8 @@
#include <boost/date_time/microsec_time_clock.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/config/abi_prefix.hpp>
+
namespace boost
{
typedef boost::posix_time::ptime system_time;
@@ -43,4 +45,6 @@
}
+#include <boost/config/abi_suffix.hpp>
+
#endif
Modified: branches/release/boost/thread/win32/basic_recursive_mutex.hpp
==============================================================================
--- branches/release/boost/thread/win32/basic_recursive_mutex.hpp (original)
+++ branches/release/boost/thread/win32/basic_recursive_mutex.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -3,7 +3,7 @@
// basic_recursive_mutex.hpp
//
-// (C) Copyright 2006-7 Anthony Williams
+// (C) Copyright 2006-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -12,6 +12,8 @@
#include "thread_primitives.hpp"
#include "basic_timed_mutex.hpp"
+#include <boost/config/abi_prefix.hpp>
+
namespace boost
{
namespace detail
@@ -123,4 +125,6 @@
#define BOOST_BASIC_RECURSIVE_MUTEX_INITIALIZER {0}
+#include <boost/config/abi_suffix.hpp>
+
#endif
Modified: branches/release/boost/thread/win32/basic_timed_mutex.hpp
==============================================================================
--- branches/release/boost/thread/win32/basic_timed_mutex.hpp (original)
+++ branches/release/boost/thread/win32/basic_timed_mutex.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -3,7 +3,7 @@
// basic_timed_mutex_win32.hpp
//
-// (C) Copyright 2006 Anthony Williams
+// (C) Copyright 2006-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -15,13 +15,18 @@
#include <boost/thread/thread_time.hpp>
#include <boost/detail/interlocked.hpp>
+#include <boost/config/abi_prefix.hpp>
+
namespace boost
{
namespace detail
{
struct basic_timed_mutex
{
- BOOST_STATIC_CONSTANT(long,lock_flag_value=0x80000000);
+ BOOST_STATIC_CONSTANT(unsigned char,lock_flag_bit=31);
+ BOOST_STATIC_CONSTANT(unsigned char,event_set_flag_bit=30);
+ BOOST_STATIC_CONSTANT(long,lock_flag_value=1<<lock_flag_bit);
+ BOOST_STATIC_CONSTANT(long,event_set_flag_value=1<<event_set_flag_bit);
long active_count;
void* event;
@@ -50,18 +55,7 @@
bool try_lock()
{
- long old_count=active_count&~lock_flag_value;
- do
- {
- long const current_count=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,(old_count+1)|lock_flag_value,old_count);
- if(current_count==old_count)
- {
- return true;
- }
- old_count=current_count;
- }
- while(!(old_count&lock_flag_value));
- return false;
+ return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit);
}
void lock()
@@ -70,47 +64,46 @@
}
bool timed_lock(::boost::system_time const& wait_until)
{
+ if(!win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit))
+ {
+ return true;
+ }
long old_count=active_count;
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4127)
-#endif
- while(true)
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
+ for(;;)
{
- long const current_count=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,(old_count+1)|lock_flag_value,old_count);
- if(current_count==old_count)
+ long const new_count=(old_count&lock_flag_value)?(old_count+1):(old_count|lock_flag_value);
+ long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
+ if(current==old_count)
{
break;
}
- old_count=current_count;
+ old_count=current;
}
if(old_count&lock_flag_value)
{
bool lock_acquired=false;
void* const sem=get_event();
- ++old_count; // we're waiting, too
+
do
{
- old_count-=(lock_flag_value+1); // there will be one less active thread on this mutex when it gets unlocked
if(win32::WaitForSingleObject(sem,::boost::detail::get_milliseconds_until(wait_until))!=0)
{
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
}
- do
+ old_count&=~lock_flag_value;
+ old_count|=event_set_flag_value;
+ for(;;)
{
- long const current_count=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,old_count|lock_flag_value,old_count);
- if(current_count==old_count)
+ long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value;
+ long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
+ if(current==old_count)
{
break;
}
- old_count=current_count;
+ old_count=current;
}
- while(!(old_count&lock_flag_value));
lock_acquired=!(old_count&lock_flag_value);
}
while(!lock_acquired);
@@ -131,12 +124,14 @@
void unlock()
{
- long const offset=lock_flag_value+1;
- long old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,(~offset)+1);
-
- if(old_count>offset)
+ long const offset=lock_flag_value;
+ long const old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,lock_flag_value);
+ if(!(old_count&event_set_flag_value) && (old_count>offset))
{
- win32::SetEvent(get_event());
+ if(!win32::interlocked_bit_test_and_set(&active_count,event_set_flag_bit))
+ {
+ win32::SetEvent(get_event());
+ }
}
}
@@ -182,4 +177,6 @@
#define BOOST_BASIC_TIMED_MUTEX_INITIALIZER {0}
+#include <boost/config/abi_suffix.hpp>
+
#endif
Modified: branches/release/boost/thread/win32/condition_variable.hpp
==============================================================================
--- branches/release/boost/thread/win32/condition_variable.hpp (original)
+++ branches/release/boost/thread/win32/condition_variable.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -3,7 +3,7 @@
// 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)
-// (C) Copyright 2007 Anthony Williams
+// (C) Copyright 2007-8 Anthony Williams
#include <boost/thread/mutex.hpp>
#include "thread_primitives.hpp"
@@ -14,85 +14,118 @@
#include <boost/thread/thread_time.hpp>
#include "interlocked_read.hpp"
#include <boost/thread/xtime.hpp>
+#include <vector>
+#include <boost/intrusive_ptr.hpp>
+
+#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
- class basic_condition_variable
+ class basic_cv_list_entry;
+ void intrusive_ptr_add_ref(basic_cv_list_entry * p);
+ void intrusive_ptr_release(basic_cv_list_entry * p);
+
+ class basic_cv_list_entry
{
- boost::mutex internal_mutex;
- long total_count;
- unsigned active_generation_count;
+ private:
+ detail::win32::handle_manager semaphore;
+ detail::win32::handle_manager wake_sem;
+ long waiters;
+ bool notified;
+ long references;
- struct list_entry
- {
- detail::win32::handle semaphore;
- long count;
- bool notified;
+ basic_cv_list_entry(basic_cv_list_entry&);
+ void operator=(basic_cv_list_entry&);
+
+ public:
+ explicit basic_cv_list_entry(detail::win32::handle_manager const& wake_sem_):
+ semaphore(detail::win32::create_anonymous_semaphore(0,LONG_MAX)),
+ wake_sem(wake_sem_.duplicate()),
+ waiters(1),notified(false),references(0)
+ {}
- list_entry():
- semaphore(0),count(0),notified(0)
- {}
- };
+ static bool no_waiters(boost::intrusive_ptr<basic_cv_list_entry> const& entry)
+ {
+ return !detail::interlocked_read_acquire(&entry->waiters);
+ }
- BOOST_STATIC_CONSTANT(unsigned,generation_count=3);
+ void add_waiter()
+ {
+ BOOST_INTERLOCKED_INCREMENT(&waiters);
+ }
+
+ void remove_waiter()
+ {
+ BOOST_INTERLOCKED_DECREMENT(&waiters);
+ }
- list_entry generations[generation_count];
- detail::win32::handle wake_sem;
+ void release(unsigned count_to_release)
+ {
+ notified=true;
+ detail::win32::ReleaseSemaphore(semaphore,count_to_release,0);
+ }
- static bool no_waiters(list_entry const& entry)
+ void release_waiters()
{
- return entry.count==0;
+ release(detail::interlocked_read_acquire(&waiters));
}
- void shift_generations_down()
+ bool is_notified() const
{
- list_entry* const last_active_entry=std::remove_if(generations,generations+generation_count,no_waiters);
- if(last_active_entry==generations+generation_count)
- {
- broadcast_entry(generations[generation_count-1],false);
- }
- else
- {
- active_generation_count=unsigned(last_active_entry-generations)+1;
- }
+ return notified;
+ }
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4996)
-#endif
- std::copy_backward(generations,generations+active_generation_count-1,generations+active_generation_count);
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
- generations[0]=list_entry();
+ bool wait(timeout wait_until)
+ {
+ return this_thread::interruptible_wait(semaphore,wait_until);
}
- void broadcast_entry(list_entry& entry,bool wake)
+ bool woken()
{
- long const count_to_wake=entry.count;
- detail::interlocked_write_release(&total_count,total_count-count_to_wake);
- if(wake)
- {
- detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0);
- }
- detail::win32::ReleaseSemaphore(entry.semaphore,count_to_wake,0);
- entry.count=0;
- dispose_entry(entry);
+ unsigned long const woken_result=detail::win32::WaitForSingleObject(wake_sem,0);
+ BOOST_ASSERT((woken_result==detail::win32::timeout) || (woken_result==0));
+ return woken_result==0;
}
-
- void dispose_entry(list_entry& entry)
+ friend void intrusive_ptr_add_ref(basic_cv_list_entry * p);
+ friend void intrusive_ptr_release(basic_cv_list_entry * p);
+ };
+
+ inline void intrusive_ptr_add_ref(basic_cv_list_entry * p)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&p->references);
+ }
+
+ inline void intrusive_ptr_release(basic_cv_list_entry * p)
+ {
+ if(!BOOST_INTERLOCKED_DECREMENT(&p->references))
{
- if(entry.semaphore)
- {
- BOOST_VERIFY(detail::win32::CloseHandle(entry.semaphore));
- entry.semaphore=0;
- }
- entry.notified=false;
+ delete p;
}
+ }
+
+ class basic_condition_variable
+ {
+ boost::mutex internal_mutex;
+ long total_count;
+ unsigned active_generation_count;
+
+ typedef basic_cv_list_entry list_entry;
+ typedef boost::intrusive_ptr<list_entry> entry_ptr;
+ typedef std::vector<entry_ptr> generation_list;
+
+ generation_list generations;
+ detail::win32::handle_manager wake_sem;
+
+ void wake_waiters(long count_to_wake)
+ {
+ detail::interlocked_write_release(&total_count,total_count-count_to_wake);
+ detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0);
+ }
+
template<typename lock_type>
struct relocker
{
@@ -116,75 +149,78 @@
}
private:
+ relocker(relocker&);
void operator=(relocker&);
};
- template<typename lock_type>
- void start_wait_loop_first_time(relocker<lock_type>& locker,
- detail::win32::handle_manager& local_wake_sem)
+ entry_ptr get_wait_entry()
{
- locker.unlock();
+ boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
+
if(!wake_sem)
{
wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
BOOST_ASSERT(wake_sem);
}
- local_wake_sem=detail::win32::duplicate_handle(wake_sem);
-
- if(generations[0].notified)
+
+ detail::interlocked_write_release(&total_count,total_count+1);
+ if(generations.empty() || generations.back()->is_notified())
{
- shift_generations_down();
+ entry_ptr new_entry(new list_entry(wake_sem));
+ generations.push_back(new_entry);
+ return new_entry;
}
- else if(!active_generation_count)
+ else
{
- active_generation_count=1;
+ generations.back()->add_waiter();
+ return generations.back();
}
}
- template<typename lock_type>
- void start_wait_loop(relocker<lock_type>& locker,
- detail::win32::handle_manager& local_wake_sem,
- detail::win32::handle_manager& sem)
+ struct entry_manager
{
- boost::mutex::scoped_lock internal_lock(internal_mutex);
- detail::interlocked_write_release(&total_count,total_count+1);
- if(!local_wake_sem)
+ entry_ptr const entry;
+
+ entry_manager(entry_ptr const& entry_):
+ entry(entry_)
+ {}
+
+ ~entry_manager()
{
- start_wait_loop_first_time(locker,local_wake_sem);
+ entry->remove_waiter();
}
- if(!generations[0].semaphore)
+
+ list_entry* operator->()
{
- generations[0].semaphore=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
- BOOST_ASSERT(generations[0].semaphore);
+ return entry.get();
}
- ++generations[0].count;
- sem=detail::win32::duplicate_handle(generations[0].semaphore);
- }
+
+ private:
+ void operator=(entry_manager&);
+ entry_manager(entry_manager&);
+ };
+
protected:
template<typename lock_type>
bool do_wait(lock_type& lock,timeout wait_until)
{
- detail::win32::handle_manager local_wake_sem;
- detail::win32::handle_manager sem;
- bool woken=false;
-
relocker<lock_type> locker(lock);
-
+
+ entry_manager entry(get_wait_entry());
+
+ locker.unlock();
+
+ bool woken=false;
while(!woken)
{
- start_wait_loop(locker,local_wake_sem,sem);
-
- if(!this_thread::interruptible_wait(sem,wait_until))
+ if(!entry->wait(wait_until))
{
return false;
}
- unsigned long const woken_result=detail::win32::WaitForSingleObject(local_wake_sem,0);
- BOOST_ASSERT(woken_result==detail::win32::timeout || woken_result==0);
-
- woken=(woken_result==0);
+ woken=entry->woken();
}
return woken;
}
@@ -202,45 +238,33 @@
basic_condition_variable(const basic_condition_variable& other);
basic_condition_variable& operator=(const basic_condition_variable& other);
+
public:
basic_condition_variable():
total_count(0),active_generation_count(0),wake_sem(0)
{}
~basic_condition_variable()
- {
- for(unsigned i=0;i<generation_count;++i)
- {
- dispose_entry(generations[i]);
- }
- detail::win32::CloseHandle(wake_sem);
- }
+ {}
-
void notify_one()
{
if(detail::interlocked_read_acquire(&total_count))
{
- boost::mutex::scoped_lock internal_lock(internal_mutex);
- detail::win32::ReleaseSemaphore(wake_sem,1,0);
- for(unsigned generation=active_generation_count;generation!=0;--generation)
+ boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
+ if(!total_count)
+ {
+ return;
+ }
+ wake_waiters(1);
+
+ for(generation_list::iterator it=generations.begin(),
+ end=generations.end();
+ it!=end;++it)
{
- list_entry& entry=generations[generation-1];
- if(entry.count)
- {
- detail::interlocked_write_release(&total_count,total_count-1);
- entry.notified=true;
- detail::win32::ReleaseSemaphore(entry.semaphore,1,0);
- if(!--entry.count)
- {
- dispose_entry(entry);
- if(generation==active_generation_count)
- {
- --active_generation_count;
- }
- }
- }
+ (*it)->release(1);
}
+ generations.erase(std::remove_if(generations.begin(),generations.end(),&basic_cv_list_entry::no_waiters),generations.end());
}
}
@@ -248,16 +272,20 @@
{
if(detail::interlocked_read_acquire(&total_count))
{
- boost::mutex::scoped_lock internal_lock(internal_mutex);
- for(unsigned generation=active_generation_count;generation!=0;--generation)
+ boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
+ if(!total_count)
+ {
+ return;
+ }
+ wake_waiters(total_count);
+ for(generation_list::iterator it=generations.begin(),
+ end=generations.end();
+ it!=end;++it)
{
- list_entry& entry=generations[generation-1];
- if(entry.count)
- {
- broadcast_entry(entry,true);
- }
+ (*it)->release_waiters();
}
- active_generation_count=0;
+ generations.clear();
+ wake_sem=detail::win32::handle(0);
}
}
@@ -265,9 +293,18 @@
}
class condition_variable:
- public detail::basic_condition_variable
+ private detail::basic_condition_variable
{
+ private:
+ condition_variable(condition_variable&);
+ void operator=(condition_variable&);
public:
+ condition_variable()
+ {}
+
+ using detail::basic_condition_variable::notify_one;
+ using detail::basic_condition_variable::notify_all;
+
void wait(unique_lock<mutex>& m)
{
do_wait(m,detail::timeout::sentinel());
@@ -313,9 +350,18 @@
};
class condition_variable_any:
- public detail::basic_condition_variable
+ private detail::basic_condition_variable
{
+ private:
+ condition_variable_any(condition_variable_any&);
+ void operator=(condition_variable_any&);
public:
+ condition_variable_any()
+ {}
+
+ using detail::basic_condition_variable::notify_one;
+ using detail::basic_condition_variable::notify_all;
+
template<typename lock_type>
void wait(lock_type& m)
{
@@ -367,4 +413,6 @@
}
+#include <boost/config/abi_suffix.hpp>
+
#endif
Modified: branches/release/boost/thread/win32/interlocked_read.hpp
==============================================================================
--- branches/release/boost/thread/win32/interlocked_read.hpp (original)
+++ branches/release/boost/thread/win32/interlocked_read.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -3,12 +3,16 @@
// interlocked_read_win32.hpp
//
-// (C) Copyright 2005-7 Anthony Williams
+// (C) Copyright 2005-8 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/detail/interlocked.hpp>
+
+#include <boost/config/abi_prefix.hpp>
+
#ifdef BOOST_MSVC
extern "C" void _ReadWriteBarrier(void);
@@ -46,8 +50,6 @@
#else
-#include <boost/detail/interlocked.hpp>
-
namespace boost
{
namespace detail
@@ -73,5 +75,6 @@
#endif
+#include <boost/config/abi_suffix.hpp>
#endif
Modified: branches/release/boost/thread/win32/mutex.hpp
==============================================================================
--- branches/release/boost/thread/win32/mutex.hpp (original)
+++ branches/release/boost/thread/win32/mutex.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -10,6 +10,8 @@
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
+#include <boost/config/abi_prefix.hpp>
+
namespace boost
{
namespace detail
@@ -32,7 +34,7 @@
}
typedef unique_lock<mutex> scoped_lock;
- typedef scoped_lock scoped_try_lock;
+ typedef detail::try_lock_wrapper<mutex> scoped_try_lock;
};
typedef mutex try_mutex;
@@ -53,9 +55,11 @@
}
typedef unique_lock<timed_mutex> scoped_timed_lock;
- typedef scoped_timed_lock scoped_try_lock;
+ typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
};
}
+#include <boost/config/abi_suffix.hpp>
+
#endif
Modified: branches/release/boost/thread/win32/once.hpp
==============================================================================
--- branches/release/boost/thread/win32/once.hpp (original)
+++ branches/release/boost/thread/win32/once.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -18,6 +18,8 @@
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/interlocked_read.hpp>
+#include <boost/config/abi_prefix.hpp>
+
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std
{
@@ -129,4 +131,6 @@
}
}
+#include <boost/config/abi_suffix.hpp>
+
#endif
Modified: branches/release/boost/thread/win32/recursive_mutex.hpp
==============================================================================
--- branches/release/boost/thread/win32/recursive_mutex.hpp (original)
+++ branches/release/boost/thread/win32/recursive_mutex.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -15,6 +15,8 @@
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
+#include <boost/config/abi_prefix.hpp>
+
namespace boost
{
class recursive_mutex:
@@ -32,7 +34,7 @@
}
typedef unique_lock<recursive_mutex> scoped_lock;
- typedef scoped_lock scoped_try_lock;
+ typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
};
typedef recursive_mutex recursive_try_mutex;
@@ -52,10 +54,11 @@
}
typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
- typedef scoped_timed_lock scoped_try_lock;
+ typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
};
}
+#include <boost/config/abi_suffix.hpp>
#endif
Modified: branches/release/boost/thread/win32/shared_mutex.hpp
==============================================================================
--- branches/release/boost/thread/win32/shared_mutex.hpp (original)
+++ branches/release/boost/thread/win32/shared_mutex.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -15,6 +15,8 @@
#include <boost/utility.hpp>
#include <boost/thread/thread_time.hpp>
+#include <boost/config/abi_prefix.hpp>
+
namespace boost
{
class shared_mutex:
@@ -23,12 +25,12 @@
private:
struct state_data
{
- unsigned shared_count:11;
- unsigned shared_waiting:11;
- unsigned exclusive:1;
- unsigned upgrade:1;
- unsigned exclusive_waiting:7;
- unsigned exclusive_waiting_blocked:1;
+ unsigned shared_count:11,
+ shared_waiting:11,
+ exclusive:1,
+ upgrade:1,
+ exclusive_waiting:7,
+ exclusive_waiting_blocked:1;
friend bool operator==(state_data const& lhs,state_data const& rhs)
{
@@ -120,6 +122,12 @@
BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel()));
}
+ template<typename TimeDuration>
+ bool timed_lock_shared(TimeDuration const & relative_time)
+ {
+ return timed_lock_shared(get_system_time()+relative_time);
+ }
+
bool timed_lock_shared(boost::system_time const& wait_until)
{
#ifdef BOOST_MSVC
@@ -269,6 +277,12 @@
BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
}
+ template<typename TimeDuration>
+ bool timed_lock(TimeDuration const & relative_time)
+ {
+ return timed_lock(get_system_time()+relative_time);
+ }
+
bool timed_lock(boost::system_time const& wait_until)
{
#ifdef BOOST_MSVC
@@ -325,7 +339,10 @@
{
if(new_state.exclusive_waiting)
{
- --new_state.exclusive_waiting;
+ if(!--new_state.exclusive_waiting)
+ {
+ new_state.exclusive_waiting_blocked=false;
+ }
}
}
else
@@ -617,5 +634,6 @@
};
}
+#include <boost/config/abi_suffix.hpp>
#endif
Deleted: branches/release/boost/thread/win32/thread.hpp
==============================================================================
--- branches/release/boost/thread/win32/thread.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
+++ (empty file)
@@ -1,524 +0,0 @@
-#ifndef BOOST_THREAD_THREAD_WIN32_HPP
-#define BOOST_THREAD_THREAD_WIN32_HPP
-// 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)
-// (C) Copyright 2007 Anthony Williams
-
-#include <exception>
-#include <boost/thread/exceptions.hpp>
-#include <ostream>
-#include <boost/thread/detail/move.hpp>
-#include <boost/intrusive_ptr.hpp>
-#include <boost/thread/mutex.hpp>
-#include <boost/thread/thread_time.hpp>
-#include "thread_primitives.hpp"
-#include "thread_heap_alloc.hpp"
-#include <boost/utility.hpp>
-#include <boost/assert.hpp>
-#include <list>
-#include <algorithm>
-#include <boost/ref.hpp>
-#include <boost/cstdint.hpp>
-#include <stdlib.h>
-#include <memory>
-
-#ifdef BOOST_MSVC
-#pragma warning(push)
-#pragma warning(disable:4251)
-#endif
-
-namespace boost
-{
- class thread_interrupted
- {};
-
- namespace detail
- {
- struct thread_exit_callback_node;
- struct tss_data_node;
-
- struct thread_data_base
- {
- long count;
- detail::win32::handle_manager thread_handle;
- detail::win32::handle_manager interruption_handle;
- boost::detail::thread_exit_callback_node* thread_exit_callbacks;
- boost::detail::tss_data_node* tss_data;
- bool interruption_enabled;
- unsigned id;
-
- thread_data_base():
- count(0),thread_handle(detail::win32::invalid_handle_value),
- interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)),
- thread_exit_callbacks(0),tss_data(0),
- interruption_enabled(true),
- id(0)
- {}
- virtual ~thread_data_base()
- {}
-
- friend void intrusive_ptr_add_ref(thread_data_base * p)
- {
- BOOST_INTERLOCKED_INCREMENT(&p->count);
- }
-
- friend void intrusive_ptr_release(thread_data_base * p)
- {
- if(!BOOST_INTERLOCKED_DECREMENT(&p->count))
- {
- detail::heap_delete(p);
- }
- }
-
- void interrupt()
- {
- BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0);
- }
-
-
- virtual void run()=0;
- };
-
- typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr;
-
- struct timeout
- {
- unsigned long start;
- uintmax_t milliseconds;
- bool relative;
- boost::system_time abs_time;
-
- static unsigned long const max_non_infinite_wait=0xfffffffe;
-
- timeout(uintmax_t milliseconds_):
- start(win32::GetTickCount()),
- milliseconds(milliseconds_),
- relative(true),
- abs_time(boost::get_system_time())
- {}
-
- timeout(boost::system_time const& abs_time_):
- start(win32::GetTickCount()),
- milliseconds(0),
- relative(false),
- abs_time(abs_time_)
- {}
-
- struct remaining_time
- {
- bool more;
- unsigned long milliseconds;
-
- remaining_time(uintmax_t remaining):
- more(remaining>max_non_infinite_wait),
- milliseconds(more?max_non_infinite_wait:(unsigned long)remaining)
- {}
- };
-
- remaining_time remaining_milliseconds() const
- {
- if(is_sentinel())
- {
- return remaining_time(win32::infinite);
- }
- else if(relative)
- {
- unsigned long const now=win32::GetTickCount();
- unsigned long const elapsed=now-start;
- return remaining_time((elapsed<milliseconds)?(milliseconds-elapsed):0);
- }
- else
- {
- system_time const now=get_system_time();
- if(abs_time<=now)
- {
- return remaining_time(0);
- }
- return remaining_time((abs_time-now).total_milliseconds()+1);
- }
- }
-
- bool is_sentinel() const
- {
- return milliseconds==~uintmax_t(0);
- }
-
-
- static timeout sentinel()
- {
- return timeout(sentinel_type());
- }
- private:
- struct sentinel_type
- {};
-
- explicit timeout(sentinel_type):
- start(0),milliseconds(~uintmax_t(0)),relative(true)
- {}
- };
- }
-
- class BOOST_THREAD_DECL thread
- {
- private:
- thread(thread&);
- thread& operator=(thread&);
-
- void release_handle();
-
- template<typename F>
- struct thread_data:
- detail::thread_data_base
- {
- F f;
-
- thread_data(F f_):
- f(f_)
- {}
- thread_data(detail::thread_move_t<F> f_):
- f(f_)
- {}
-
- void run()
- {
- f();
- }
- };
-
- mutable boost::mutex thread_info_mutex;
- detail::thread_data_ptr thread_info;
-
- static unsigned __stdcall thread_start_function(void* param);
-
- void start_thread();
-
- explicit thread(detail::thread_data_ptr data);
-
- detail::thread_data_ptr get_thread_info() const;
- public:
- thread();
- ~thread();
-
- template <class F>
- explicit thread(F f):
- thread_info(detail::heap_new<thread_data<F> >(f))
- {
- start_thread();
- }
- template <class F>
- thread(detail::thread_move_t<F> f):
- thread_info(detail::heap_new<thread_data<F> >(f))
- {
- start_thread();
- }
-
- thread(detail::thread_move_t<thread> x);
- thread& operator=(detail::thread_move_t<thread> x);
- operator detail::thread_move_t<thread>();
- detail::thread_move_t<thread> move();
-
- void swap(thread& x);
-
- class id;
- id get_id() const;
-
-
- bool joinable() const;
- void join();
- bool timed_join(const system_time& wait_until);
-
- template<typename TimeDuration>
- inline bool timed_join(TimeDuration const& rel_time)
- {
- return timed_join(get_system_time()+rel_time);
- }
- void detach();
-
- static unsigned hardware_concurrency();
-
- typedef detail::win32::handle native_handle_type;
- native_handle_type native_handle();
-
- // backwards compatibility
- bool operator==(const thread& other) const;
- bool operator!=(const thread& other) const;
-
- static void yield();
- static void sleep(const system_time& xt);
-
- // extensions
- void interrupt();
- 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>
- struct thread::thread_data<boost::reference_wrapper<F> >:
- detail::thread_data_base
- {
- F& f;
-
- thread_data(boost::reference_wrapper<F> f_):
- f(f_)
- {}
-
- void run()
- {
- f();
- }
- };
-
-
- namespace this_thread
- {
- class BOOST_THREAD_DECL disable_interruption
- {
- disable_interruption(const disable_interruption&);
- disable_interruption& operator=(const disable_interruption&);
-
- bool interruption_was_enabled;
- friend class restore_interruption;
- public:
- disable_interruption();
- ~disable_interruption();
- };
-
- class BOOST_THREAD_DECL restore_interruption
- {
- restore_interruption(const restore_interruption&);
- restore_interruption& operator=(const restore_interruption&);
- public:
- explicit restore_interruption(disable_interruption& d);
- ~restore_interruption();
- };
-
- thread::id BOOST_THREAD_DECL get_id();
-
- bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
- inline bool interruptible_wait(unsigned long milliseconds)
- {
- return interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
- }
-
- void BOOST_THREAD_DECL interruption_point();
- bool BOOST_THREAD_DECL interruption_enabled();
- bool BOOST_THREAD_DECL interruption_requested();
-
- void BOOST_THREAD_DECL yield();
- template<typename TimeDuration>
- void sleep(TimeDuration const& rel_time)
- {
- interruptible_wait(static_cast<unsigned long>(rel_time.total_milliseconds()));
- }
- }
-
- class thread::id
- {
- private:
- detail::thread_data_ptr thread_data;
-
- id(detail::thread_data_ptr thread_data_):
- thread_data(thread_data_)
- {}
- friend class thread;
- friend id this_thread::get_id();
- public:
- id():
- thread_data(0)
- {}
-
- bool operator==(const id& y) const
- {
- return thread_data==y.thread_data;
- }
-
- bool operator!=(const id& y) const
- {
- return thread_data!=y.thread_data;
- }
-
- bool operator<(const id& y) const
- {
- return thread_data<y.thread_data;
- }
-
- bool operator>(const id& y) const
- {
- return y.thread_data<thread_data;
- }
-
- bool operator<=(const id& y) const
- {
- return !(y.thread_data<thread_data);
- }
-
- bool operator>=(const id& y) const
- {
- return !(thread_data<y.thread_data);
- }
-
- template<class charT, class traits>
- friend std::basic_ostream<charT, traits>&
- operator<<(std::basic_ostream<charT, traits>& os, const id& x)
- {
- if(x.thread_data)
- {
- return os<<x.thread_data;
- }
- else
- {
- return os<<"{Not-any-thread}";
- }
- }
-
- void interrupt()
- {
- if(thread_data)
- {
- thread_data->interrupt();
- }
- }
-
- };
-
- inline bool thread::operator==(const thread& other) const
- {
- return get_id()==other.get_id();
- }
-
- inline bool thread::operator!=(const thread& other) const
- {
- return get_id()!=other.get_id();
- }
-
- namespace detail
- {
- struct thread_exit_function_base
- {
- virtual ~thread_exit_function_base()
- {}
- virtual void operator()() const=0;
- };
-
- template<typename F>
- struct thread_exit_function:
- thread_exit_function_base
- {
- F f;
-
- thread_exit_function(F f_):
- f(f_)
- {}
-
- void operator()() const
- {
- f();
- }
- };
-
- void add_thread_exit_function(thread_exit_function_base*);
- }
-
- namespace this_thread
- {
- template<typename F>
- void at_thread_exit(F f)
- {
- detail::thread_exit_function_base* const thread_exit_func=detail::heap_new<detail::thread_exit_function<F> >(f);
- detail::add_thread_exit_function(thread_exit_func);
- }
- }
-
- class thread_group:
- private noncopyable
- {
- public:
- ~thread_group()
- {
- for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
- it!=end;
- ++it)
- {
- delete *it;
- }
- }
-
- template<typename F>
- thread* create_thread(F threadfunc)
- {
- boost::lock_guard<mutex> guard(m);
- std::auto_ptr<thread> new_thread(new thread(threadfunc));
- threads.push_back(new_thread.get());
- return new_thread.release();
- }
-
- void add_thread(thread* thrd)
- {
- if(thrd)
- {
- boost::lock_guard<mutex> guard(m);
- threads.push_back(thrd);
- }
- }
-
- void remove_thread(thread* thrd)
- {
- boost::lock_guard<mutex> guard(m);
- std::list<thread*>::iterator const it=std::find(threads.begin(),threads.end(),thrd);
- if(it!=threads.end())
- {
- threads.erase(it);
- }
- }
-
- void join_all()
- {
- boost::lock_guard<mutex> guard(m);
-
- for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
- it!=end;
- ++it)
- {
- (*it)->join();
- }
- }
-
- void interrupt_all()
- {
- boost::lock_guard<mutex> guard(m);
-
- for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
- it!=end;
- ++it)
- {
- (*it)->interrupt();
- }
- }
-
- size_t size() const
- {
- boost::lock_guard<mutex> guard(m);
- return threads.size();
- }
-
- private:
- std::list<thread*> threads;
- mutable mutex m;
- };
-}
-
-#ifdef BOOST_MSVC
-#pragma warning(pop)
-#endif
-
-#endif
Modified: branches/release/boost/thread/win32/thread_heap_alloc.hpp
==============================================================================
--- branches/release/boost/thread/win32/thread_heap_alloc.hpp (original)
+++ branches/release/boost/thread/win32/thread_heap_alloc.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -49,6 +49,8 @@
#endif
+#include <boost/config/abi_prefix.hpp>
+
namespace boost
{
namespace detail
@@ -69,7 +71,7 @@
}
template<typename T>
- T* heap_new()
+ inline T* heap_new()
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
try
@@ -84,8 +86,72 @@
}
}
+#ifdef BOOST_HAS_RVALUE_REFS
+ template<typename T,typename A1>
+ inline T* heap_new(A1&& a1)
+ {
+ void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
+ try
+ {
+ T* const data=new (heap_memory) T(static_cast<A1&&>(a1));
+ return data;
+ }
+ catch(...)
+ {
+ free_raw_heap_memory(heap_memory);
+ throw;
+ }
+ }
+ template<typename T,typename A1,typename A2>
+ inline T* heap_new(A1&& a1,A2&& a2)
+ {
+ void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
+ try
+ {
+ T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2));
+ return data;
+ }
+ catch(...)
+ {
+ free_raw_heap_memory(heap_memory);
+ throw;
+ }
+ }
+ template<typename T,typename A1,typename A2,typename A3>
+ inline T* heap_new(A1&& a1,A2&& a2,A3&& a3)
+ {
+ void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
+ try
+ {
+ T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2),
+ static_cast<A3&&>(a3));
+ return data;
+ }
+ catch(...)
+ {
+ free_raw_heap_memory(heap_memory);
+ throw;
+ }
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4>
+ inline T* heap_new(A1&& a1,A2&& a2,A3&& a3,A4&& a4)
+ {
+ void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
+ try
+ {
+ T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2),
+ static_cast<A3&&>(a3),static_cast<A4&&>(a4));
+ return data;
+ }
+ catch(...)
+ {
+ free_raw_heap_memory(heap_memory);
+ throw;
+ }
+ }
+#else
template<typename T,typename A1>
- T* heap_new(A1 a1)
+ inline T* heap_new_impl(A1 a1)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
try
@@ -99,9 +165,9 @@
throw;
}
}
-
+
template<typename T,typename A1,typename A2>
- T* heap_new(A1 a1,A2 a2)
+ inline T* heap_new_impl(A1 a1,A2 a2)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
try
@@ -117,7 +183,7 @@
}
template<typename T,typename A1,typename A2,typename A3>
- T* heap_new(A1 a1,A2 a2,A3 a3)
+ inline T* heap_new_impl(A1 a1,A2 a2,A3 a3)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
try
@@ -131,9 +197,9 @@
throw;
}
}
-
+
template<typename T,typename A1,typename A2,typename A3,typename A4>
- T* heap_new(A1 a1,A2 a2,A3 a3,A4 a4)
+ inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
try
@@ -147,9 +213,168 @@
throw;
}
}
+
+
+ template<typename T,typename A1>
+ inline T* heap_new(A1 const& a1)
+ {
+ return heap_new_impl<T,A1 const&>(a1);
+ }
+ template<typename T,typename A1>
+ inline T* heap_new(A1& a1)
+ {
+ return heap_new_impl<T,A1&>(a1);
+ }
+
+ template<typename T,typename A1,typename A2>
+ inline T* heap_new(A1 const& a1,A2 const& a2)
+ {
+ return heap_new_impl<T,A1 const&,A2 const&>(a1,a2);
+ }
+ template<typename T,typename A1,typename A2>
+ inline T* heap_new(A1& a1,A2 const& a2)
+ {
+ return heap_new_impl<T,A1&,A2 const&>(a1,a2);
+ }
+ template<typename T,typename A1,typename A2>
+ inline T* heap_new(A1 const& a1,A2& a2)
+ {
+ return heap_new_impl<T,A1 const&,A2&>(a1,a2);
+ }
+ template<typename T,typename A1,typename A2>
+ inline T* heap_new(A1& a1,A2& a2)
+ {
+ return heap_new_impl<T,A1&,A2&>(a1,a2);
+ }
+
+ template<typename T,typename A1,typename A2,typename A3>
+ inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3)
+ {
+ return heap_new_impl<T,A1 const&,A2 const&,A3 const&>(a1,a2,a3);
+ }
+ template<typename T,typename A1,typename A2,typename A3>
+ inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3)
+ {
+ return heap_new_impl<T,A1&,A2 const&,A3 const&>(a1,a2,a3);
+ }
+ template<typename T,typename A1,typename A2,typename A3>
+ inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3)
+ {
+ return heap_new_impl<T,A1 const&,A2&,A3 const&>(a1,a2,a3);
+ }
+ template<typename T,typename A1,typename A2,typename A3>
+ inline T* heap_new(A1& a1,A2& a2,A3 const& a3)
+ {
+ return heap_new_impl<T,A1&,A2&,A3 const&>(a1,a2,a3);
+ }
+
+ template<typename T,typename A1,typename A2,typename A3>
+ inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3)
+ {
+ return heap_new_impl<T,A1 const&,A2 const&,A3&>(a1,a2,a3);
+ }
+ template<typename T,typename A1,typename A2,typename A3>
+ inline T* heap_new(A1& a1,A2 const& a2,A3& a3)
+ {
+ return heap_new_impl<T,A1&,A2 const&,A3&>(a1,a2,a3);
+ }
+ template<typename T,typename A1,typename A2,typename A3>
+ inline T* heap_new(A1 const& a1,A2& a2,A3& a3)
+ {
+ return heap_new_impl<T,A1 const&,A2&,A3&>(a1,a2,a3);
+ }
+ template<typename T,typename A1,typename A2,typename A3>
+ inline T* heap_new(A1& a1,A2& a2,A3& a3)
+ {
+ return heap_new_impl<T,A1&,A2&,A3&>(a1,a2,a3);
+ }
+
+ template<typename T,typename A1,typename A2,typename A3,typename A4>
+ inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4 const& a4)
+ {
+ return heap_new_impl<T,A1 const&,A2 const&,A3 const&,A4 const&>(a1,a2,a3,a4);
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4>
+ inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4 const& a4)
+ {
+ return heap_new_impl<T,A1&,A2 const&,A3 const&,A4 const&>(a1,a2,a3,a4);
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4>
+ inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4 const& a4)
+ {
+ return heap_new_impl<T,A1 const&,A2&,A3 const&,A4 const&>(a1,a2,a3,a4);
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4>
+ inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4 const& a4)
+ {
+ return heap_new_impl<T,A1&,A2&,A3 const&,A4 const&>(a1,a2,a3,a4);
+ }
+
+ template<typename T,typename A1,typename A2,typename A3,typename A4>
+ inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4 const& a4)
+ {
+ return heap_new_impl<T,A1 const&,A2 const&,A3&,A4 const&>(a1,a2,a3,a4);
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4>
+ inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4 const& a4)
+ {
+ return heap_new_impl<T,A1&,A2 const&,A3&,A4 const&>(a1,a2,a3,a4);
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4>
+ inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4 const& a4)
+ {
+ return heap_new_impl<T,A1 const&,A2&,A3&,A4 const&>(a1,a2,a3,a4);
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4>
+ inline T* heap_new(A1& a1,A2& a2,A3& a3,A4 const& a4)
+ {
+ return heap_new_impl<T,A1&,A2&,A3&,A4 const&>(a1,a2,a3,a4);
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4>
+ inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4& a4)
+ {
+ return heap_new_impl<T,A1 const&,A2 const&,A3 const&,A4&>(a1,a2,a3,a4);
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4>
+ inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4& a4)
+ {
+ return heap_new_impl<T,A1&,A2 const&,A3 const&,A4&>(a1,a2,a3,a4);
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4>
+ inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4& a4)
+ {
+ return heap_new_impl<T,A1 const&,A2&,A3 const&,A4&>(a1,a2,a3,a4);
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4>
+ inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4& a4)
+ {
+ return heap_new_impl<T,A1&,A2&,A3 const&,A4&>(a1,a2,a3,a4);
+ }
+
+ template<typename T,typename A1,typename A2,typename A3,typename A4>
+ inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4& a4)
+ {
+ return heap_new_impl<T,A1 const&,A2 const&,A3&,A4&>(a1,a2,a3,a4);
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4>
+ inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4& a4)
+ {
+ return heap_new_impl<T,A1&,A2 const&,A3&,A4&>(a1,a2,a3,a4);
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4>
+ inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4& a4)
+ {
+ return heap_new_impl<T,A1 const&,A2&,A3&,A4&>(a1,a2,a3,a4);
+ }
+ template<typename T,typename A1,typename A2,typename A3,typename A4>
+ inline T* heap_new(A1& a1,A2& a2,A3& a3,A4& a4)
+ {
+ return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4);
+ }
+#endif
template<typename T>
- void heap_delete(T* data)
+ inline void heap_delete(T* data)
{
data->~T();
free_raw_heap_memory(data);
@@ -166,5 +391,7 @@
}
}
+#include <boost/config/abi_suffix.hpp>
+
#endif
Modified: branches/release/boost/thread/win32/thread_primitives.hpp
==============================================================================
--- branches/release/boost/thread/win32/thread_primitives.hpp (original)
+++ branches/release/boost/thread/win32/thread_primitives.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -13,10 +13,12 @@
#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/thread/exceptions.hpp>
+#include <boost/detail/interlocked.hpp>
#include <algorithm>
#if defined( BOOST_USE_WINDOWS_H )
# include <windows.h>
+
namespace boost
{
namespace detail
@@ -146,6 +148,8 @@
# error "Win32 functions not available"
#endif
+#include <boost/config/abi_prefix.hpp>
+
namespace boost
{
namespace detail
@@ -277,5 +281,117 @@
}
}
+#if defined(BOOST_MSVC) && (_MSC_VER>=1400) && !defined(UNDER_CE)
+#if _MSC_VER==1400
+extern "C" unsigned char _interlockedbittestandset(long *a,long b);
+extern "C" unsigned char _interlockedbittestandreset(long *a,long b);
+#else
+extern "C" unsigned char _interlockedbittestandset(volatile long *a,long b);
+extern "C" unsigned char _interlockedbittestandreset(volatile long *a,long b);
+#endif
+
+#pragma intrinsic(_interlockedbittestandset)
+#pragma intrinsic(_interlockedbittestandreset)
+
+namespace boost
+{
+ namespace detail
+ {
+ namespace win32
+ {
+ inline bool interlocked_bit_test_and_set(long* x,long bit)
+ {
+ return _interlockedbittestandset(x,bit)!=0;
+ }
+
+ inline bool interlocked_bit_test_and_reset(long* x,long bit)
+ {
+ return _interlockedbittestandreset(x,bit)!=0;
+ }
+
+ }
+ }
+}
+#define BOOST_THREAD_BTS_DEFINED
+#elif (defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)) && defined(_M_IX86)
+namespace boost
+{
+ namespace detail
+ {
+ namespace win32
+ {
+ inline bool interlocked_bit_test_and_set(long* x,long bit)
+ {
+ __asm {
+ mov eax,bit;
+ mov edx,x;
+ lock bts [edx],eax;
+ setc al;
+ };
+ }
+
+ inline bool interlocked_bit_test_and_reset(long* x,long bit)
+ {
+ __asm {
+ mov eax,bit;
+ mov edx,x;
+ lock btr [edx],eax;
+ setc al;
+ };
+ }
+
+ }
+ }
+}
+#define BOOST_THREAD_BTS_DEFINED
+#endif
+
+#ifndef BOOST_THREAD_BTS_DEFINED
+
+namespace boost
+{
+ namespace detail
+ {
+ namespace win32
+ {
+ inline bool interlocked_bit_test_and_set(long* x,long bit)
+ {
+ long const value=1<<bit;
+ long old=*x;
+ do
+ {
+ long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old|value,old);
+ if(current==old)
+ {
+ break;
+ }
+ old=current;
+ }
+ while(true);
+ return (old&value)!=0;
+ }
+
+ inline bool interlocked_bit_test_and_reset(long* x,long bit)
+ {
+ long const value=1<<bit;
+ long old=*x;
+ do
+ {
+ long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old&~value,old);
+ if(current==old)
+ {
+ break;
+ }
+ old=current;
+ }
+ while(true);
+ return (old&value)!=0;
+ }
+ }
+ }
+}
+#endif
+
+#include <boost/config/abi_suffix.hpp>
#endif
Deleted: branches/release/boost/thread/win32/tss.hpp
==============================================================================
--- branches/release/boost/thread/win32/tss.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
+++ (empty file)
@@ -1,103 +0,0 @@
-#ifndef BOOST_THREAD_WIN32_TSS_HPP
-#define BOOST_THREAD_WIN32_TSS_HPP
-// 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)
-// (C) Copyright 2007 Anthony Williams
-
-#include <boost/shared_ptr.hpp>
-#include "thread_heap_alloc.hpp"
-
-namespace boost
-{
- namespace detail
- {
- struct tss_cleanup_function
- {
- virtual ~tss_cleanup_function()
- {}
-
- virtual void operator()(void* data)=0;
- };
-
- BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
- BOOST_THREAD_DECL void* get_tss_data(void const* key);
- }
-
- template <typename T>
- class thread_specific_ptr
- {
- private:
- thread_specific_ptr(thread_specific_ptr&);
- thread_specific_ptr& operator=(thread_specific_ptr&);
-
- struct delete_data:
- detail::tss_cleanup_function
- {
- void operator()(void* data)
- {
- delete static_cast<T*>(data);
- }
- };
-
- struct run_custom_cleanup_function:
- detail::tss_cleanup_function
- {
- void (*cleanup_function)(T*);
-
- explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)):
- cleanup_function(cleanup_function_)
- {}
-
- void operator()(void* data)
- {
- cleanup_function(static_cast<T*>(data));
- }
- };
-
-
- boost::shared_ptr<detail::tss_cleanup_function> cleanup;
-
- public:
- thread_specific_ptr():
- cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
- {}
- explicit thread_specific_ptr(void (*func_)(T*)):
- cleanup(detail::heap_new<run_custom_cleanup_function>(func_),detail::do_heap_delete<run_custom_cleanup_function>())
- {}
- ~thread_specific_ptr()
- {
- reset();
- }
-
- T* get() const
- {
- return static_cast<T*>(detail::get_tss_data(this));
- }
- T* operator->() const
- {
- return get();
- }
- T& operator*() const
- {
- return *get();
- }
- T* release()
- {
- T* const temp=get();
- detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,false);
- return temp;
- }
- void reset(T* new_value=0)
- {
- T* const current_value=get();
- if(current_value!=new_value)
- {
- detail::set_tss_data(this,cleanup,new_value,true);
- }
- }
- };
-}
-
-
-#endif
Modified: branches/release/boost/thread/xtime.hpp
==============================================================================
--- branches/release/boost/thread/xtime.hpp (original)
+++ branches/release/boost/thread/xtime.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -1,6 +1,6 @@
// Copyright (C) 2001-2003
// William E. Kempf
-// Copyright (C) 2007 Anthony Williams
+// Copyright (C) 2007-8 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)
@@ -14,6 +14,8 @@
#include <boost/thread/thread_time.hpp>
#include <boost/date_time/posix_time/conversion.hpp>
+#include <boost/config/abi_prefix.hpp>
+
namespace boost {
enum xtime_clock_types
@@ -56,7 +58,7 @@
inline xtime get_xtime(boost::system_time const& abs_time)
{
- xtime res={0};
+ xtime res;
boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0);
res.sec=static_cast<xtime::xtime_sec_t>(time_since_epoch.total_seconds());
@@ -85,4 +87,6 @@
} // namespace boost
+#include <boost/config/abi_suffix.hpp>
+
#endif //BOOST_XTIME_WEK070601_HPP
Modified: branches/release/boost/utility/addressof.hpp
==============================================================================
--- branches/release/boost/utility/addressof.hpp (original)
+++ branches/release/boost/utility/addressof.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -1,6 +1,7 @@
// Copyright (C) 2002 Brad King (brad.king_at_[hidden])
// Douglas Gregor (gregod_at_[hidden])
-// Peter Dimov
+//
+// Copyright (C) 2002, 2008 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -14,27 +15,31 @@
# include <boost/config.hpp>
# include <boost/detail/workaround.hpp>
-namespace boost {
-
-// Do not make addressof() inline. Breaks MSVC 7. (Peter Dimov)
+namespace boost
+{
-// VC7 strips const from nested classes unless we add indirection here
-# if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
+namespace detail
+{
-template<class T> struct _addp
+template<class T> struct addressof_impl
{
- typedef T * type;
+ static inline T * f( T & v, long )
+ {
+ return reinterpret_cast<T*>(
+ &const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
+ }
+
+ static inline T * f( T * v, int )
+ {
+ return v;
+ }
};
-
-template <typename T> typename _addp<T>::type
-# else
-template <typename T> T*
-# endif
-addressof(T& v)
+} // namespace detail
+
+template<class T> T * addressof( T & v )
{
- return reinterpret_cast<T*>(
- &const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
+ return boost::detail::addressof_impl<T>::f( v, 0 );
}
// Borland doesn't like casting an array reference to a char reference
@@ -53,6 +58,6 @@
}
# endif
-}
+} // namespace boost
#endif // BOOST_UTILITY_ADDRESSOF_HPP
Modified: branches/release/libs/bind/bind.html
==============================================================================
--- branches/release/libs/bind/bind.html (original)
+++ branches/release/libs/bind/bind.html 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -60,6 +60,7 @@
<h4 style="MARGIN-LEFT: 40pt"><A href="#err_long_form">Inappropriate use of
bind<R>(f, ...)</A></h4>
<h4 style="MARGIN-LEFT: 40pt">Binding a nonstandard function</h4>
+ <h4 style="MARGIN-LEFT: 40pt">Binding an overloaded function</h4>
<h4 style="MARGIN-LEFT: 40pt">const in signatures</h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#err_msvc_using">MSVC specific: using
boost::bind;</A></h4>
@@ -188,6 +189,27 @@
</pre>
<p>[Note: the ability to omit the return type is not available on all compilers.]
</p>
+ <P>By default, <STRONG>bind</STRONG> makes a copy of the provided function object. <code>
+ boost::ref</code> and <code>boost::cref</code> can be used to make it store
+ a reference to the function object, rather than a copy. This can be useful when
+ the function object is noncopyable, expensive to copy, or contains state; of
+ course, in this case the programmer is expected to ensure that the function
+ object is not destroyed while it's still being used.</P>
+ <pre>struct F2
+{
+ int s;
+
+ typedef void result_type;
+ void operator()( int x ) { s += x; }
+};
+
+F2 f2 = { 0 };
+int a[] = { 1, 2, 3 };
+
+std::for_each( a, a+3, bind( ref(f2), _1 ) );
+
+assert( f2.s == 6 );
+</pre>
<h3><a name="with_member_pointers">Using bind with pointers to members</a></h3>
<p>Pointers to member functions and pointers to data members are not function
objects, because they do not support <tt>operator()</tt>. For convenience, <b>bind</b>
@@ -285,21 +307,23 @@
evaluation, use <tt>protect(bind(f, ...))</tt>.</P>
<h3><a name="operators">Overloaded operators</a> (new in Boost 1.33)</h3>
<p>For convenience, the function objects produced by <tt>bind</tt> overload the
- logical not operator <STRONG>!</STRONG> and the relational operators <STRONG>==</STRONG>,
- <STRONG>!=</STRONG>, <STRONG><</STRONG>, <STRONG><=</STRONG>, <STRONG>></STRONG>,
- <STRONG>>=</STRONG>.</p>
+ logical not operator <code>!</code> and the relational and logical operators <code>==</code>,
+ <code>!=</code>, <code><</code>, <code><=</code>, <code>></code>, <code>>=</code>,
+ <code>&&</code>, <code>||</code>.</p>
<P><tt>!bind(f, ...)</tt> is equivalent to <tt>bind( <EM>logical_not</EM>(), bind(f,
...) )</tt>, where <tt><EM>logical_not</EM></tt> is a function object that
takes one argument <tt>x</tt> and returns <tt>!x</tt>.</P>
- <P><tt>bind(f, ...) <EM>op</EM> x</tt>, where <EM>op</EM> is a relational operator,
- is equivalent to <tt>bind( <EM>relation</EM>(), bind(f, ...), x )</tt>, where <em>relation</em>
- is a function object that takes two arguments <tt>a</tt> and <tt>b</tt> and
- returns <tt>a <EM>op</EM> b</tt>.</P>
+ <P><tt>bind(f, ...) <EM>op</EM> x</tt>, where <EM>op</EM> is a relational or
+ logical operator, is equivalent to <tt>bind( <EM>relation</EM>(), bind(f, ...), x )</tt>,
+ where <em>relation</em> is a function object that takes two arguments <tt>a</tt>
+ and <tt>b</tt> and returns <tt>a <EM>op</EM> b</tt>.</P>
<P>What this means in practice is that you can conveniently negate the result of <tt>bind</tt>:</P>
<P><tt>std::remove_if( first, last, !bind( &X::visible, _1 ) ); // remove invisible
objects</tt></P>
<P>and compare the result of <tt>bind</tt> against a value:</P>
- <P><tt>std::find_if( first, last, bind( &X::name, _1 ) == "peter" );</tt></P>
+ <P><tt>std::find_if( first, last, bind( &X::name, _1 ) == "Peter" );</tt></P>
+ <P><tt>std::find_if( first, last, bind( &X::name, _1 ) == "Peter" || bind(
+ &X::name, _1 ) == "Paul" );</tt></P>
<P>against a placeholder:</P>
<P><tt>bind( &X::name, _1 ) == _2</tt></P>
<P>or against another <tt>bind</tt> expression:</P>
@@ -362,10 +386,12 @@
}
</pre>
<h2><a name="Limitations">Limitations</a></h2>
- <p>The function objects generated by <b>bind</b> take their arguments by reference
- and cannot, therefore, accept non-const temporaries or literal constants. This
- is an inherent limitation of the C++ language, known as <A href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1385.htm">
- the forwarding problem</A>.</p>
+ <p>As a general rule, the function objects generated by <b>bind</b> take their
+ arguments by reference and cannot, therefore, accept non-const temporaries or
+ literal constants. This is an inherent limitation of the C++ language in its
+ current (2003) incarnation, known as <A href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1385.htm">
+ the forwarding problem</A>. (It will be fixed in the next standard, usually
+ called C++0x.)</p>
<p>The library uses signatures of the form
</p>
<pre>template<class T> void f(T & t);
@@ -373,17 +399,17 @@
<p>to accept arguments of arbitrary types and pass them on unmodified. As noted,
this does not work with non-const r-values.
</p>
- <p>An oft-proposed "solution" to this problem is to add an overload:
+ <p>On compilers that support partial ordering of function templates, a possible
+ solution is to add an overload:
</p>
<pre>template<class T> void f(T & t);
template<class T> void f(T const & t);
</pre>
- <p>Unfortunately, this (a) requires providing 512 overloads for nine arguments and
- (b) does not actually work for const arguments, both l- and r-values, since the
- two templates produce the exact same signature and cannot be partially ordered.
- </p>
- <p>[Note: this is a dark corner of the language, and the <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#214">
- corresponding issue</a> has only recently been resolved.]
+ <p>Unfortunately, this requires providing 512 overloads for nine arguments, which
+ is impractical. The library chooses a small subset: for up to two arguments, it
+ provides the const overloads in full, for arities of three and more it provides
+ a single additional overload with all of the arguments taken by const
+ reference. This covers a reasonable portion of the use cases.
</p>
<h2><a name="FAQ">Frequently Asked Questions</a></h2>
<h3><a name="Q_doesnt_compile">Why doesn't this compile?</a></h3>
@@ -528,6 +554,37 @@
recognized by the short form of bind.
</p>
<P>See also "__stdcall" and "pascal" Support.</P>
+ <h3><a name="err_overloaded">Binding an overloaded function</a></h3>
+ <p>An attempt to bind an overloaded function usually results in an error, as there
+ is no way to tell which overload was meant to be bound. This is a common
+ problem with member functions with two overloads, const and non-const, as in
+ this simplified example:</p>
+ <pre>struct X
+{
+ int& get();
+ int const& get() const;
+};
+
+int main()
+{
+ boost::bind( &X::get, _1 );
+}
+</pre>
+ <P>The ambiguity can be resolved manually by casting the (member) function pointer
+ to the desired type:</P>
+<pre>int main()
+{
+ boost::bind( static_cast< int const& (X::*) () const >( &X::get ), _1 );
+}
+</pre>
+ <P>Another, arguably more readable, alternative is to introduce a temporary
+ variable:</P>
+<pre>int main()
+{
+ int const& (X::*get) () const = &X::get;
+ boost::bind( get, _1 );
+}
+</pre>
<h3><a name="err_const_arg"><b>const</b> in signatures</a></h3>
<p>Some compilers, including MSVC 6.0 and Borland C++ 5.5.1, have problems with the
top-level <b>const</b> in function signatures:
@@ -859,7 +916,7 @@
by Jaakko Järvi;
<li>
The Lambda Library
- (now part of Boost) by Jaakko Järvi and Gary Powell (the successor to the
+ (now part of Boost) by Jaakko Järvi and Gary Powell (the successor to the
Binder Library);
<li>
<a href="http://more.sourceforge.net/">Extensions to the STL</a> by Petter
@@ -890,7 +947,7 @@
<br>
<br>
<small>Copyright © 2001, 2002 by Peter Dimov and Multi Media Ltd. Copyright
- 2003-2005 Peter Dimov. Distributed under the Boost Software License, Version
+ 2003-2008 Peter Dimov. 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.</small></p>
</body>
Modified: branches/release/libs/bind/test/Jamfile.v2
==============================================================================
--- branches/release/libs/bind/test/Jamfile.v2 (original)
+++ branches/release/libs/bind/test/Jamfile.v2 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -27,10 +27,15 @@
[ run bind_visit_test.cpp ]
[ run bind_placeholder_test.cpp ]
[ run bind_rvalue_test.cpp ]
+ [ run bind_and_or_test.cpp ]
[ run mem_fn_test.cpp ]
[ run mem_fn_void_test.cpp ]
[ run mem_fn_derived_test.cpp ]
[ run mem_fn_eq_test.cpp ]
[ run mem_fn_dm_test.cpp ]
[ run mem_fn_rv_test.cpp ]
+ [ run ref_fn_test.cpp ]
+ [ run bind_fnobj2_test.cpp ]
+ [ run bind_fn2_test.cpp ]
+ [ run bind_mf2_test.cpp ]
;
Modified: branches/release/libs/bind/test/bind_lookup_problem_test.cpp
==============================================================================
--- branches/release/libs/bind/test/bind_lookup_problem_test.cpp (original)
+++ branches/release/libs/bind/test/bind_lookup_problem_test.cpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -1,7 +1,7 @@
//
// bind_lookup_problem_test.cpp
//
-// Copyright (C) Markus Schöpflin 2005.
+// Copyright (C) Markus Schoepflin 2005.
//
// Use, modification, and distribution are subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Modified: branches/release/libs/thread/doc/changes.qbk
==============================================================================
--- branches/release/libs/thread/doc/changes.qbk (original)
+++ branches/release/libs/thread/doc/changes.qbk 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -44,7 +44,14 @@
but did not lock it on construction. This facility has now been replaced with the constructor that takes a
`boost::defer_lock_type` as the second parameter: ``boost::mutex::scoped_lock some_lock(some_mutex,boost::defer_lock);``
+* The `locked()` member function of the `scoped_lock` types has been renamed to __owns_lock_ref__.
+
+* You can no longer obtain a __thread__ instance representing the current thread: a default-constructed __thread__ object is not
+associated with any thread. The only use for such a thread object was to support the comparison operators: this functionality has
+been moved to __thread_id__.
+
* The broken `boost::read_write_mutex` has been replaced with __shared_mutex__.
+* __mutex__ is now never recursive. For Boost releases prior to 1.35 __mutex__ was recursive on Windows and not on POSIX platforms.
[endsect]
Modified: branches/release/libs/thread/doc/mutex_concepts.qbk
==============================================================================
--- branches/release/libs/thread/doc/mutex_concepts.qbk (original)
+++ branches/release/libs/thread/doc/mutex_concepts.qbk 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -373,6 +373,7 @@
class unique_lock
{
public:
+ unique_lock();
explicit unique_lock(Lockable& m_);
unique_lock(Lockable& m_,adopt_lock_t);
unique_lock(Lockable& m_,defer_lock_t);
@@ -426,6 +427,20 @@
__lockable_concept_type__ object by a particular thread, and the member functions that release ownership of the lock state
(including the destructor) must be called by the same thread that acquired ownership of the lock state.
+[section:defaultconstructor `unique_lock()`]
+
+[variablelist
+
+[[Effects:] [Creates a lock object with no associated mutex.]]
+
+[[Postcondition:] [__owns_lock_ref__ returns `false`. __mutex_func_ref__ returns `NULL`.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
[section:constructor `unique_lock(Lockable & m)`]
[variablelist
@@ -599,6 +614,7 @@
class shared_lock
{
public:
+ shared_lock();
explicit shared_lock(Lockable& m_);
shared_lock(Lockable& m_,adopt_lock_t);
shared_lock(Lockable& m_,defer_lock_t);
@@ -644,6 +660,20 @@
ownership of a __lockable_concept_type__ object by a particular thread, and the member functions that release ownership of the lock
state (including the destructor) must be called by the same thread that acquired ownership of the lock state.
+[section:defaultconstructor `shared_lock()`]
+
+[variablelist
+
+[[Effects:] [Creates a lock object with no associated mutex.]]
+
+[[Postcondition:] [__owns_lock_ref__ returns `false`. __mutex_func_ref__ returns `NULL`.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
[section:constructor `shared_lock(Lockable & m)`]
[variablelist
Modified: branches/release/libs/thread/doc/mutexes.qbk
==============================================================================
--- branches/release/libs/thread/doc/mutexes.qbk (original)
+++ branches/release/libs/thread/doc/mutexes.qbk 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -12,6 +12,9 @@
void lock();
bool try_lock();
void unlock();
+
+ typedef platform-specific-type native_handle_type;
+ native_handle_type native_handle();
typedef unique_lock<mutex> scoped_lock;
typedef scoped_lock scoped_try_lock;
@@ -20,6 +23,23 @@
__mutex__ implements the __lockable_concept__ to provide an exclusive-ownership mutex. At most one thread can own the lock on a given
instance of __mutex__ at any time. Multiple concurrent calls to __lock_ref__, __try_lock_ref__ and __unlock_ref__ shall be permitted.
+[section:nativehandle Member function `native_handle()`]
+
+ typedef platform-specific-type native_handle_type;
+ native_handle_type native_handle();
+
+[variablelist
+
+[[Effects:] [Returns an instance of `native_handle_type` that can be used with platform-specific APIs to manipulate the underlying
+implementation. If no such instance exists, `native_handle()` and `native_handle_type` are not present.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+
[endsect]
[section:try_mutex Typedef `try_mutex`]
@@ -47,6 +67,9 @@
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time);
+ typedef platform-specific-type native_handle_type;
+ native_handle_type native_handle();
+
typedef unique_lock<timed_mutex> scoped_timed_lock;
typedef scoped_timed_lock scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
@@ -56,6 +79,22 @@
lock on a given instance of __timed_mutex__ at any time. Multiple concurrent calls to __lock_ref__, __try_lock_ref__,
__timed_lock_ref__, __timed_lock_duration_ref__ and __unlock_ref__ shall be permitted.
+[section:nativehandle Member function `native_handle()`]
+
+ typedef platform-specific-type native_handle_type;
+ native_handle_type native_handle();
+
+[variablelist
+
+[[Effects:] [Returns an instance of `native_handle_type` that can be used with platform-specific APIs to manipulate the underlying
+implementation. If no such instance exists, `native_handle()` and `native_handle_type` are not present.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
[endsect]
[section:recursive_mutex Class `recursive_mutex`]
@@ -70,6 +109,9 @@
void lock();
bool try_lock();
void unlock();
+
+ typedef platform-specific-type native_handle_type;
+ native_handle_type native_handle();
typedef unique_lock<recursive_mutex> scoped_lock;
typedef scoped_lock scoped_try_lock;
@@ -81,6 +123,22 @@
__lock_ref__ or __try_lock_ref__ to acquire an additional level of ownership of the mutex. __unlock_ref__ must be called once for
each level of ownership acquired by a single thread before ownership can be acquired by another thread.
+[section:nativehandle Member function `native_handle()`]
+
+ typedef platform-specific-type native_handle_type;
+ native_handle_type native_handle();
+
+[variablelist
+
+[[Effects:] [Returns an instance of `native_handle_type` that can be used with platform-specific APIs to manipulate the underlying
+implementation. If no such instance exists, `native_handle()` and `native_handle_type` are not present.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
[endsect]
[section:recursive_try_mutex Typedef `recursive_try_mutex`]
@@ -108,6 +166,9 @@
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time);
+
+ typedef platform-specific-type native_handle_type;
+ native_handle_type native_handle();
typedef unique_lock<recursive_timed_mutex> scoped_lock;
typedef scoped_lock scoped_try_lock;
@@ -121,6 +182,22 @@
__timed_lock_duration_ref__ or __try_lock_ref__ to acquire an additional level of ownership of the mutex. __unlock_ref__ must be
called once for each level of ownership acquired by a single thread before ownership can be acquired by another thread.
+[section:nativehandle Member function `native_handle()`]
+
+ typedef platform-specific-type native_handle_type;
+ native_handle_type native_handle();
+
+[variablelist
+
+[[Effects:] [Returns an instance of `native_handle_type` that can be used with platform-specific APIs to manipulate the underlying
+implementation. If no such instance exists, `native_handle()` and `native_handle_type` are not present.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
[endsect]
[include shared_mutex_ref.qbk]
Modified: branches/release/libs/thread/doc/thread.qbk
==============================================================================
--- branches/release/libs/thread/doc/thread.qbk (original)
+++ branches/release/libs/thread/doc/thread.qbk 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -147,4 +147,6 @@
[include tss.qbk]
+[include time.qbk]
+
[include acknowledgements.qbk]
Modified: branches/release/libs/thread/doc/thread_ref.qbk
==============================================================================
--- branches/release/libs/thread/doc/thread_ref.qbk (original)
+++ branches/release/libs/thread/doc/thread_ref.qbk 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -17,6 +17,13 @@
some_thread.join();
}
+[Note: On compilers that support rvalue references, __thread__ provides a proper move constructor and move-assignment operator, and
+therefore meets the C++0x ['MoveConstructible] and ['MoveAssignable] concepts. With such compilers, __thread__ can therefore be used
+with containers that support those concepts.
+
+For other compilers, move support is provided with a move emulation layer, so containers must explicitly detect that move emulation
+layer. See <boost/thread/detail/move.hpp> for details.]
+
[heading Launching threads]
A new thread is launched by passing an object of a callable type that can be invoked with no parameters to the constructor. The
@@ -43,11 +50,21 @@
// this leads to undefined behaviour
If you wish to construct an instance of __thread__ with a function or callable object that requires arguments to be supplied,
-this can be done using `boost::bind`:
+this can be done by passing additional arguments to the __thread__ constructor:
void find_the_question(int the_answer);
- boost::thread deep_thought_2(boost::bind(find_the_question,42));
+ boost::thread deep_thought_2(find_the_question,42);
+
+The arguments are ['copied] into the internal thread structure: if a reference is required, use `boost::ref`, just as for references
+to callable functions.
+
+There is an unspecified limit on the number of additional arguments that can be passed.
+
+[heading Exceptions in thread functions]
+
+If the function or callable object passed to the __thread__ constructor propagates an exception when invoked that is not of type
+__thread_interrupted__, `std::terminate()` is called.
[heading Joining and detaching]
@@ -189,6 +206,8 @@
static void sleep(const system_time& xt);
};
+ void swap(thread& lhs,thread& rhs);
+
[section:default_constructor Default Constructor]
thread();
@@ -212,7 +231,9 @@
[[Preconditions:] [`Callable` must by copyable.]]
-[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created thread of execution.]]
+[[Effects:] [`func` is copied into storage managed internally by the thread library, and that copy is invoked on a newly-created
+thread of execution. If this invocation results in an exception being propagated into the internals of the thread library that is
+not of type __thread_interrupted__, then `std::terminate()` will be called.]]
[[Postconditions:] [`*this` refers to the newly created thread of execution.]]
@@ -306,7 +327,7 @@
[variablelist
-[[Effects:] [If `*this` refers to a thread of execution, that thread of execution becomes detached, and longer has an associated __thread__ object.]]
+[[Effects:] [If `*this` refers to a thread of execution, that thread of execution becomes detached, and no longer has an associated __thread__ object.]]
[[Postconditions:] [`*this` no longer refers to any thread of execution.]]
@@ -364,6 +385,22 @@
[endsect]
+[section:nativehandle Member function `native_handle()`]
+
+ typedef platform-specific-type native_handle_type;
+ native_handle_type native_handle();
+
+[variablelist
+
+[[Effects:] [Returns an instance of `native_handle_type` that can be used with platform-specific APIs to manipulate the underlying
+implementation. If no such instance exists, `native_handle()` and `native_handle_type` are not present.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
[section:equals `operator==`]
bool operator==(const thread& other) const;
@@ -416,6 +453,36 @@
[endsect]
+[section:swap Member function `swap()`]
+
+ void swap(thread& other);
+
+[variablelist
+
+[[Effects:] [Exchanges the threads of execution associated with `*this` and `other`, so `*this` is associated with the thread of
+execution associated with `other` prior to the call, and vice-versa.]]
+
+[[Postconditions:] [`this->get_id()` returns the same value as `other.get_id()` prior to the call. `other.get_id()` returns the same
+value as `this->get_id()` prior to the call.]]
+
+[[Throws:] [Nothing.]]
+
+]
+
+[endsect]
+
+[section:non_member_swap Non-member function `swap()`]
+
+ void swap(thread& lhs,thread& rhs);
+
+[variablelist
+
+[[Effects:] [[link thread.thread_management.thread.swap `lhs.swap(rhs)`].]]
+
+]
+
+[endsect]
+
[section:id Class `boost::thread::id`]
@@ -471,7 +538,7 @@
[variablelist
-[[Returns:] [`true` if `*this` and `y` represent the different threads of execution, or one represents a thread of execution, and
+[[Returns:] [`true` if `*this` and `y` represent different threads of execution, or one represents a thread of execution, and
the other represent __not_a_thread__, `false` otherwise.]]
[[Throws:] [Nothing]]
Modified: branches/release/libs/thread/example/condition.cpp
==============================================================================
--- branches/release/libs/thread/example/condition.cpp (original)
+++ branches/release/libs/thread/example/condition.cpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -46,11 +46,16 @@
bounded_buffer buf(2);
+boost::mutex io_mutex;
+
void sender() {
int n = 0;
while (n < 100) {
buf.send(n);
- std::cout << "sent: " << n << std::endl;
+ {
+ boost::mutex::scoped_lock io_lock(io_mutex);
+ std::cout << "sent: " << n << std::endl;
+ }
++n;
}
buf.send(-1);
@@ -60,7 +65,10 @@
int n;
do {
n = buf.receive();
- std::cout << "received: " << n << std::endl;
+ {
+ boost::mutex::scoped_lock io_lock(io_mutex);
+ std::cout << "received: " << n << std::endl;
+ }
} while (n != -1); // -1 indicates end of buffer
}
Modified: branches/release/libs/thread/src/pthread/thread.cpp
==============================================================================
--- branches/release/libs/thread/src/pthread/thread.cpp (original)
+++ branches/release/libs/thread/src/pthread/thread.cpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -1,6 +1,6 @@
// Copyright (C) 2001-2003
// William E. Kempf
-// Copyright (C) 2007 Anthony Williams
+// Copyright (C) 2007-8 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)
@@ -18,7 +18,7 @@
#elif defined(__APPLE__) || defined(__FreeBSD__)
#include <sys/types.h>
#include <sys/sysctl.h>
-#elif defined(__sun)
+#elif defined(__sun) || defined(__CYGWIN__)
#include <unistd.h>
#endif
@@ -28,6 +28,9 @@
{
namespace detail
{
+ thread_data_base::~thread_data_base()
+ {}
+
struct thread_exit_callback_node
{
boost::detail::thread_exit_function_base* func;
@@ -119,7 +122,7 @@
{
void* thread_proxy(void* param)
{
- boost::shared_ptr<boost::detail::thread_data_base> thread_info = static_cast<boost::detail::thread_data_base*>(param)->self;
+ boost::detail::thread_data_ptr thread_info = static_cast<boost::detail::thread_data_base*>(param)->self;
thread_info->self.reset();
detail::set_current_thread_data(thread_info.get());
try
@@ -153,6 +156,10 @@
void run()
{}
+
+ private:
+ externally_launched_thread(externally_launched_thread&);
+ void operator=(externally_launched_thread&);
};
detail::thread_data_base* make_external_thread_data()
@@ -196,47 +203,6 @@
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
- {
- return get_id()==other.get_id();
- }
-
- bool thread::operator!=(const thread& other) const
- {
- return !operator==(other);
- }
-
detail::thread_data_ptr thread::get_thread_info() const
{
lock_guard<mutex> l(thread_info_mutex);
@@ -361,57 +327,61 @@
}
}
- void thread::sleep(const system_time& st)
+ namespace this_thread
{
- detail::thread_data_base* const thread_info=detail::get_current_thread_data();
- if(thread_info)
- {
- unique_lock<mutex> lk(thread_info->sleep_mutex);
- while(thread_info->sleep_condition.timed_wait(lk,st));
- }
- else
+ void sleep(const system_time& st)
{
- xtime const xt=get_xtime(st);
-
- for (int foo=0; foo < 5; ++foo)
+ detail::thread_data_base* const thread_info=detail::get_current_thread_data();
+
+ if(thread_info)
+ {
+ unique_lock<mutex> lk(thread_info->sleep_mutex);
+ while(thread_info->sleep_condition.timed_wait(lk,st));
+ }
+ else
{
+ xtime const xt=get_xtime(st);
+
+ for (int foo=0; foo < 5; ++foo)
+ {
# if defined(BOOST_HAS_PTHREAD_DELAY_NP)
- timespec ts;
- to_timespec_duration(xt, ts);
- BOOST_VERIFY(!pthread_delay_np(&ts));
+ timespec ts;
+ to_timespec_duration(xt, ts);
+ BOOST_VERIFY(!pthread_delay_np(&ts));
# elif defined(BOOST_HAS_NANOSLEEP)
- timespec ts;
- to_timespec_duration(xt, ts);
+ timespec ts;
+ to_timespec_duration(xt, ts);
- // nanosleep takes a timespec that is an offset, not
- // an absolute time.
- nanosleep(&ts, 0);
+ // nanosleep takes a timespec that is an offset, not
+ // an absolute time.
+ nanosleep(&ts, 0);
# else
- mutex mx;
- mutex::scoped_lock lock(mx);
- condition cond;
- cond.timed_wait(lock, xt);
+ mutex mx;
+ mutex::scoped_lock lock(mx);
+ condition cond;
+ cond.timed_wait(lock, xt);
# endif
- xtime cur;
- xtime_get(&cur, TIME_UTC);
- if (xtime_cmp(xt, cur) <= 0)
- return;
+ xtime cur;
+ xtime_get(&cur, TIME_UTC);
+ if (xtime_cmp(xt, cur) <= 0)
+ return;
+ }
}
}
- }
- void thread::yield()
- {
+ void yield()
+ {
# if defined(BOOST_HAS_SCHED_YIELD)
- BOOST_VERIFY(!sched_yield());
+ BOOST_VERIFY(!sched_yield());
# elif defined(BOOST_HAS_PTHREAD_YIELD)
- BOOST_VERIFY(!pthread_yield());
+ BOOST_VERIFY(!pthread_yield());
# else
- xtime xt;
- xtime_get(&xt, TIME_UTC);
- sleep(xt);
+ xtime xt;
+ xtime_get(&xt, TIME_UTC);
+ sleep(xt);
# endif
+ }
}
unsigned thread::hardware_concurrency()
@@ -424,7 +394,7 @@
int count;
size_t size=sizeof(count);
return sysctlbyname("hw.ncpu",&count,&size,NULL,0)?0:count;
-#elif defined(__sun)
+#elif defined(__sun) || defined(__CYGWIN__)
int const count=sysconf(_SC_NPROCESSORS_ONLN);
return (count>0)?count:0;
#else
@@ -472,6 +442,21 @@
return false;
}
}
+
+ thread::native_handle_type thread::native_handle()
+ {
+ detail::thread_data_ptr const local_thread_info=get_thread_info();
+ if(local_thread_info)
+ {
+ lock_guard<mutex> lk(local_thread_info->data_mutex);
+ return local_thread_info->thread_handle;
+ }
+ else
+ {
+ return pthread_t();
+ }
+ }
+
namespace this_thread
@@ -607,85 +592,85 @@
}
}
- thread_group::thread_group()
- {
- }
-
- thread_group::~thread_group()
- {
- // We shouldn't have to scoped_lock here, since referencing this object
- // from another thread while we're deleting it in the current thread is
- // going to lead to undefined behavior any way.
- for (std::list<thread*>::iterator it = m_threads.begin();
- it != m_threads.end(); ++it)
- {
- delete (*it);
- }
- }
-
- thread* thread_group::create_thread(const function0<void>& threadfunc)
- {
- // No scoped_lock required here since the only "shared data" that's
- // modified here occurs inside add_thread which does scoped_lock.
- std::auto_ptr<thread> thrd(new thread(threadfunc));
- add_thread(thrd.get());
- return thrd.release();
- }
-
- void thread_group::add_thread(thread* thrd)
- {
- mutex::scoped_lock scoped_lock(m_mutex);
-
- // For now we'll simply ignore requests to add a thread object multiple
- // times. Should we consider this an error and either throw or return an
- // error value?
- std::list<thread*>::iterator it = std::find(m_threads.begin(),
- m_threads.end(), thrd);
- BOOST_ASSERT(it == m_threads.end());
- if (it == m_threads.end())
- m_threads.push_back(thrd);
- }
-
- void thread_group::remove_thread(thread* thrd)
- {
- mutex::scoped_lock scoped_lock(m_mutex);
-
- // For now we'll simply ignore requests to remove a thread object that's
- // not in the group. Should we consider this an error and either throw or
- // return an error value?
- std::list<thread*>::iterator it = std::find(m_threads.begin(),
- m_threads.end(), thrd);
- BOOST_ASSERT(it != m_threads.end());
- if (it != m_threads.end())
- m_threads.erase(it);
- }
-
- void thread_group::join_all()
- {
- mutex::scoped_lock scoped_lock(m_mutex);
- for (std::list<thread*>::iterator it = m_threads.begin();
- it != m_threads.end(); ++it)
- {
- (*it)->join();
- }
- }
-
- void thread_group::interrupt_all()
- {
- boost::lock_guard<mutex> guard(m_mutex);
+// thread_group::thread_group()
+// {
+// }
+
+// thread_group::~thread_group()
+// {
+// // We shouldn't have to scoped_lock here, since referencing this object
+// // from another thread while we're deleting it in the current thread is
+// // going to lead to undefined behavior any way.
+// for (std::list<thread*>::iterator it = m_threads.begin();
+// it != m_threads.end(); ++it)
+// {
+// delete (*it);
+// }
+// }
+
+// thread* thread_group::create_thread(const function0<void>& threadfunc)
+// {
+// // No scoped_lock required here since the only "shared data" that's
+// // modified here occurs inside add_thread which does scoped_lock.
+// std::auto_ptr<thread> thrd(new thread(threadfunc));
+// add_thread(thrd.get());
+// return thrd.release();
+// }
+
+// void thread_group::add_thread(thread* thrd)
+// {
+// mutex::scoped_lock scoped_lock(m_mutex);
+
+// // For now we'll simply ignore requests to add a thread object multiple
+// // times. Should we consider this an error and either throw or return an
+// // error value?
+// std::list<thread*>::iterator it = std::find(m_threads.begin(),
+// m_threads.end(), thrd);
+// BOOST_ASSERT(it == m_threads.end());
+// if (it == m_threads.end())
+// m_threads.push_back(thrd);
+// }
+
+// void thread_group::remove_thread(thread* thrd)
+// {
+// mutex::scoped_lock scoped_lock(m_mutex);
+
+// // For now we'll simply ignore requests to remove a thread object that's
+// // not in the group. Should we consider this an error and either throw or
+// // return an error value?
+// std::list<thread*>::iterator it = std::find(m_threads.begin(),
+// m_threads.end(), thrd);
+// BOOST_ASSERT(it != m_threads.end());
+// if (it != m_threads.end())
+// m_threads.erase(it);
+// }
+
+// void thread_group::join_all()
+// {
+// mutex::scoped_lock scoped_lock(m_mutex);
+// for (std::list<thread*>::iterator it = m_threads.begin();
+// it != m_threads.end(); ++it)
+// {
+// (*it)->join();
+// }
+// }
+
+// void thread_group::interrupt_all()
+// {
+// boost::lock_guard<mutex> guard(m_mutex);
- for(std::list<thread*>::iterator it=m_threads.begin(),end=m_threads.end();
- it!=end;
- ++it)
- {
- (*it)->interrupt();
- }
- }
+// for(std::list<thread*>::iterator it=m_threads.begin(),end=m_threads.end();
+// it!=end;
+// ++it)
+// {
+// (*it)->interrupt();
+// }
+// }
- size_t thread_group::size() const
- {
- return m_threads.size();
- }
+// size_t thread_group::size() const
+// {
+// return m_threads.size();
+// }
}
Modified: branches/release/libs/thread/src/tss_null.cpp
==============================================================================
--- branches/release/libs/thread/src/tss_null.cpp (original)
+++ branches/release/libs/thread/src/tss_null.cpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -6,7 +6,7 @@
#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
Modified: branches/release/libs/thread/src/win32/thread.cpp
==============================================================================
--- branches/release/libs/thread/src/win32/thread.cpp (original)
+++ branches/release/libs/thread/src/win32/thread.cpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -81,25 +81,6 @@
}
- void thread::yield()
- {
- this_thread::yield();
- }
-
- void thread::sleep(const system_time& target)
- {
- system_time const now(get_system_time());
-
- if(target<=now)
- {
- this_thread::yield();
- }
- else
- {
- this_thread::sleep(target-now);
- }
- }
-
namespace detail
{
struct thread_exit_callback_node
@@ -164,26 +145,24 @@
set_current_thread_data(0);
}
- }
-
-
- unsigned __stdcall thread::thread_start_function(void* param)
- {
- detail::thread_data_base* const thread_info(reinterpret_cast<detail::thread_data_base*>(param));
- set_current_thread_data(thread_info);
- try
+ unsigned __stdcall thread_start_function(void* param)
{
- thread_info->run();
- }
- catch(thread_interrupted const&)
- {
- }
- catch(...)
- {
- std::terminate();
+ detail::thread_data_base* const thread_info(reinterpret_cast<detail::thread_data_base*>(param));
+ set_current_thread_data(thread_info);
+ try
+ {
+ thread_info->run();
+ }
+ catch(thread_interrupted const&)
+ {
+ }
+ catch(...)
+ {
+ std::terminate();
+ }
+ run_thread_exit_callbacks();
+ return 0;
}
- run_thread_exit_callbacks();
- return 0;
}
thread::thread()
@@ -218,6 +197,9 @@
void run()
{}
+ private:
+ externally_launched_thread(externally_launched_thread&);
+ void operator=(externally_launched_thread&);
};
void make_external_thread_data()
@@ -244,36 +226,6 @@
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=0;
- }
-
- 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);
- }
-
thread::id thread::get_id() const
{
return thread::id(get_thread_info());
Modified: branches/release/libs/thread/test/Jamfile.v2
==============================================================================
--- branches/release/libs/thread/test/Jamfile.v2 (original)
+++ branches/release/libs/thread/test/Jamfile.v2 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -22,22 +22,24 @@
: requirements <library>/boost/test//boost_unit_test_framework/<link>static
<threading>multi
;
-
+
rule thread-run ( sources )
{
return
- [ run $(sources) ../build//boost_thread ]
- [ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static
- : : : : $(sources[1]:B)_lib ]
- ;
+ [ run $(sources) ../build//boost_thread ]
+ [ run $(sources) ../src/tss_null.cpp ../build//boost_thread/<link>static
+ : : : : $(sources[1]:B)_lib ]
+ ;
}
-
+
{
test-suite "threads"
: [ 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_thread_launching.cpp ]
+ [ thread-run test_thread_mf.cpp ]
[ thread-run test_move_function.cpp ]
[ thread-run test_mutex.cpp ]
[ thread-run test_condition_notify_one.cpp ]
@@ -47,9 +49,13 @@
[ thread-run test_tss.cpp ]
[ thread-run test_once.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_part_2.cpp ]
+ [ thread-run test_shared_mutex_timed_locks.cpp ]
[ thread-run test_lock_concept.cpp ]
+ [ thread-run test_generic_locks.cpp ]
+ [ compile-fail no_implicit_move_from_lvalue_thread.cpp ]
+ [ compile-fail no_implicit_assign_from_lvalue_thread.cpp ]
;
}
Modified: branches/release/libs/thread/test/shared_mutex_locking_thread.hpp
==============================================================================
--- branches/release/libs/thread/test/shared_mutex_locking_thread.hpp (original)
+++ branches/release/libs/thread/test/shared_mutex_locking_thread.hpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -66,5 +66,67 @@
void operator=(locking_thread&);
};
+class simple_writing_thread
+{
+ boost::shared_mutex& rwm;
+ boost::mutex& finish_mutex;
+ boost::mutex& unblocked_mutex;
+ unsigned& unblocked_count;
+
+ void operator=(simple_writing_thread&);
+
+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);
+ }
+};
+
+class simple_reading_thread
+{
+ boost::shared_mutex& rwm;
+ boost::mutex& finish_mutex;
+ boost::mutex& unblocked_mutex;
+ unsigned& unblocked_count;
+
+ void operator=(simple_reading_thread&);
+
+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);
+ }
+};
+
#endif
Modified: branches/release/libs/thread/test/test_condition_notify_all.cpp
==============================================================================
--- branches/release/libs/thread/test/test_condition_notify_all.cpp (original)
+++ branches/release/libs/thread/test/test_condition_notify_all.cpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -159,6 +159,47 @@
}
}
+namespace
+{
+ boost::mutex multiple_wake_mutex;
+ boost::condition_variable multiple_wake_cond;
+ unsigned multiple_wake_count=0;
+
+ void wait_for_condvar_and_increase_count()
+ {
+ boost::mutex::scoped_lock lk(multiple_wake_mutex);
+ multiple_wake_cond.wait(lk);
+ ++multiple_wake_count;
+ }
+
+}
+
+
+void do_test_notify_all_following_notify_one_wakes_all_threads()
+{
+ boost::thread thread1(wait_for_condvar_and_increase_count);
+ boost::thread thread2(wait_for_condvar_and_increase_count);
+
+ boost::this_thread::sleep(boost::posix_time::milliseconds(200));
+ multiple_wake_cond.notify_one();
+
+ boost::thread thread3(wait_for_condvar_and_increase_count);
+
+ boost::this_thread::sleep(boost::posix_time::milliseconds(200));
+ multiple_wake_cond.notify_one();
+ multiple_wake_cond.notify_all();
+ boost::this_thread::sleep(boost::posix_time::milliseconds(200));
+
+ {
+ boost::mutex::scoped_lock lk(multiple_wake_mutex);
+ BOOST_CHECK(multiple_wake_count==3);
+ }
+
+ thread1.join();
+ thread2.join();
+ thread3.join();
+}
+
void test_condition_notify_all()
{
timed_test(&do_test_condition_notify_all_wakes_from_wait, timeout_seconds);
@@ -166,6 +207,7 @@
timed_test(&do_test_condition_notify_all_wakes_from_timed_wait, timeout_seconds);
timed_test(&do_test_condition_notify_all_wakes_from_timed_wait_with_predicate, timeout_seconds);
timed_test(&do_test_condition_notify_all_wakes_from_relative_timed_wait_with_predicate, timeout_seconds);
+ timed_test(&do_test_notify_all_following_notify_one_wakes_all_threads, timeout_seconds);
}
Modified: branches/release/libs/thread/test/test_condition_notify_one.cpp
==============================================================================
--- branches/release/libs/thread/test/test_condition_notify_one.cpp (original)
+++ branches/release/libs/thread/test/test_condition_notify_one.cpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -92,6 +92,47 @@
BOOST_CHECK(data.woken);
}
+namespace
+{
+ boost::mutex multiple_wake_mutex;
+ boost::condition_variable multiple_wake_cond;
+ unsigned multiple_wake_count=0;
+
+ void wait_for_condvar_and_increase_count()
+ {
+ boost::mutex::scoped_lock lk(multiple_wake_mutex);
+ multiple_wake_cond.wait(lk);
+ ++multiple_wake_count;
+ }
+
+}
+
+
+void do_test_multiple_notify_one_calls_wakes_multiple_threads()
+{
+ boost::thread thread1(wait_for_condvar_and_increase_count);
+ boost::thread thread2(wait_for_condvar_and_increase_count);
+
+ boost::this_thread::sleep(boost::posix_time::milliseconds(200));
+ multiple_wake_cond.notify_one();
+
+ boost::thread thread3(wait_for_condvar_and_increase_count);
+
+ boost::this_thread::sleep(boost::posix_time::milliseconds(200));
+ multiple_wake_cond.notify_one();
+ multiple_wake_cond.notify_one();
+ boost::this_thread::sleep(boost::posix_time::milliseconds(200));
+
+ {
+ boost::mutex::scoped_lock lk(multiple_wake_mutex);
+ BOOST_CHECK(multiple_wake_count==3);
+ }
+
+ thread1.join();
+ thread2.join();
+ thread3.join();
+}
+
void test_condition_notify_one()
{
timed_test(&do_test_condition_notify_one_wakes_from_wait, timeout_seconds, execution_monitor::use_mutex);
@@ -99,6 +140,7 @@
timed_test(&do_test_condition_notify_one_wakes_from_timed_wait, timeout_seconds, execution_monitor::use_mutex);
timed_test(&do_test_condition_notify_one_wakes_from_timed_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex);
timed_test(&do_test_condition_notify_one_wakes_from_relative_timed_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex);
+ timed_test(&do_test_multiple_notify_one_calls_wakes_multiple_threads, timeout_seconds, execution_monitor::use_mutex);
}
Modified: branches/release/libs/thread/test/test_lock_concept.cpp
==============================================================================
--- branches/release/libs/thread/test/test_lock_concept.cpp (original)
+++ branches/release/libs/thread/test/test_lock_concept.cpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -1,4 +1,4 @@
-// (C) Copyright 2006-7 Anthony Williams
+// (C) Copyright 2006-8 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)
@@ -7,7 +7,9 @@
#include <boost/test/test_case_template.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/thread/mutex.hpp>
+#include <boost/thread/thread.hpp>
#include <boost/thread/recursive_mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
template<typename Mutex,typename Lock>
struct test_initially_locked
@@ -23,6 +25,64 @@
};
template<typename Mutex,typename Lock>
+struct test_initially_unlocked_if_other_thread_has_lock
+{
+ Mutex m;
+ boost::mutex done_mutex;
+ bool done;
+ bool locked;
+ boost::condition_variable done_cond;
+
+ test_initially_unlocked_if_other_thread_has_lock():
+ done(false),locked(false)
+ {}
+
+ void locking_thread()
+ {
+ Lock lock(m);
+
+ boost::lock_guard<boost::mutex> lk(done_mutex);
+ locked=lock.owns_lock();
+ done=true;
+ done_cond.notify_one();
+ }
+
+ bool is_done() const
+ {
+ return done;
+ }
+
+
+ void operator()()
+ {
+ Lock lock(m);
+
+ typedef test_initially_unlocked_if_other_thread_has_lock<Mutex,Lock> this_type;
+
+ boost::thread t(&this_type::locking_thread,this);
+
+ try
+ {
+ {
+ boost::mutex::scoped_lock lk(done_mutex);
+ BOOST_CHECK(done_cond.timed_wait(lk,boost::posix_time::seconds(2),
+ boost::bind(&this_type::is_done,this)));
+ BOOST_CHECK(!locked);
+ }
+
+ lock.unlock();
+ t.join();
+ }
+ catch(...)
+ {
+ lock.unlock();
+ t.join();
+ throw;
+ }
+ }
+};
+
+template<typename Mutex,typename Lock>
struct test_initially_unlocked_with_defer_lock_parameter
{
void operator()() const
@@ -125,11 +185,51 @@
BOOST_CHECK_THROW( lock.unlock(), boost::lock_error );
}
};
+template<typename Lock>
+struct test_default_constructed_has_no_mutex_and_unlocked
+{
+ void operator()() const
+ {
+ Lock l;
+ BOOST_CHECK(!l.mutex());
+ BOOST_CHECK(!l.owns_lock());
+ };
+};
+
+
+template<typename Mutex,typename Lock>
+struct test_locks_can_be_swapped
+{
+ void operator()() const
+ {
+ Mutex m1;
+ Mutex m2;
+ Lock l1(m1);
+ Lock l2(m2);
+
+ BOOST_CHECK_EQUAL(l1.mutex(),&m1);
+ BOOST_CHECK_EQUAL(l2.mutex(),&m2);
+
+ l1.swap(l2);
+
+ BOOST_CHECK_EQUAL(l1.mutex(),&m2);
+ BOOST_CHECK_EQUAL(l2.mutex(),&m1);
+
+ swap(l1,l2);
+
+ BOOST_CHECK_EQUAL(l1.mutex(),&m1);
+ BOOST_CHECK_EQUAL(l2.mutex(),&m2);
+
+ }
+};
+
+
BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_scoped_lock_concept,Mutex)
{
typedef typename Mutex::scoped_lock Lock;
+ test_default_constructed_has_no_mutex_and_unlocked<Lock>()();
test_initially_locked<Mutex,Lock>()();
test_initially_unlocked_with_defer_lock_parameter<Mutex,Lock>()();
test_initially_locked_with_adopt_lock_parameter<Mutex,Lock>()();
@@ -137,13 +237,16 @@
test_locked_after_lock_called<Mutex,Lock>()();
test_throws_if_lock_called_when_already_locked<Mutex,Lock>()();
test_throws_if_unlock_called_when_already_unlocked<Mutex,Lock>()();
+ test_locks_can_be_swapped<Mutex,Lock>()();
}
BOOST_TEST_CASE_TEMPLATE_FUNCTION(test_scoped_try_lock_concept,Mutex)
{
typedef typename Mutex::scoped_try_lock Lock;
+ test_default_constructed_has_no_mutex_and_unlocked<Lock>()();
test_initially_locked<Mutex,Lock>()();
+ test_initially_unlocked_if_other_thread_has_lock<Mutex,Lock>()();
test_initially_unlocked_with_defer_lock_parameter<Mutex,Lock>()();
test_initially_locked_with_adopt_lock_parameter<Mutex,Lock>()();
test_unlocked_after_unlock_called<Mutex,Lock>()();
@@ -152,6 +255,7 @@
test_throws_if_lock_called_when_already_locked<Mutex,Lock>()();
test_throws_if_try_lock_called_when_already_locked<Mutex,Lock>()();
test_throws_if_unlock_called_when_already_unlocked<Mutex,Lock>()();
+ test_locks_can_be_swapped<Mutex,Lock>()();
}
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
Modified: branches/release/libs/thread/test/test_move_function.cpp
==============================================================================
--- branches/release/libs/thread/test/test_move_function.cpp (original)
+++ branches/release/libs/thread/test/test_move_function.cpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -1,10 +1,11 @@
-// Copyright (C) 2007 Anthony Williams
+// Copyright (C) 2007-8 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>
+#include <boost/shared_ptr.hpp>
void do_nothing()
{}
@@ -20,13 +21,36 @@
dest.join();
}
+void test_thread_move_from_lvalue_on_assignment()
+{
+ boost::thread src(do_nothing);
+ boost::thread::id src_id=src.get_id();
+ boost::thread dest;
+ 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();
+}
+
+boost::thread start_thread()
+{
+ return boost::thread(do_nothing);
+}
+
void test_thread_move_from_rvalue_on_construction()
{
- boost::thread x(boost::move(boost::thread(do_nothing)));
+ boost::thread x(start_thread());
BOOST_CHECK(x.get_id()!=boost::thread::id());
x.join();
}
+void test_thread_move_from_rvalue_using_explicit_move()
+{
+ boost::thread x(boost::move(start_thread()));
+ BOOST_CHECK(x.get_id()!=boost::thread::id());
+ x.join();
+}
void test_unique_lock_move_from_lvalue_on_construction()
{
@@ -42,6 +66,48 @@
BOOST_CHECK(l2.mutex()==&m);
}
+boost::unique_lock<boost::mutex> get_lock(boost::mutex& m)
+{
+ return boost::unique_lock<boost::mutex>(m);
+}
+
+
+void test_unique_lock_move_from_rvalue_on_construction()
+{
+ boost::mutex m;
+ boost::unique_lock<boost::mutex> l(get_lock(m));
+ BOOST_CHECK(l.owns_lock());
+ BOOST_CHECK(l.mutex()==&m);
+}
+
+namespace user_test_ns
+{
+ template<typename T>
+ T move(T& t)
+ {
+ return t.move();
+ }
+
+ bool move_called=false;
+
+ struct nc:
+ public boost::shared_ptr<int>
+ {
+ nc move()
+ {
+ move_called=true;
+ return nc();
+ }
+ };
+}
+
+void test_move_for_user_defined_type_unaffected()
+{
+ user_test_ns::nc src;
+ user_test_ns::nc dest=move(src);
+ BOOST_CHECK(user_test_ns::move_called);
+}
+
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test_framework::test_suite* test =
@@ -49,6 +115,10 @@
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_thread_move_from_rvalue_using_explicit_move));
+ test->add(BOOST_TEST_CASE(test_thread_move_from_lvalue_on_assignment));
test->add(BOOST_TEST_CASE(test_unique_lock_move_from_lvalue_on_construction));
+ test->add(BOOST_TEST_CASE(test_unique_lock_move_from_rvalue_on_construction));
+ test->add(BOOST_TEST_CASE(test_move_for_user_defined_type_unaffected));
return test;
}
Modified: branches/release/libs/thread/test/test_shared_mutex_part_2.cpp
==============================================================================
--- branches/release/libs/thread/test/test_shared_mutex_part_2.cpp (original)
+++ branches/release/libs/thread/test/test_shared_mutex_part_2.cpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -107,40 +107,6 @@
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;
-
- void operator=(simple_writing_thread&);
-
- 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()
{
@@ -175,40 +141,6 @@
}
}
-namespace
-{
- class simple_reading_thread
- {
- boost::shared_mutex& rwm;
- boost::mutex& finish_mutex;
- boost::mutex& unblocked_mutex;
- unsigned& unblocked_count;
-
- void operator=(simple_reading_thread&);
-
- 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()
{
@@ -232,33 +164,6 @@
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 =
@@ -269,7 +174,6 @@
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;
}
Modified: branches/release/libs/thread/test/test_thread.cpp
==============================================================================
--- branches/release/libs/thread/test/test_thread.cpp (original)
+++ branches/release/libs/thread/test/test_thread.cpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -1,5 +1,6 @@
// Copyright (C) 2001-2003
// William E. Kempf
+// Copyright (C) 2008 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)
@@ -198,6 +199,22 @@
timed_test(&do_test_timed_join, 10);
}
+void test_swap()
+{
+ boost::thread t(simple_thread);
+ boost::thread t2(simple_thread);
+ boost::thread::id id1=t.get_id();
+ boost::thread::id id2=t2.get_id();
+
+ t.swap(t2);
+ BOOST_CHECK(t.get_id()==id2);
+ BOOST_CHECK(t2.get_id()==id1);
+
+ swap(t,t2);
+ BOOST_CHECK(t.get_id()==id1);
+ BOOST_CHECK(t2.get_id()==id2);
+}
+
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
@@ -211,6 +228,7 @@
test->add(BOOST_TEST_CASE(test_thread_no_interrupt_if_interrupts_disabled_at_interruption_point));
test->add(BOOST_TEST_CASE(test_creation_through_reference_wrapper));
test->add(BOOST_TEST_CASE(test_timed_join));
+ test->add(BOOST_TEST_CASE(test_swap));
return test;
}
Modified: branches/release/libs/thread/test/test_tss.cpp
==============================================================================
--- branches/release/libs/thread/test/test_tss.cpp (original)
+++ branches/release/libs/thread/test/test_tss.cpp 2008-06-18 09:01:08 EDT (Wed, 18 Jun 2008)
@@ -258,11 +258,58 @@
}
}
+struct dummy_class_tracks_deletions
+{
+ static unsigned deletions;
+
+ ~dummy_class_tracks_deletions()
+ {
+ ++deletions;
+ }
+
+};
+
+unsigned dummy_class_tracks_deletions::deletions=0;
+
+boost::thread_specific_ptr<dummy_class_tracks_deletions> tss_with_null_cleanup(NULL);
+
+void tss_thread_with_null_cleanup(dummy_class_tracks_deletions* delete_tracker)
+{
+ tss_with_null_cleanup.reset(delete_tracker);
+}
+
+void do_test_tss_does_no_cleanup_with_null_cleanup_function()
+{
+ dummy_class_tracks_deletions* delete_tracker=new dummy_class_tracks_deletions;
+ boost::thread t(tss_thread_with_null_cleanup,delete_tracker);
+ try
+ {
+ t.join();
+ }
+ catch(...)
+ {
+ t.interrupt();
+ t.join();
+ throw;
+ }
+
+ BOOST_CHECK(!dummy_class_tracks_deletions::deletions);
+ if(!dummy_class_tracks_deletions::deletions)
+ {
+ delete delete_tracker;
+ }
+}
+
void test_tss_does_no_cleanup_after_release()
{
timed_test(&do_test_tss_does_no_cleanup_after_release, 2);
}
+void test_tss_does_no_cleanup_with_null_cleanup_function()
+{
+ timed_test(&do_test_tss_does_no_cleanup_with_null_cleanup_function, 2);
+}
+
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
{
boost::unit_test_framework::test_suite* test =
@@ -271,6 +318,7 @@
test->add(BOOST_TEST_CASE(test_tss));
test->add(BOOST_TEST_CASE(test_tss_with_custom_cleanup));
test->add(BOOST_TEST_CASE(test_tss_does_no_cleanup_after_release));
+ test->add(BOOST_TEST_CASE(test_tss_does_no_cleanup_with_null_cleanup_function));
return test;
}
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk