Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r86428 - in trunk: boost/sync boost/sync/condition_variables boost/sync/detail/condition_variables boost/sync/detail/events boost/sync/detail/mutexes libs/sync/doc libs/sync/src libs/sync/test/run
From: andrey.semashev_at_[hidden]
Date: 2013-10-25 12:35:13


Author: andysem
Date: 2013-10-25 12:35:13 EDT (Fri, 25 Oct 2013)
New Revision: 86428
URL: http://svn.boost.org/trac/boost/changeset/86428

Log:
Implemented notify_all_at_thread_exit, condition_variable_any and manual_reset_event (emulation). Timed mutex tests re-enabled. Added support for compiler-based TLS on non-Windows targets.

Added:
   trunk/boost/sync/condition_variables/condition_variable_any.hpp (contents, props changed)
   trunk/boost/sync/condition_variables/notify_all_at_thread_exit.hpp (contents, props changed)
   trunk/boost/sync/detail/condition_variables/condition_variable_any_generic.hpp (contents, props changed)
   trunk/boost/sync/detail/condition_variables/condition_variable_any_windows.hpp (contents, props changed)
Text files modified:
   trunk/boost/sync/condition_variables.hpp | 2
   trunk/boost/sync/condition_variables/condition_variable_any.hpp | 240 ++++++++++++++++++++++++++++++++++++++++
   trunk/boost/sync/condition_variables/notify_all_at_thread_exit.hpp | 66 +++++++++++
   trunk/boost/sync/detail/condition_variables/condition_variable_any_generic.hpp | 184 ++++++++++++++++++++++++++++++
   trunk/boost/sync/detail/condition_variables/condition_variable_any_windows.hpp | 162 +++++++++++++++++++++++++++
   trunk/boost/sync/detail/condition_variables/condition_variable_windows.hpp | 2
   trunk/boost/sync/detail/events/auto_reset_event_emulation.hpp | 14 +-
   trunk/boost/sync/detail/events/manual_reset_event_emulation.hpp | 204 +++++++++------------------------
   trunk/boost/sync/detail/mutexes/timed_mutex_posix.hpp | 7 +
   trunk/libs/sync/doc/Jamfile.v2 | 1
   trunk/libs/sync/src/tss_manager.hpp | 23 +++
   trunk/libs/sync/src/tss_pthread.cpp | 55 ++++++++
   trunk/libs/sync/src/tss_windows.cpp | 15 ++
   trunk/libs/sync/test/run/mutex_test.cpp | 27 +++
   14 files changed, 838 insertions(+), 164 deletions(-)

Modified: trunk/boost/sync/condition_variables.hpp
==============================================================================
--- trunk/boost/sync/condition_variables.hpp Fri Oct 25 12:35:09 2013 (r86427)
+++ trunk/boost/sync/condition_variables.hpp 2013-10-25 12:35:13 EDT (Fri, 25 Oct 2013) (r86428)
@@ -21,5 +21,7 @@
 #endif
 
 #include <boost/sync/condition_variables/condition_variable.hpp>
+#include <boost/sync/condition_variables/condition_variable_any.hpp>
+#include <boost/sync/condition_variables/notify_all_at_thread_exit.hpp>
 
 #endif // BOOST_SYNC_CONDITION_VARIABLES_HPP_INCLUDED_

