|
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