Added: trunk/boost/sync/condition_variables/condition_variable_any.hpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/boost/sync/condition_variables/condition_variable_any.hpp 2013-10-25 12:35:13 EDT (Fri, 25 Oct 2013) (r86428)
@@ -0,0 +1,240 @@
+/*
+ * 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 2013 Andrey Semashev
+ */
+/*!
+ * \file sync/condition_variables/condition_variable_any.hpp
+ *
+ * \brief This header defines a basic condition variable primitive.
+ */
+
+#ifndef BOOST_SYNC_CONDITION_VARIABLES_CONDITION_VARIABLE_ANY_HPP_INCLUDED_
+#define BOOST_SYNC_CONDITION_VARIABLES_CONDITION_VARIABLE_ANY_HPP_INCLUDED_
+
+#if defined(BOOST_SYNC_DETAIL_DOXYGEN)
+
+namespace boost {
+
+namespace sync {
+
+/*!
+ * \brief The condition variable class
+ */
+class condition_variable_any
+{
+public:
+ /*!
+ * \brief Default constructor
+ *
+ * \b Throws: An exception in case if the operating system is unable to create the primitive (e.g. due to insufficient resources).
+ */
+ condition_variable_any();
+
+ /*!
+ * \brief Destructor
+ *
+ * Destroys the condition variable.
+ *
+ * \pre There are no threads blocked on the object.
+ */
+ ~condition_variable_any();
+
+ condition_variable_any(condition_variable_any const&) = delete;
+ condition_variable_any& operator= (condition_variable_any const&) = delete;
+
+ /*!
+ * \brief Wakes up one thread blocked on the object
+ */
+ void notify_one();
+
+ /*!
+ * \brief Wakes up all threads blocked on the object
+ */
+ void notify_all();
+
+ /*!
+ * \brief Blocks the current thread on the object
+ *
+ * Atomically unlocks the lock and blocks on the object. When unblocked, it locks the lock and returns.
+ * The function can unblock upon another thread calling \c notify_one(), \c notify_all() or spuriously.
+ *
+ * \param lock Lock object. Must be a model of \c BasicLockable.
+ *
+ * \b Throws: An exception in case if the operating system is unable to fulfill the request. The lock is left in the locked state in case of exception.
+ */
+ template< typename Lock >
+ void wait(Lock& lock);
+
+ /*!
+ * \brief Blocks the current thread on the object until the predicate is satisfied
+ *
+ * Works equivalent to:
+ *
+ * <code>
+ * while (!pred())
+ * wait(lock);
+ * </code>
+ *
+ * \param lock Lock object. Must be a model of \c BasicLockable.
+ * \param pred Condition predicate.
+ *
+ * \b Throws: An exception in case if the operating system is unable to fulfill the request. The mutex is left in the locked state in case of exception.
+ */
+ template< typename Lock, typename Predicate >
+ void wait(Lock& lock, Predicate pred);
+
+ /*!
+ * \brief Blocks the current thread on the object until the timeout expires
+ *
+ * Atomically unlocks the lock and blocks on the object. When unblocked, it locks the lock and returns.
+ * The function can unblock after the specified timeout expires, upon another thread calling \c notify_one(), \c notify_all() or spuriously, whichever happens first.
+ * The timeout can be specified as an absolute time point or duration.
+ *
+ * \param lock Lock object. Must be a model of \c BasicLockable.
+ * \param timeout Relative or absolute timeout. If timeout is relative, the time is measured according to the system clock.
+ *
+ * \return \c true if the function returned before the timeout expired, otherwise \c false.
+ *
+ * \b Throws: An exception in case if the operating system is unable to fulfill the request. The lock is left in the locked state in case of exception.
+ *
+ * \note In order to use this method, a supplementary header must be included from boost/sync/support to enable support for particular time units.
+ */
+ template< typename Lock, typename Time >
+ bool timed_wait(Lock& lock, Time const& timeout);
+
+ /*!
+ * \brief Blocks the current thread on the object until the predicate is satisfied or the timeout expires
+ *
+ * If the timeout is an absolute time point, works equivalent to:
+ *
+ * <code>
+ * while (!pred())
+ * if (!timed_wait(lock, timeout))
+ * return pred();
+ * </code>
+ *
+ * otherwise works as if equivalent to:
+ *
+ * <code>
+ * auto abs_timeout = chrono::system_clock::now() + timeout;
+ * while (!pred())
+ * if (!timed_wait(lock, abs_timeout))
+ * return pred();
+ * </code>
+ *
+ * \param lock Lock object. Must be a model of \c BasicLockable.
+ * \param timeout Relative or absolute timeout. If timeout is relative, the time is measured according to the system clock.
+ * \param pred Condition predicate.
+ *
+ * \b Throws: An exception in case if the operating system is unable to fulfill the request. The lock is left in the locked state in case of exception.
+ *
+ * \note In order to use this method, a supplementary header must be included from boost/sync/support to enable support for particular time units.
+ */
+ template< typename Lock, typename Time, typename Predicate >
+ bool timed_wait(Lock& lock, Time const& timeout, Predicate pred);
+
+ /*!
+ * \brief Blocks the current thread on the object until the timeout expires
+ *
+ * Atomically unlocks the lock and blocks on the object. When unblocked, it locks the lock and returns.
+ * The function can unblock after the specified timeout expires, upon another thread calling \c notify_one(), \c notify_all() or spuriously, whichever happens first.
+ * The timeout must be specified as a time duration.
+ *
+ * \param lock Lock object. Must be a model of \c BasicLockable.
+ * \param timeout Relative timeout. The time is measured according to the system clock.
+ *
+ * \return \c cv_status::no_timeout if the function returned before the timeout expired, otherwise \c cv_status::timeout.
+ *
+ * \b Throws: An exception in case if the operating system is unable to fulfill the request. The lock is left in the locked state in case of exception.
+ *
+ * \note In order to use this method, a supplementary header must be included from boost/sync/support to enable support for particular time units.
+ */
+ template< typename Lock, typename Duration >
+ cv_status wait_for(Lock& lock, Duration const& rel_timeout);
+
+ /*!
+ * \brief Blocks the current thread on the object until the timeout expires
+ *
+ * Works equivalent to:
+ *
+ * <code>
+ * return wait_until(lock, chrono::system_clock::now() + rel_timeout, pred);
+ * </code>
+ *
+ * \param lock Lock object. Must be a model of \c BasicLockable.
+ * \param timeout Relative timeout. The time is measured according to the system clock.
+ * \param pred Condition predicate.
+ *
+ * \b Throws: An exception in case if the operating system is unable to fulfill the request. The lock is left in the locked state in case of exception.
+ *
+ * \note In order to use this method, a supplementary header must be included from boost/sync/support to enable support for particular time units.
+ */
+ template< typename Lock, typename Duration, typename Predicate >
+ bool wait_for(Lock& lock, Duration const& rel_timeout, Predicate pred);
+
+ /*!
+ * \brief Blocks the current thread on the object until the timeout expires
+ *
+ * Atomically unlocks the lock and blocks on the object. When unblocked, it locks the lock and returns.
+ * The function can unblock after the specified timeout expires, upon another thread calling \c notify_one(), \c notify_all() or spuriously, whichever happens first.
+ * The timeout must be specified as an absolute time point.
+ *
+ * \param lock Lock object. Must be a model of \c BasicLockable.
+ * \param timeout Absolute timeout.
+ *
+ * \return \c cv_status::no_timeout if the function returned before the timeout expired, otherwise \c cv_status::timeout.
+ *
+ * \b Throws: An exception in case if the operating system is unable to fulfill the request. The lock is left in the locked state in case of exception.
+ *
+ * \note In order to use this method, a supplementary header must be included from boost/sync/support to enable support for particular time units.
+ */
+ template< typename Lock, typename TimePoint >
+ cv_status wait_until(Lock& lock, TimePoint const& abs_timeout);
+
+ /*!
+ * \brief Blocks the current thread on the object until the timeout expires
+ *
+ * Works equivalent to:
+ *
+ * <code>
+ * while (!pred())
+ * if (wait_until(lock, timeout) == cv_status::timeout)
+ * return pred();
+ * </code>
+ *
+ * \param lock Lock object. Must be a model of \c BasicLockable.
+ * \param timeout Absolute timeout.
+ * \param pred Condition predicate.
+ *
+ * \b Throws: An exception in case if the operating system is unable to fulfill the request. The lock is left in the locked state in case of exception.
+ *
+ * \note In order to use this method, a supplementary header must be included from boost/sync/support to enable support for particular time units.
+ */
+ template< typename Lock, typename TimePoint, typename Predicate >
+ bool wait_until(Lock& lock, TimePoint const& abs_timeout, Predicate pred);
+};
+
+} // namespace sync
+
+} // namespace boost
+
+#else // defined(BOOST_SYNC_DETAIL_DOXYGEN)
+
+#include <boost/sync/detail/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if defined(BOOST_SYNC_DETAIL_PLATFORM_WINAPI)
+#include <boost/sync/detail/condition_variables/condition_variable_any_windows.hpp>
+#else
+#include <boost/sync/detail/condition_variables/condition_variable_any_generic.hpp>
+#endif
+
+#endif // defined(BOOST_SYNC_DETAIL_DOXYGEN)
+
+#endif // BOOST_SYNC_CONDITION_VARIABLES_CONDITION_VARIABLE_ANY_HPP_INCLUDED_

Added: trunk/boost/sync/condition_variables/notify_all_at_thread_exit.hpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/boost/sync/condition_variables/notify_all_at_thread_exit.hpp 2013-10-25 12:35:13 EDT (Fri, 25 Oct 2013) (r86428)
@@ -0,0 +1,66 @@
+/*
+ * 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 2013 Andrey Semashev
+ */
+/*!
+ * \file sync/condition_variables/notify_all_at_thread_exit.hpp
+ *
+ * \brief This header defines the \c notify_all_at_thread_exit function.
+ */
+
+#ifndef BOOST_SYNC_CONDITION_VARIABLES_NOTIFY_ALL_AT_THREAD_EXIT_HPP_INCLUDED_
+#define BOOST_SYNC_CONDITION_VARIABLES_NOTIFY_ALL_AT_THREAD_EXIT_HPP_INCLUDED_
+
+#include <boost/assert.hpp>
+#include <boost/sync/detail/link_config.hpp>
+#include <boost/sync/locks/unique_lock.hpp>
+#include <boost/sync/mutexes/mutex.hpp>
+#include <boost/sync/condition_variables/condition_variable.hpp>
+#include <boost/sync/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+namespace sync {
+
+namespace detail {
+
+//! Adds a notification entry at thread termination
+BOOST_SYNC_API void add_thread_exit_notify_entry(sync::mutex* mtx, sync::condition_variable* cond);
+
+} // namespace detail
+
+/*!
+ * Schedules a notification of the condition variable at the calling thread termination. The notification
+ * shall be performed with the <tt>cond.notify_all()</tt> method shortly before the thread terminates.
+ *
+ * The provided lock must be locked, its ownership is transferred to an external storage until the notification
+ * is performed. If there are threads blocked on the \a cond object, these threads should have used the same
+ * mutex object as the one referred to by the \a lock.
+ *
+ * \param cond Condition variable to perform notification on.
+ * \param lock The lock that owns the mutex, used to block on the condition variable.
+ *
+ * \pre <tt>lock.owns_lock()</tt>
+ * \post <tt>!lock.owns_lock()</tt>
+ */
+inline void notify_all_at_thread_exit(sync::condition_variable& cond, sync::unique_lock< sync::mutex > lock)
+{
+ BOOST_ASSERT(lock.owns_lock());
+ sync::detail::add_thread_exit_notify_entry(lock.mutex(), &cond);
+ lock.release();
+}
+
+} // namespace sync
+
+} // namespace boost
+
+#include <boost/sync/detail/footer.hpp>
+
+#endif // BOOST_SYNC_CONDITION_VARIABLES_NOTIFY_ALL_AT_THREAD_EXIT_HPP_INCLUDED_

Added: trunk/boost/sync/detail/condition_variables/condition_variable_any_generic.hpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/boost/sync/detail/condition_variables/condition_variable_any_generic.hpp 2013-10-25 12:35:13 EDT (Fri, 25 Oct 2013) (r86428)
@@ -0,0 +1,184 @@
+/*
+ * 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-2008 Anthony Williams
+ * (C) Copyright 2011-2012 Vicente J. Botet Escriba
+ * (C) Copyright 2013 Andrey Semashev
+ */
+/*!
+ * \file detail/condition_variables/condition_variable_any_generic.hpp
+ *
+ * \brief This header is the Boost.Sync library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/sync/doc/html/index.html.
+ */
+
+#ifndef BOOST_SYNC_DETAIL_CONDITION_VARIABLES_CONDITION_VARIABLE_ANY_GENERIC_HPP_INCLUDED_
+#define BOOST_SYNC_DETAIL_CONDITION_VARIABLES_CONDITION_VARIABLE_ANY_GENERIC_HPP_INCLUDED_
+
+#include <cstddef>
+#include <boost/utility/enable_if.hpp>
+#include <boost/sync/detail/config.hpp>
+#include <boost/sync/detail/time_traits.hpp>
+#include <boost/sync/locks/lock_guard.hpp>
+#include <boost/sync/locks/unique_lock.hpp>
+#include <boost/sync/mutexes/mutex.hpp>
+#include <boost/sync/condition_variables/condition_variable.hpp>
+#include <boost/sync/condition_variables/cv_status.hpp>
+#include <boost/sync/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+namespace sync {
+
+BOOST_SYNC_DETAIL_OPEN_ABI_NAMESPACE {
+
+class condition_variable_any
+{
+private:
+ template< typename Lock >
+ class relocker
+ {
+ private:
+ Lock* m_lock;
+
+ public:
+ relocker() : m_lock(NULL) {}
+
+ ~relocker() BOOST_NOEXCEPT_IF(false)
+ {
+ if (m_lock)
+ m_lock->lock();
+ }
+
+ void unlock(Lock& lock)
+ {
+ lock.unlock();
+ m_lock = &lock;
+ }
+ };
+
+private:
+ sync::mutex m_mutex;
+ sync::condition_variable m_cond;
+
+public:
+#if defined(BOOST_SYNC_DEFINES_MUTEX_CONSTEXPR_CONSTRUCTOR) && defined(BOOST_SYNC_DEFINES_CONDITION_VARIABLE_CONSTEXPR_CONSTRUCTOR)
+#define BOOST_SYNC_DEFINES_CONDITION_VARIABLE_ANY_CONSTEXPR_CONSTRUCTOR
+ BOOST_DEFAULTED_FUNCTION(BOOST_CONSTEXPR condition_variable_any() BOOST_NOEXCEPT, {})
+#else
+ BOOST_DEFAULTED_FUNCTION(condition_variable_any(), {})
+#endif
+
+ void notify_one()
+ {
+ sync::lock_guard< sync::mutex > internal_lock(m_mutex);
+ m_cond.notify_one();
+ }
+
+ void notify_all()
+ {
+ sync::lock_guard< sync::mutex > internal_lock(m_mutex);
+ m_cond.notify_all();
+ }
+
+ template< typename Lock >
+ void wait(Lock& lock)
+ {
+ relocker< Lock > relock_guard;
+ sync::unique_lock< sync::mutex > internal_lock(m_mutex);
+ relock_guard.unlock(lock);
+ m_cond.wait(internal_lock);
+ }
+
+ template< typename Lock, typename Predicate >
+ void wait(Lock& lock, Predicate pred)
+ {
+ while (!pred())
+ this->wait(lock);
+ }
+
+ template< typename Lock, typename Time >
+ typename enable_if_c< sync::detail::time_traits< Time >::is_specialized, bool >::type
+ timed_wait(Lock& lock, Time const& t)
+ {
+ relocker< Lock > relock_guard;
+ sync::unique_lock< sync::mutex > internal_lock(m_mutex);
+ relock_guard.unlock(lock);
+ return m_cond.timed_wait(internal_lock, t);
+ }
+
+ template< typename Lock, typename Time, typename Predicate >
+ typename enable_if_c< sync::detail::time_traits< Time >::is_specialized, bool >::type
+ timed_wait(Lock& lock, Time const& t, Predicate pred)
+ {
+ while (!pred())
+ {
+ if (!this->timed_wait(lock, t))
+ return pred();
+ }
+ return true;
+ }
+
+ template< typename Lock, typename TimePoint >
+ typename detail::enable_if_tag< TimePoint, detail::time_point_tag, sync::cv_status >::type
+ wait_until(Lock& lock, TimePoint const& abs_time)
+ {
+ relocker< Lock > relock_guard;
+ sync::unique_lock< sync::mutex > internal_lock(m_mutex);
+ relock_guard.unlock(lock);
+ return m_cond.wait_until(internal_lock, abs_time);
+ }
+
+ template< typename Lock, typename TimePoint, typename Predicate >
+ typename detail::enable_if_tag< TimePoint, detail::time_point_tag, bool >::type
+ wait_until(Lock& lock, TimePoint const& abs_time, Predicate pred)
+ {
+ while (!pred())
+ {
+ if (this->wait_until(lock, abs_time) != sync::cv_status::no_timeout)
+ return pred();
+ }
+ return true;
+ }
+
+ template< typename Lock, typename Duration >
+ typename detail::enable_if_tag< Duration, detail::time_duration_tag, sync::cv_status >::type
+ wait_for(Lock& lock, Duration const& rel_time)
+ {
+ relocker< Lock > relock_guard;
+ sync::unique_lock< sync::mutex > internal_lock(m_mutex);
+ relock_guard.unlock(lock);
+ return m_cond.wait_for(internal_lock, rel_time);
+ }
+
+ template< typename Lock, typename Duration, typename Predicate >
+ typename detail::enable_if_tag< Duration, detail::time_duration_tag, bool >::type
+ wait_for(Lock& lock, Duration const& rel_time, Predicate pred)
+ {
+ while (!pred())
+ {
+ if (this->wait_for(lock, rel_time) != sync::cv_status::no_timeout)
+ return pred();
+ }
+ return true;
+ }
+
+ BOOST_DELETED_FUNCTION(condition_variable_any(condition_variable_any const&))
+ BOOST_DELETED_FUNCTION(condition_variable_any& operator= (condition_variable_any const&))
+};
+
+} // namespace abi
+
+} // namespace sync
+
+} // namespace boost
+
+#include <boost/sync/detail/footer.hpp>
+
+#endif // BOOST_SYNC_DETAIL_CONDITION_VARIABLES_CONDITION_VARIABLE_ANY_GENERIC_HPP_INCLUDED_

Added: trunk/boost/sync/detail/condition_variables/condition_variable_any_windows.hpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/boost/sync/detail/condition_variables/condition_variable_any_windows.hpp 2013-10-25 12:35:13 EDT (Fri, 25 Oct 2013) (r86428)
@@ -0,0 +1,162 @@
+/*
+ * 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-2008 Anthony Williams
+ * (C) Copyright 2011-2012 Vicente J. Botet Escriba
+ * (C) Copyright 2013 Andrey Semashev
+ */
+/*!
+ * \file detail/condition_variables/condition_variable_any_windows.hpp
+ *
+ * \brief This header is the Boost.Sync library implementation, see the library documentation
+ * at http://www.boost.org/doc/libs/release/libs/sync/doc/html/index.html.
+ */
+
+#ifndef BOOST_SYNC_DETAIL_CONDITION_VARIABLES_CONDITION_VARIABLE_ANY_WINDOWS_HPP_INCLUDED_
+#define BOOST_SYNC_DETAIL_CONDITION_VARIABLES_CONDITION_VARIABLE_ANY_WINDOWS_HPP_INCLUDED_
+
+#include <boost/utility/enable_if.hpp>
+#include <boost/sync/detail/config.hpp>
+#include <boost/sync/detail/time_traits.hpp>
+#include <boost/sync/detail/time_units.hpp>
+#include <boost/sync/detail/condition_variables/basic_condition_variable_windows.hpp>
+#include <boost/sync/condition_variables/cv_status.hpp>
+#include <boost/sync/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+namespace sync {
+
+BOOST_SYNC_DETAIL_OPEN_ABI_NAMESPACE {
+
+class condition_variable_any
+{
+private:
+ sync::detail::windows::basic_condition_variable m_cond;
+
+public:
+#if !defined(BOOST_NO_CXX11_CONSTEXPR)
+#define BOOST_SYNC_DEFINES_CONDITION_VARIABLE_ANY_CONSTEXPR_CONSTRUCTOR
+#endif
+
+ BOOST_CONSTEXPR condition_variable_any() BOOST_NOEXCEPT : m_cond()
+ {
+ }
+
+ void notify_one() BOOST_NOEXCEPT
+ {
+ m_cond.notify_one();
+ }
+
+ void notify_all() BOOST_NOEXCEPT
+ {
+ m_cond.notify_all();
+ }
+
+ template< typename Lock >
+ void wait(Lock& lock)
+ {
+ m_cond.wait(lock);
+ }
+
+ template< typename Lock, typename Predicate >
+ void wait(Lock& lock, Predicate pred)
+ {
+ while (!pred())
+ m_cond.wait(lock);
+ }
+
+ template< typename Lock, typename Time >
+ typename enable_if_c< sync::detail::time_traits< Time >::is_specialized, bool >::type
+ timed_wait(Lock& lock, Time const& t)
+ {
+ return m_cond.timed_wait(lock, sync::detail::time_traits< Time >::to_sync_unit(t)) == sync::cv_status::no_timeout;
+ }
+
+ template< typename Lock, typename TimePoint, typename Predicate >
+ typename detail::enable_if_tag< TimePoint, detail::time_point_tag, bool >::type
+ timed_wait(Lock& lock, TimePoint const& t, Predicate pred)
+ {
+ typedef typename sync::detail::time_traits< TimePoint >::unit_type unit_type;
+ unit_type abs_timeout = sync::detail::time_traits< TimePoint >::to_sync_unit(t);
+ while (!pred())
+ {
+ if (m_cond.timed_wait(lock, abs_timeout) != sync::cv_status::no_timeout)
+ return pred();
+ }
+ return true;
+ }
+
+ template< typename Lock, typename Duration, typename Predicate >
+ typename detail::enable_if_tag< Duration, detail::time_duration_tag, bool >::type
+ timed_wait(Lock& lock, Duration const& t, Predicate pred)
+ {
+ sync::detail::system_time_point abs_timeout = sync::detail::system_time_point::now() + sync::detail::time_traits< Duration >::to_sync_unit(t);
+ while (!pred())
+ {
+ if (m_cond.timed_wait(lock, abs_timeout) != sync::cv_status::no_timeout)
+ return pred();
+ }
+ return true;
+ }
+
+ template< typename Lock, typename TimePoint >
+ typename detail::enable_if_tag< TimePoint, detail::time_point_tag, sync::cv_status >::type
+ wait_until(Lock& lock, TimePoint const& abs_time)
+ {
+ return m_cond.timed_wait(lock, sync::detail::time_traits< TimePoint >::to_sync_unit(abs_time));
+ }
+
+ template< typename Lock, typename TimePoint, typename Predicate >
+ typename detail::enable_if_tag< TimePoint, detail::time_point_tag, bool >::type
+ wait_until(Lock& lock, TimePoint const& abs_time, Predicate pred)
+ {
+ typedef typename sync::detail::time_traits< TimePoint >::unit_type unit_type;
+ unit_type abs_timeout = sync::detail::time_traits< TimePoint >::to_sync_unit(abs_time);
+ while (!pred())
+ {
+ if (m_cond.timed_wait(lock, abs_timeout) != sync::cv_status::no_timeout)
+ return pred();
+ }
+ return true;
+ }
+
+ template< typename Lock, typename Duration >
+ typename detail::enable_if_tag< Duration, detail::time_duration_tag, sync::cv_status >::type
+ wait_for(Lock& lock, Duration const& rel_time)
+ {
+ return m_cond.timed_wait(lock, sync::detail::time_traits< Duration >::to_sync_unit(rel_time));
+ }
+
+ template< typename Lock, typename Duration, typename Predicate >
+ typename detail::enable_if_tag< Duration, detail::time_duration_tag, bool >::type
+ wait_for(Lock& lock, Duration const& rel_time, Predicate pred)
+ {
+ sync::detail::system_time_point abs_timeout = sync::detail::system_time_point::now() + sync::detail::time_traits< Duration >::to_sync_unit(rel_time);
+ while (!pred())
+ {
+ if (m_cond.timed_wait(lock, abs_timeout) != sync::cv_status::no_timeout)
+ return pred();
+ }
+ return true;
+ }
+
+ BOOST_DELETED_FUNCTION(condition_variable_any(condition_variable_any const&))
+ BOOST_DELETED_FUNCTION(condition_variable_any& operator= (condition_variable_any const&))
+};
+
+} // namespace abi
+
+} // namespace sync
+
+} // namespace boost
+
+#include <boost/sync/detail/footer.hpp>
+
+#endif // BOOST_SYNC_DETAIL_CONDITION_VARIABLES_CONDITION_VARIABLE_ANY_WINDOWS_HPP_INCLUDED_

Modified: trunk/boost/sync/detail/condition_variables/condition_variable_windows.hpp
==============================================================================
--- trunk/boost/sync/detail/condition_variables/condition_variable_windows.hpp Fri Oct 25 12:35:09 2013 (r86427)
+++ trunk/boost/sync/detail/condition_variables/condition_variable_windows.hpp 2013-10-25 12:35:13 EDT (Fri, 25 Oct 2013) (r86428)
@@ -164,7 +164,7 @@
     BOOST_DELETED_FUNCTION(condition_variable& operator= (condition_variable const&))
 };
 
-} // namespace posix
+} // namespace abi
 
 } // namespace sync
 

Modified: trunk/boost/sync/detail/events/auto_reset_event_emulation.hpp
==============================================================================
--- trunk/boost/sync/detail/events/auto_reset_event_emulation.hpp Fri Oct 25 12:35:09 2013 (r86427)
+++ trunk/boost/sync/detail/events/auto_reset_event_emulation.hpp 2013-10-25 12:35:13 EDT (Fri, 25 Oct 2013) (r86428)
@@ -1,4 +1,4 @@
-// event.hpp, condition variable emulation
+// auto_reset_event_emulation.hpp, event emulation
 //
 // Copyright (C) 2013 Tim Blechmann
 // Copyright (C) 2013 Andrey Semashev
@@ -23,7 +23,7 @@
 #pragma once
 #endif
 
-#define BOOST_SYNC_EVENT_EMULATED
+#define BOOST_SYNC_AUTO_RESET_EVENT_EMULATED
 
 namespace boost {
 
@@ -34,20 +34,22 @@
 class auto_reset_event
 {
     BOOST_DELETED_FUNCTION(auto_reset_event(auto_reset_event const&));
- BOOST_DELETED_FUNCTION(auto_reset_event& operator=(auto_reset_event const&));
+ BOOST_DELETED_FUNCTION(auto_reset_event& operator= (auto_reset_event const&));
 
 public:
- auto_reset_event() BOOST_NOEXCEPT : m_is_set(false)
+ auto_reset_event() : m_is_set(false)
     {
     }
 
     void post()
     {
         sync::lock_guard< sync::mutex > lock(m_mutex);
- bool already_signaled = m_is_set;
- m_is_set = true;
+ const bool already_signaled = m_is_set;
         if (!already_signaled)
+ {
+ m_is_set = true;
             m_cond.notify_one();
+ }
     }
 
     void wait()

Modified: trunk/boost/sync/detail/events/manual_reset_event_emulation.hpp
==============================================================================
--- trunk/boost/sync/detail/events/manual_reset_event_emulation.hpp Fri Oct 25 12:35:09 2013 (r86427)
+++ trunk/boost/sync/detail/events/manual_reset_event_emulation.hpp 2013-10-25 12:35:13 EDT (Fri, 25 Oct 2013) (r86428)
@@ -1,209 +1,119 @@
-// event.hpp, condition variable emulation
+// manual_reset_event_emulation.hpp, event emulation
 //
 // Copyright (C) 2013 Tim Blechmann
+// Copyright (C) 2013 Andrey Semashev
 //
 // 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)
 
-#ifndef BOOST_SYNC_DETAIL_EVENT_EVENT_EMULATION_HPP_INCLUDED_
-#define BOOST_SYNC_DETAIL_EVENT_EVENT_EMULATION_HPP_INCLUDED_
-
-#include <boost/sync/semaphore.hpp>
-
-// we use the semaphore implementation if we have native semaphores
-#ifndef BOOST_SYNC_SEMAPHORE_EMULATED
-#include <boost/sync/detail/event/event_autoreset_semaphore.hpp>
-#endif
-
-
-#include <boost/thread/condition_variable.hpp>
-#include <boost/thread/shared_mutex.hpp>
-#include <boost/thread/locks.hpp>
+#ifndef BOOST_SYNC_DETAIL_EVENTS_MANUAL_RESET_EVENT_EMULATION_HPP_INCLUDED_
+#define BOOST_SYNC_DETAIL_EVENTS_MANUAL_RESET_EVENT_EMULATION_HPP_INCLUDED_
 
+#include <boost/utility/enable_if.hpp>
 #include <boost/sync/detail/config.hpp>
-//#include <boost/sync/locks/lock_guard.hpp>
-//#include <boost/sync/locks/unique_lock.hpp>
+#include <boost/sync/detail/time_traits.hpp>
+#include <boost/sync/locks/lock_guard.hpp>
+#include <boost/sync/locks/unique_lock.hpp>
+#include <boost/sync/mutexes/mutex.hpp>
+#include <boost/sync/condition_variables/condition_variable.hpp>
 #include <boost/sync/detail/header.hpp>
 
-#define BOOST_SYNC_EVENT_EMULATED
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#define BOOST_SYNC_MANUAL_RESET_EVENT_EMULATED
 
 namespace boost {
-namespace sync {
-BOOST_SYNC_DETAIL_OPEN_ABI_NAMESPACE {
 
+namespace sync {
 
-#ifdef BOOST_SYNC_SEMAPHORE_EMULATED
+BOOST_SYNC_DETAIL_OPEN_ABI_NAMESPACE {
 
-class auto_reset_event
+class manual_reset_event
 {
- BOOST_DELETED_FUNCTION(auto_reset_event(auto_reset_event const&));
- BOOST_DELETED_FUNCTION(auto_reset_event& operator=(auto_reset_event const&));
+ BOOST_DELETED_FUNCTION(manual_reset_event(manual_reset_event const&));
+ BOOST_DELETED_FUNCTION(manual_reset_event& operator= (manual_reset_event const&));
 
 public:
- auto_reset_event() BOOST_NOEXCEPT :
- m_is_set(false)
- {}
-
- void post()
- {
- unique_lock<upgrade_mutex> lock(m_mutex);
- bool already_signaled = m_is_set;
- m_is_set = true;
- if (!already_signaled)
- m_cond.notify_one();
- }
-
- void wait()
+ manual_reset_event() : m_is_set(false)
     {
- upgrade_lock<upgrade_mutex> lock(m_mutex);
-
- while (!m_is_set)
- m_cond.wait(lock);
-
- upgrade_to_unique_lock<upgrade_mutex> unique_lock(lock);
- m_is_set = false;
- }
-
- void reset()
- {
- lock_guard<upgrade_mutex> lock(m_mutex);
- m_is_set = false;
     }
 
- bool try_wait()
+ void set()
     {
- lock_guard<upgrade_mutex> lock(m_mutex);
- const bool res = m_is_set;
- if (res)
- m_is_set = false;
- return res;
- }
-
- template <class Duration>
- bool try_wait_for(const Duration & duration)
- {
- upgrade_lock<upgrade_mutex> lock(m_mutex);
-
- while (!m_is_set) {
- if (m_cond.wait_for(lock, duration) == cv_status::timeout) {
- if (!m_is_set)
- return false;
- break;
- }
+ sync::lock_guard< sync::mutex > lock(m_mutex);
+ const bool already_signaled = m_is_set;
+ if (!already_signaled)
+ {
+ m_is_set = true;
+ m_cond.notify_all();
         }
-
- upgrade_to_unique_lock<upgrade_mutex> unique_lock(lock);
- m_is_set = false;
- return true;
     }
 
- template <typename TimePoint>
- bool try_wait_until(const TimePoint & timeout)
+ void reset()
     {
- upgrade_lock<upgrade_mutex> lock(m_mutex);
-
- while (!m_is_set) {
- if (m_cond.wait_until(lock, timeout) == cv_status::timeout) {
- if (!m_is_set)
- return false;
- break;
- }
- }
-
- upgrade_to_unique_lock<upgrade_mutex> unique_lock(lock);
+ sync::lock_guard< sync::mutex > lock(m_mutex);
         m_is_set = false;
- return true;
- }
-
-private:
- bool m_is_set;
- upgrade_mutex m_mutex;
- condition_variable_any m_cond;
-};
-
-#endif
-
-class manual_reset_event
-{
- BOOST_DELETED_FUNCTION(manual_reset_event(manual_reset_event const&));
- BOOST_DELETED_FUNCTION(manual_reset_event& operator=(manual_reset_event const&));
-
-public:
- manual_reset_event() BOOST_NOEXCEPT :
- m_is_set(false)
- {}
-
- void post()
- {
- unique_lock<upgrade_mutex> lock(m_mutex);
- bool already_signaled = m_is_set;
- m_is_set = true;
- m_cond.notify_all();
     }
 
     void wait()
     {
- upgrade_lock<upgrade_mutex> lock(m_mutex);
+ sync::unique_lock< sync::mutex > lock(m_mutex);
 
         while (!m_is_set)
             m_cond.wait(lock);
     }
 
- void reset()
- {
- lock_guard<upgrade_mutex> lock(m_mutex);
- m_is_set = false;
- }
-
     bool try_wait()
     {
- lock_guard<upgrade_mutex> lock(m_mutex);
+ sync::lock_guard< sync::mutex > lock(m_mutex);
         return m_is_set;
     }
 
- template <typename Duration>
- bool try_wait_for(const Duration & duration)
+ template< typename Time >
+ typename enable_if_c< sync::detail::time_traits< Time >::is_specialized, bool >::type timed_wait(Time const& timeout)
     {
- upgrade_lock<upgrade_mutex> lock(m_mutex);
-
- while (!m_is_set) {
- if (m_cond.wait_for(lock, duration) == cv_status::timeout) {
+ sync::unique_lock< sync::mutex > lock(m_mutex);
+ while (!m_is_set)
+ {
+ if (!m_cond.timed_wait(lock, timeout))
+ {
                 if (!m_is_set)
                     return false;
- break;
+ else
+ break;
             }
         }
 
         return true;
     }
 
- template <typename TimePoint>
- bool try_wait_until(const TimePoint & timeout)
+ template< typename Duration >
+ typename enable_if< detail::is_time_tag_of< Duration, detail::time_duration_tag >, bool >::type wait_for(Duration const& duration)
     {
- upgrade_lock<upgrade_mutex> lock(m_mutex);
-
- while (!m_is_set) {
- if (m_cond.wait_until(lock, timeout) == cv_status::timeout) {
- if (!m_is_set)
- return false;
- break;
- }
- }
+ return timed_wait(duration);
+ }
 
- return true;
+ template< typename TimePoint >
+ typename enable_if< detail::is_time_tag_of< TimePoint, detail::time_point_tag >, bool >::type wait_until(TimePoint const& abs_time)
+ {
+ return timed_wait(abs_time);
     }
 
 private:
+ sync::mutex m_mutex;
+ sync::condition_variable m_cond;
     bool m_is_set;
- upgrade_mutex m_mutex;
- condition_variable_any m_cond;
 };
 
-}
-}
-}
+} // namespace abi
+
+} // namespace sync
+
+} // namespace boost
 
 #include <boost/sync/detail/footer.hpp>
 
-#endif // BOOST_SYNC_DETAIL_EVENT_EVENT_EMULATION_HPP_INCLUDED_
+#endif // BOOST_SYNC_DETAIL_EVENTS_MANUAL_RESET_EVENT_EMULATION_HPP_INCLUDED_

Modified: trunk/boost/sync/detail/mutexes/timed_mutex_posix.hpp
==============================================================================
--- trunk/boost/sync/detail/mutexes/timed_mutex_posix.hpp Fri Oct 25 12:35:09 2013 (r86427)
+++ trunk/boost/sync/detail/mutexes/timed_mutex_posix.hpp 2013-10-25 12:35:13 EDT (Fri, 25 Oct 2013) (r86428)
@@ -37,7 +37,9 @@
 #pragma once
 #endif
 
+#if defined(BOOST_SYNC_DETAIL_PTHREAD_HAS_TIMEDLOCK)
 #define BOOST_SYNC_DEFINES_TIMED_MUTEX_NATIVE_HANDLE
+#endif
 
 namespace boost {
 
@@ -51,8 +53,9 @@
 #if defined(BOOST_SYNC_DETAIL_PTHREAD_HAS_TIMEDLOCK)
     typedef void _is_condition_variable_compatible;
 #endif
-
+#if defined(BOOST_SYNC_DEFINES_TIMED_MUTEX_NATIVE_HANDLE)
     typedef pthread_mutex_t* native_handle_type;
+#endif
 
 private:
     pthread_mutex_t m_mutex;
@@ -186,10 +189,12 @@
         return priv_timed_lock(sync::detail::time_traits< TimePoint >::to_sync_unit(abs_time));
     }
 
+#if defined(BOOST_SYNC_DEFINES_TIMED_MUTEX_NATIVE_HANDLE)
     native_handle_type native_handle() BOOST_NOEXCEPT
     {
         return &m_mutex;
     }
+#endif
 
     BOOST_DELETED_FUNCTION(timed_mutex(timed_mutex const&))
     BOOST_DELETED_FUNCTION(timed_mutex& operator= (timed_mutex const&))

Modified: trunk/libs/sync/doc/Jamfile.v2
==============================================================================
--- trunk/libs/sync/doc/Jamfile.v2 Fri Oct 25 12:35:09 2013 (r86427)
+++ trunk/libs/sync/doc/Jamfile.v2 2013-10-25 12:35:13 EDT (Fri, 25 Oct 2013) (r86428)
@@ -44,6 +44,7 @@
 # <doxygen:param>"INCLUDE_PATH=../../.."
 # <doxygen:param>EXCLUDE_SYMBOLS="aux aux::*"
         <doxygen:param>"PREDEFINED=BOOST_SYNC_DETAIL_DOXYGEN \\
+ BOOST_SYNC_API= \\
                         BOOST_SYMBOL_VISIBLE= \\
                         BOOST_FORCEINLINE=inline \\
                         BOOST_STATIC_ASSERT(x)= \\

Modified: trunk/libs/sync/src/tss_manager.hpp
==============================================================================
--- trunk/libs/sync/src/tss_manager.hpp Fri Oct 25 12:35:09 2013 (r86427)
+++ trunk/libs/sync/src/tss_manager.hpp 2013-10-25 12:35:13 EDT (Fri, 25 Oct 2013) (r86428)
@@ -25,6 +25,7 @@
 #include <boost/sync/locks/lock_guard.hpp>
 #include <boost/sync/locks/unique_lock.hpp>
 #include <boost/sync/mutexes/mutex.hpp>
+#include <boost/sync/condition_variables/condition_variable.hpp>
 #include <boost/sync/detail/tss.hpp>
 #include <boost/sync/detail/header.hpp>
 
@@ -58,9 +59,16 @@
             void* context;
         };
 
+ struct notify_at_exit_entry
+ {
+ sync::mutex* mtx;
+ sync::condition_variable* cond;
+ };
+
     private:
         std::vector< void* > m_storage;
         std::vector< at_exit_entry > m_at_exit_functions;
+ std::vector< notify_at_exit_entry > m_notify_at_exit;
 
     public:
         void* get_value(thread_specific_key key) const BOOST_NOEXCEPT
@@ -85,6 +93,14 @@
             entry.context = context;
             m_at_exit_functions.push_back(entry);
         }
+
+ void add_notify_at_exit_entry(sync::mutex* mtx, sync::condition_variable* cond)
+ {
+ notify_at_exit_entry entry;
+ entry.mtx = mtx;
+ entry.cond = cond;
+ m_notify_at_exit.push_back(entry);
+ }
     };
 
 private:
@@ -162,6 +178,13 @@
             }
         }
 
+ // Notify about thread termination. This must be performed last, after all TLS variables are destroyed.
+ for (std::vector< thread_context::notify_at_exit_entry >::const_iterator it = p->m_notify_at_exit.begin(), end = p->m_notify_at_exit.end(); it != end; ++it)
+ {
+ it->mtx->unlock();
+ it->cond->notify_all();
+ }
+
         // Destroy the context
         {
             sync::lock_guard< mutex_type > lock(m_mutex);

Modified: trunk/libs/sync/src/tss_pthread.cpp
==============================================================================
--- trunk/libs/sync/src/tss_pthread.cpp Fri Oct 25 12:35:09 2013 (r86427)
+++ trunk/libs/sync/src/tss_pthread.cpp 2013-10-25 12:35:13 EDT (Fri, 25 Oct 2013) (r86428)
@@ -21,6 +21,7 @@
 #include <cstdlib>
 #include <pthread.h>
 #include <boost/sync/detail/tss.hpp>
+#include <boost/sync/condition_variables/notify_all_at_thread_exit.hpp>
 #include "tss_manager.hpp"
 #include <boost/sync/detail/header.hpp>
 
@@ -34,7 +35,11 @@
 
 static pthread_once_t init_tss_once_flag = PTHREAD_ONCE_INIT;
 static tss_manager* tss_mgr = NULL;
+#if defined(BOOST_SYNC_DETAIL_TLS)
+static BOOST_SYNC_DETAIL_TLS tss_manager::thread_context* tss_context = NULL;
+#else
 static pthread_key_t tss_key;
+#endif
 
 extern "C" {
 
@@ -57,23 +62,63 @@
         std::abort();
     }
 
+#if !defined(BOOST_SYNC_DETAIL_TLS)
     if (pthread_key_create(&tss_key, &tss_cleanup) != 0)
         std::abort();
+#endif
 }
 
 } // extern "C"
 
+#if defined(BOOST_SYNC_DETAIL_TLS)
+
+BOOST_FORCEINLINE tss_manager::thread_context* get_thread_context() BOOST_NOEXCEPT
+{
+ return tss_context;
+}
+BOOST_FORCEINLINE void set_thread_context(tss_manager::thread_context* p) BOOST_NOEXCEPT
+{
+ tss_context = p;
+}
+
+#else // defined(BOOST_SYNC_DETAIL_TLS)
+
+BOOST_FORCEINLINE tss_manager::thread_context* get_thread_context() BOOST_NOEXCEPT
+{
+ return static_cast< tss_manager::thread_context* >(pthread_getspecific(tss_key));
+}
+BOOST_FORCEINLINE void set_thread_context(tss_manager::thread_context* p) BOOST_NOEXCEPT
+{
+ pthread_setspecific(tss_key, p);
+}
+
+#endif // defined(BOOST_SYNC_DETAIL_TLS)
+
 } // namespace
 
+BOOST_SYNC_API void add_thread_exit_notify_entry(sync::mutex* mtx, sync::condition_variable* cond)
+{
+ pthread_once(&init_tss_once_flag, &init_tss);
+ tss_manager::thread_context* ctx = get_thread_context();
+
+ if (!ctx)
+ {
+ ctx = tss_mgr->create_thread_context();
+ set_thread_context(ctx);
+ }
+
+ ctx->add_notify_at_exit_entry(mtx, cond);
+}
+
 BOOST_SYNC_API void add_thread_exit_callback(at_thread_exit_callback callback, void* context)
 {
     pthread_once(&init_tss_once_flag, &init_tss);
- tss_manager::thread_context* ctx = static_cast< tss_manager::thread_context* >(pthread_getspecific(tss_key));
+ tss_manager::thread_context* ctx = get_thread_context();
 
     if (!ctx)
     {
         ctx = tss_mgr->create_thread_context();
- pthread_setspecific(tss_key, ctx);
+ set_thread_context(ctx);
     }
 
     ctx->add_at_exit_entry(callback, context);
@@ -99,7 +144,7 @@
 
 BOOST_SYNC_API void* get_thread_specific(thread_specific_key key)
 {
- tss_manager::thread_context* ctx = static_cast< tss_manager::thread_context* >(pthread_getspecific(tss_key));
+ tss_manager::thread_context* ctx = get_thread_context();
     if (ctx)
         return ctx->get_value(key);
     return NULL;
@@ -107,12 +152,12 @@
 
 BOOST_SYNC_API void set_thread_specific(thread_specific_key key, void* p)
 {
- tss_manager::thread_context* ctx = static_cast< tss_manager::thread_context* >(pthread_getspecific(tss_key));
+ tss_manager::thread_context* ctx = get_thread_context();
 
     if (!ctx)
     {
         ctx = tss_mgr->create_thread_context();
- pthread_setspecific(tss_key, ctx);
+ set_thread_context(ctx);
     }
 
     ctx->set_value(key, p);

Modified: trunk/libs/sync/src/tss_windows.cpp
==============================================================================
--- trunk/libs/sync/src/tss_windows.cpp Fri Oct 25 12:35:09 2013 (r86427)
+++ trunk/libs/sync/src/tss_windows.cpp 2013-10-25 12:35:13 EDT (Fri, 25 Oct 2013) (r86428)
@@ -21,6 +21,7 @@
 #include <cstdlib>
 #include <boost/sync/detail/interlocked.hpp>
 #include <boost/sync/detail/tss.hpp>
+#include <boost/sync/condition_variables/notify_all_at_thread_exit.hpp>
 #include "tss_manager.hpp"
 #include "tss_windows_hooks.hpp"
 #include <windows.h>
@@ -165,6 +166,20 @@
 
 } // namespace windows
 
+BOOST_SYNC_API void add_thread_exit_notify_entry(sync::mutex* mtx, sync::condition_variable* cond)
+{
+ init_tss_once();
+ tss_manager::thread_context* ctx = get_thread_context();
+
+ if (!ctx)
+ {
+ ctx = tss_mgr->create_thread_context();
+ set_thread_context(ctx);
+ }
+
+ ctx->add_notify_at_exit_entry(mtx, cond);
+}
+
 BOOST_SYNC_API void add_thread_exit_callback(at_thread_exit_callback callback, void* context)
 {
     init_tss_once();

Modified: trunk/libs/sync/test/run/mutex_test.cpp
==============================================================================
--- trunk/libs/sync/test/run/mutex_test.cpp Fri Oct 25 12:35:09 2013 (r86427)
+++ trunk/libs/sync/test/run/mutex_test.cpp 2013-10-25 12:35:13 EDT (Fri, 25 Oct 2013) (r86428)
@@ -7,9 +7,12 @@
 #include <boost/test/unit_test.hpp>
 
 #include <boost/bind.hpp>
+#include <boost/mpl/if.hpp>
 #include <boost/sync/mutexes.hpp>
 #include <boost/sync/locks.hpp>
 #include <boost/sync/condition_variables/condition_variable.hpp>
+#include <boost/sync/condition_variables/condition_variable_any.hpp>
+#include <boost/sync/traits/is_condition_variable_compatible.hpp>
 #include <boost/sync/support/boost_date_time.hpp>
 #include <boost/thread/thread.hpp>
 #include <boost/thread/thread_time.hpp>
@@ -21,12 +24,17 @@
 struct test_lock
 {
     typedef M mutex_type;
+ typedef typename boost::mpl::if_<
+ boost::sync::is_condition_variable_compatible< mutex_type >,
+ boost::sync::condition_variable,
+ boost::sync::condition_variable_any
+ >::type condition_variable_type;
     typedef boost::sync::unique_lock< mutex_type > lock_type;
 
     void operator()() const
     {
         mutex_type mutex;
- boost::sync::condition_variable condition;
+ condition_variable_type condition;
 
         // Test the lock's constructors.
         {
@@ -57,12 +65,17 @@
 struct test_trylock
 {
     typedef M mutex_type;
+ typedef typename boost::mpl::if_<
+ boost::sync::is_condition_variable_compatible< mutex_type >,
+ boost::sync::condition_variable,
+ boost::sync::condition_variable_any
+ >::type condition_variable_type;
     typedef boost::sync::unique_lock< mutex_type > lock_type;
 
     void operator()()
     {
         mutex_type mutex;
- boost::sync::condition_variable condition;
+ condition_variable_type condition;
 
         // Test the lock's constructors.
         {
@@ -182,6 +195,11 @@
 struct test_timedlock
 {
     typedef M mutex_type;
+ typedef typename boost::mpl::if_<
+ boost::sync::is_condition_variable_compatible< mutex_type >,
+ boost::sync::condition_variable,
+ boost::sync::condition_variable_any
+ >::type condition_variable_type;
     typedef boost::sync::unique_lock< mutex_type > lock_type;
     typedef boost::sync::unique_lock< mutex_type > timed_lock_type;
 
@@ -195,7 +213,7 @@
         test_lock_times_out_if_other_thread_has_lock<mutex_type>()();
 
         mutex_type mutex;
- boost::sync::condition_variable condition;
+ condition_variable_type condition;
 
         // Test the lock's constructors.
         {
@@ -284,7 +302,7 @@
     timed_test(&do_test_try_mutex, 3);
 }
 
-/*
+
 void do_test_timed_mutex()
 {
     test_lock<boost::sync::timed_mutex>()();
@@ -297,6 +315,7 @@
     timed_test(&do_test_timed_mutex, 3);
 }
 
+/*
 void do_test_recursive_mutex()
 {
     test_lock<boost::recursive_mutex>()();


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