Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r86480 - in trunk: boost/sync/thread_specific libs/sync/test/run
From: andrey.semashev_at_[hidden]
Date: 2013-10-27 12:11:25


Author: andysem
Date: 2013-10-27 12:11:25 EDT (Sun, 27 Oct 2013)
New Revision: 86480
URL: http://svn.boost.org/trac/boost/changeset/86480

Log:
Added more tests.

Added:
   trunk/libs/sync/test/run/at_thread_exit.cpp (contents, props changed)
   trunk/libs/sync/test/run/condition_test_common.hpp (contents, props changed)
   trunk/libs/sync/test/run/condition_variable.cpp (contents, props changed)
   trunk/libs/sync/test/run/condition_variable_notify_all.cpp (contents, props changed)
   trunk/libs/sync/test/run/condition_variable_notify_one.cpp (contents, props changed)
   trunk/libs/sync/test/run/condition_variable_timed_wait_times_out.cpp (contents, props changed)
   trunk/libs/sync/test/run/thread_specific_ptr.cpp (contents, props changed)
Text files modified:
   trunk/boost/sync/thread_specific/thread_specific_ptr.hpp | 8
   trunk/libs/sync/test/run/at_thread_exit.cpp | 45 ++++
   trunk/libs/sync/test/run/chrono_system_clock_time_t_mismatch.cpp | 48 +++++
   trunk/libs/sync/test/run/condition_test_common.hpp | 106 +++++++++++
   trunk/libs/sync/test/run/condition_variable.cpp | 164 +++++++++++++++++
   trunk/libs/sync/test/run/condition_variable_notify_all.cpp | 228 +++++++++++++++++++++++
   trunk/libs/sync/test/run/condition_variable_notify_one.cpp | 161 ++++++++++++++++
   trunk/libs/sync/test/run/condition_variable_timed_wait_times_out.cpp | 193 ++++++++++++++++++++
   trunk/libs/sync/test/run/thread_specific_ptr.cpp | 383 ++++++++++++++++++++++++++++++++++++++++
   9 files changed, 1332 insertions(+), 4 deletions(-)

Modified: trunk/boost/sync/thread_specific/thread_specific_ptr.hpp
==============================================================================
--- trunk/boost/sync/thread_specific/thread_specific_ptr.hpp Sun Oct 27 09:20:44 2013 (r86479)
+++ trunk/boost/sync/thread_specific/thread_specific_ptr.hpp 2013-10-27 12:11:25 EDT (Sun, 27 Oct 2013) (r86480)
@@ -40,14 +40,14 @@
     const sync::detail::at_thread_exit_callback m_cleanup;
 
 public:
- explicit thread_specific_ptr(bool cleanup_on_destroy = false) :
- m_key(sync::detail::new_thread_specific_key(&thread_specific_ptr< T >::default_cleanup, cleanup_on_destroy)),
+ explicit thread_specific_ptr() :
+ m_key(sync::detail::new_thread_specific_key(&thread_specific_ptr< T >::default_cleanup, true)),
         m_cleanup(&thread_specific_ptr< T >::default_cleanup)
     {
     }
 
- explicit thread_specific_ptr(void (*cleanup)(T*), bool cleanup_on_destroy = false) :
- m_key(sync::detail::new_thread_specific_key((sync::detail::at_thread_exit_callback)cleanup, cleanup_on_destroy)),
+ explicit thread_specific_ptr(void (*cleanup)(T*)) :
+ m_key(sync::detail::new_thread_specific_key((sync::detail::at_thread_exit_callback)cleanup, true)),
         m_cleanup((sync::detail::at_thread_exit_callback)cleanup)
     {
     }

Added: trunk/libs/sync/test/run/at_thread_exit.cpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/sync/test/run/at_thread_exit.cpp 2013-10-27 12:11:25 EDT (Sun, 27 Oct 2013) (r86480)
@@ -0,0 +1,45 @@
+/*
+ * Copyright Andrey Semashev 2013.
+ * 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)
+ */
+/*!
+ * \file at_thread_exit.cpp
+ *
+ * \brief This test checks that \c at_thread_exit works
+ */
+
+#include <boost/test/unit_test.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/sync/thread_specific/at_thread_exit.hpp>
+
+unsigned int called = 0;
+
+struct my_at_thread_exit
+{
+ typedef void result_type;
+
+ explicit my_at_thread_exit(unsigned int& n) : m_called(&n) {}
+
+ void operator() () const
+ {
+ ++(*m_called);
+ }
+
+private:
+ unsigned int* m_called;
+};
+
+void my_thread_routine()
+{
+ boost::sync::at_thread_exit(my_at_thread_exit(called));
+}
+
+
+BOOST_AUTO_TEST_CASE(test_at_thread_exit)
+{
+ boost::thread t(&my_thread_routine);
+ t.join();
+ BOOST_CHECK_EQUAL(called, 1);
+}

Modified: trunk/libs/sync/test/run/chrono_system_clock_time_t_mismatch.cpp
==============================================================================
--- trunk/libs/sync/test/run/chrono_system_clock_time_t_mismatch.cpp Sun Oct 27 09:20:44 2013 (r86479)
+++ trunk/libs/sync/test/run/chrono_system_clock_time_t_mismatch.cpp 2013-10-27 12:11:25 EDT (Sun, 27 Oct 2013) (r86480)
@@ -33,9 +33,57 @@
 {
     BOOST_SYNC_DETAIL_CHECK_CLOCK(std::chrono::system_clock::to_time_t(std::chrono::system_clock::time_point()));
 }
+
+BOOST_AUTO_TEST_CASE(std_chrono_system_clock_time_t_now_mismatch)
+{
+ std::time_t t1, t3;
+ std::chrono::system_clock::time_point chrono_t2;
+ do
+ {
+ t1 = std::time(0);
+ chrono_t2 = std::chrono::system_clock::now();
+ t3 = std::time(0);
+ }
+ while (t1 != t3);
+ std::time_t t2 = std::chrono::system_clock::to_time_t(chrono_t2);
+
+ // to_time_t is allowed to perform arithmetic rounding to seconds
+ if (t2 > t1)
+ {
+ BOOST_CHECK_EQUAL((t2 - t1), 1);
+ }
+ else
+ {
+ BOOST_CHECK_EQUAL(t1, t2);
+ }
+}
 #endif
 
 BOOST_AUTO_TEST_CASE(boost_chrono_system_clock_time_t_mismatch)
 {
     BOOST_CHECK_EQUAL(boost::chrono::system_clock::to_time_t(boost::chrono::system_clock::time_point()), (std::time_t)0);
 }
+
+BOOST_AUTO_TEST_CASE(boost_chrono_system_clock_time_t_now_mismatch)
+{
+ std::time_t t1, t3;
+ boost::chrono::system_clock::time_point chrono_t2;
+ do
+ {
+ t1 = std::time(0);
+ chrono_t2 = boost::chrono::system_clock::now();
+ t3 = std::time(0);
+ }
+ while (t1 != t3);
+ std::time_t t2 = boost::chrono::system_clock::to_time_t(chrono_t2);
+
+ // to_time_t is allowed to perform arithmetic rounding to seconds
+ if (t2 > t1)
+ {
+ BOOST_CHECK_EQUAL((t2 - t1), 1);
+ }
+ else
+ {
+ BOOST_CHECK_EQUAL(t1, t2);
+ }
+}

Added: trunk/libs/sync/test/run/condition_test_common.hpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/sync/test/run/condition_test_common.hpp 2013-10-27 12:11:25 EDT (Sun, 27 Oct 2013) (r86480)
@@ -0,0 +1,106 @@
+#ifndef BOOST_SYNC_TEST_CONDITION_TEST_COMMON_HPP
+#define BOOST_SYNC_TEST_CONDITION_TEST_COMMON_HPP
+// Copyright (C) 2007 Anthony Williams
+// 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)
+
+#include <boost/config.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <boost/date_time/posix_time/posix_time_types.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/support/boost_date_time.hpp>
+
+unsigned const timeout_seconds = 5;
+
+struct wait_for_flag
+{
+ struct check_flag
+ {
+ bool const& flag;
+
+ check_flag(bool const& flag_):
+ flag(flag_)
+ {
+ }
+
+ bool operator()() const
+ {
+ return flag;
+ }
+
+ BOOST_DELETED_FUNCTION(check_flag(check_flag const&))
+ BOOST_DELETED_FUNCTION(check_flag& operator=(check_flag const&))
+ };
+
+ boost::sync::mutex mutex;
+ boost::sync::condition_variable cond_var;
+ bool flag;
+ unsigned woken;
+
+ wait_for_flag():
+ flag(false),woken(0)
+ {
+ }
+
+ void wait_without_predicate()
+ {
+ boost::sync::unique_lock<boost::sync::mutex> lock(mutex);
+ while(!flag)
+ {
+ cond_var.wait(lock);
+ }
+ ++woken;
+ }
+
+ void wait_with_predicate()
+ {
+ boost::sync::unique_lock<boost::sync::mutex> lock(mutex);
+ cond_var.wait(lock,check_flag(flag));
+ if(flag)
+ {
+ ++woken;
+ }
+ }
+
+ void timed_wait_without_predicate()
+ {
+ boost::system_time const timeout = boost::get_system_time() + boost::posix_time::seconds(timeout_seconds);
+
+ boost::sync::unique_lock<boost::sync::mutex> lock(mutex);
+ while(!flag)
+ {
+ if(!cond_var.timed_wait(lock,timeout))
+ {
+ return;
+ }
+ }
+ ++woken;
+ }
+
+ void timed_wait_with_predicate()
+ {
+ boost::system_time const timeout = boost::get_system_time() + boost::posix_time::seconds(timeout_seconds);
+ boost::sync::unique_lock<boost::sync::mutex> lock(mutex);
+ if(cond_var.timed_wait(lock,timeout,check_flag(flag)) && flag)
+ {
+ ++woken;
+ }
+ }
+ void relative_timed_wait_with_predicate()
+ {
+ boost::sync::unique_lock<boost::sync::mutex> lock(mutex);
+ if(cond_var.timed_wait(lock,boost::posix_time::seconds(timeout_seconds),check_flag(flag)) && flag)
+ {
+ ++woken;
+ }
+ }
+
+ BOOST_DELETED_FUNCTION(wait_for_flag(wait_for_flag const&))
+ BOOST_DELETED_FUNCTION(wait_for_flag& operator=(wait_for_flag const&))
+};
+
+#endif

Added: trunk/libs/sync/test/run/condition_variable.cpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/sync/test/run/condition_variable.cpp 2013-10-27 12:11:25 EDT (Sun, 27 Oct 2013) (r86480)
@@ -0,0 +1,164 @@
+// Copyright (C) 2001-2003
+// William E. Kempf
+// Copyright (C) 2007 Anthony Williams
+// 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)
+
+#include <boost/config.hpp>
+#include <boost/bind.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/support/boost_date_time.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/test/unit_test.hpp>
+#include "utils.hpp"
+
+struct condition_test_data
+{
+ condition_test_data() : notified(0), awoken(0) { }
+
+ boost::sync::mutex mutex;
+ boost::sync::condition_variable condition;
+ int notified;
+ int awoken;
+};
+
+void condition_test_thread(condition_test_data* data)
+{
+ boost::sync::unique_lock<boost::sync::mutex> lock(data->mutex);
+ BOOST_CHECK(lock ? true : false);
+ while (!(data->notified > 0))
+ data->condition.wait(lock);
+ BOOST_CHECK(lock ? true : false);
+ data->awoken++;
+}
+
+struct cond_predicate
+{
+ cond_predicate(int& var, int val) : _var(var), _val(val) { }
+
+ bool operator()() { return _var == _val; }
+
+ int& _var;
+ int _val;
+
+ BOOST_DELETED_FUNCTION(cond_predicate& operator=(cond_predicate const&))
+};
+
+void condition_test_waits(condition_test_data* data)
+{
+ boost::sync::unique_lock<boost::sync::mutex> lock(data->mutex);
+ BOOST_CHECK(lock ? true : false);
+
+ // Test wait.
+ while (data->notified != 1)
+ data->condition.wait(lock);
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK_EQUAL(data->notified, 1);
+ data->awoken++;
+ data->condition.notify_one();
+
+ // Test predicate wait.
+ data->condition.wait(lock, cond_predicate(data->notified, 2));
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK_EQUAL(data->notified, 2);
+ data->awoken++;
+ data->condition.notify_one();
+
+ // Test timed_wait.
+ boost::system_time xt = boost::get_system_time() + boost::posix_time::seconds(10);
+ while (data->notified != 3)
+ data->condition.timed_wait(lock, xt);
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK_EQUAL(data->notified, 3);
+ data->awoken++;
+ data->condition.notify_one();
+
+ // Test predicate timed_wait.
+ xt = boost::get_system_time() + boost::posix_time::seconds(10);
+ cond_predicate pred(data->notified, 4);
+ BOOST_CHECK(data->condition.timed_wait(lock, xt, pred));
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK(pred());
+ BOOST_CHECK_EQUAL(data->notified, 4);
+ data->awoken++;
+ data->condition.notify_one();
+
+ // Test predicate timed_wait with relative timeout
+ cond_predicate pred_rel(data->notified, 5);
+ BOOST_CHECK(data->condition.timed_wait(lock, boost::posix_time::seconds(10), pred_rel));
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK(pred_rel());
+ BOOST_CHECK_EQUAL(data->notified, 5);
+ data->awoken++;
+ data->condition.notify_one();
+}
+
+void do_test_condition_waits()
+{
+ condition_test_data data;
+
+ boost::thread thread(boost::bind(&condition_test_waits, &data));
+
+ {
+ boost::sync::unique_lock<boost::sync::mutex> lock(data.mutex);
+ BOOST_CHECK(lock ? true : false);
+
+ boost::thread::sleep(boost::get_system_time() + boost::posix_time::seconds(1));
+ data.notified++;
+ data.condition.notify_one();
+ while (data.awoken != 1)
+ data.condition.wait(lock);
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK_EQUAL(data.awoken, 1);
+
+ boost::thread::sleep(boost::get_system_time() + boost::posix_time::seconds(1));
+ data.notified++;
+ data.condition.notify_one();
+ while (data.awoken != 2)
+ data.condition.wait(lock);
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK_EQUAL(data.awoken, 2);
+
+ boost::thread::sleep(boost::get_system_time() + boost::posix_time::seconds(1));
+ data.notified++;
+ data.condition.notify_one();
+ while (data.awoken != 3)
+ data.condition.wait(lock);
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK_EQUAL(data.awoken, 3);
+
+ boost::thread::sleep(boost::get_system_time() + boost::posix_time::seconds(1));
+ data.notified++;
+ data.condition.notify_one();
+ while (data.awoken != 4)
+ data.condition.wait(lock);
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK_EQUAL(data.awoken, 4);
+
+
+ boost::thread::sleep(boost::get_system_time() + boost::posix_time::seconds(1));
+ data.notified++;
+ data.condition.notify_one();
+ while (data.awoken != 5)
+ data.condition.wait(lock);
+ BOOST_CHECK(lock ? true : false);
+ BOOST_CHECK_EQUAL(data.awoken, 5);
+ }
+
+ thread.join();
+ BOOST_CHECK_EQUAL(data.awoken, 5);
+}
+
+BOOST_AUTO_TEST_CASE(test_condition_waits)
+{
+ // We should have already tested notify_one here, so
+ // a timed test with the default execution_monitor::use_condition
+ // should be OK, and gives the fastest performance
+ timed_test(&do_test_condition_waits, 12);
+}

Added: trunk/libs/sync/test/run/condition_variable_notify_all.cpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/sync/test/run/condition_variable_notify_all.cpp 2013-10-27 12:11:25 EDT (Sun, 27 Oct 2013) (r86480)
@@ -0,0 +1,228 @@
+// Copyright (C) 2007 Anthony Williams
+// 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)
+
+#include <boost/bind.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/test/unit_test.hpp>
+#include "utils.hpp"
+#include "condition_test_common.hpp"
+
+unsigned const number_of_test_threads = 5;
+
+void do_test_condition_notify_all_wakes_from_wait()
+{
+ wait_for_flag data;
+
+ boost::thread_group group;
+
+ try
+ {
+ for(unsigned i=0;i<number_of_test_threads;++i)
+ {
+ group.create_thread(bind(&wait_for_flag::wait_without_predicate, data));
+ }
+
+ {
+ boost::sync::unique_lock<boost::sync::mutex> lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_all();
+ }
+
+ group.join_all();
+ BOOST_CHECK_EQUAL(data.woken,number_of_test_threads);
+ }
+ catch(...)
+ {
+ group.join_all();
+ throw;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_condition_notify_all_wakes_from_wait)
+{
+ timed_test(&do_test_condition_notify_all_wakes_from_wait, timeout_seconds);
+}
+
+void do_test_condition_notify_all_wakes_from_wait_with_predicate()
+{
+ wait_for_flag data;
+
+ boost::thread_group group;
+
+ try
+ {
+ for(unsigned i=0;i<number_of_test_threads;++i)
+ {
+ group.create_thread(bind(&wait_for_flag::wait_with_predicate, data));
+ }
+
+ {
+ boost::sync::unique_lock<boost::sync::mutex> lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_all();
+ }
+
+ group.join_all();
+ BOOST_CHECK_EQUAL(data.woken,number_of_test_threads);
+ }
+ catch(...)
+ {
+ group.join_all();
+ throw;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_condition_notify_all_wakes_from_wait_with_predicate)
+{
+ timed_test(&do_test_condition_notify_all_wakes_from_wait_with_predicate, timeout_seconds);
+}
+
+void do_test_condition_notify_all_wakes_from_timed_wait()
+{
+ wait_for_flag data;
+
+ boost::thread_group group;
+
+ try
+ {
+ for(unsigned i=0;i<number_of_test_threads;++i)
+ {
+ group.create_thread(bind(&wait_for_flag::timed_wait_without_predicate, data));
+ }
+
+ {
+ boost::sync::unique_lock<boost::sync::mutex> lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_all();
+ }
+
+ group.join_all();
+ BOOST_CHECK_EQUAL(data.woken,number_of_test_threads);
+ }
+ catch(...)
+ {
+ group.join_all();
+ throw;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_condition_notify_all_wakes_from_timed_wait)
+{
+ timed_test(&do_test_condition_notify_all_wakes_from_timed_wait, timeout_seconds);
+}
+
+void do_test_condition_notify_all_wakes_from_timed_wait_with_predicate()
+{
+ wait_for_flag data;
+
+ boost::thread_group group;
+
+ try
+ {
+ for(unsigned i=0;i<number_of_test_threads;++i)
+ {
+ group.create_thread(bind(&wait_for_flag::timed_wait_with_predicate, data));
+ }
+
+ {
+ boost::sync::unique_lock<boost::sync::mutex> lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_all();
+ }
+
+ group.join_all();
+ BOOST_CHECK_EQUAL(data.woken,number_of_test_threads);
+ }
+ catch(...)
+ {
+ group.join_all();
+ throw;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_condition_notify_all_wakes_from_timed_wait_with_predicate)
+{
+ timed_test(&do_test_condition_notify_all_wakes_from_timed_wait_with_predicate, timeout_seconds);
+}
+
+void do_test_condition_notify_all_wakes_from_relative_timed_wait_with_predicate()
+{
+ wait_for_flag data;
+
+ boost::thread_group group;
+
+ try
+ {
+ for(unsigned i=0;i<number_of_test_threads;++i)
+ {
+ group.create_thread(bind(&wait_for_flag::relative_timed_wait_with_predicate, data));
+ }
+
+ {
+ boost::sync::unique_lock<boost::sync::mutex> lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_all();
+ }
+
+ group.join_all();
+ BOOST_CHECK_EQUAL(data.woken,number_of_test_threads);
+ }
+ catch(...)
+ {
+ group.join_all();
+ throw;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_condition_notify_all_wakes_from_relative_timed_wait_with_predicate)
+{
+ timed_test(&do_test_condition_notify_all_wakes_from_relative_timed_wait_with_predicate, timeout_seconds);
+}
+
+namespace {
+
+boost::sync::mutex multiple_wake_mutex;
+boost::sync::condition_variable multiple_wake_cond;
+unsigned multiple_wake_count = 0;
+
+void wait_for_condvar_and_increase_count()
+{
+ boost::sync::unique_lock<boost::sync::mutex> lk(multiple_wake_mutex);
+ multiple_wake_cond.wait(lk);
+ ++multiple_wake_count;
+}
+
+} // namespace
+
+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::sync::unique_lock<boost::sync::mutex> lk(multiple_wake_mutex);
+ BOOST_CHECK(multiple_wake_count==3);
+ }
+
+ thread1.join();
+ thread2.join();
+ thread3.join();
+}
+
+BOOST_AUTO_TEST_CASE(test_notify_all_following_notify_one_wakes_all_threads)
+{
+ timed_test(&do_test_notify_all_following_notify_one_wakes_all_threads, timeout_seconds);
+}

Added: trunk/libs/sync/test/run/condition_variable_notify_one.cpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/sync/test/run/condition_variable_notify_one.cpp 2013-10-27 12:11:25 EDT (Sun, 27 Oct 2013) (r86480)
@@ -0,0 +1,161 @@
+// Copyright (C) 2007 Anthony Williams
+// 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)
+
+#include <boost/bind.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/test/unit_test.hpp>
+#include "utils.hpp"
+#include "condition_test_common.hpp"
+
+void do_test_condition_notify_one_wakes_from_wait()
+{
+ wait_for_flag data;
+
+ boost::thread thread(bind(&wait_for_flag::wait_without_predicate, data));
+
+ {
+ boost::sync::unique_lock<boost::sync::mutex> lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_one();
+ }
+
+ thread.join();
+ BOOST_CHECK(data.woken);
+}
+
+BOOST_AUTO_TEST_CASE(test_condition_notify_one_wakes_from_wait)
+{
+ timed_test(&do_test_condition_notify_one_wakes_from_wait, timeout_seconds, execution_monitor::use_mutex);
+}
+
+void do_test_condition_notify_one_wakes_from_wait_with_predicate()
+{
+ wait_for_flag data;
+
+ boost::thread thread(bind(&wait_for_flag::wait_with_predicate, data));
+
+ {
+ boost::sync::unique_lock<boost::sync::mutex> lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_one();
+ }
+
+ thread.join();
+ BOOST_CHECK(data.woken);
+}
+
+BOOST_AUTO_TEST_CASE(test_condition_notify_one_wakes_from_wait_with_predicate)
+{
+ timed_test(&do_test_condition_notify_one_wakes_from_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex);
+}
+
+void do_test_condition_notify_one_wakes_from_timed_wait()
+{
+ wait_for_flag data;
+
+ boost::thread thread(bind(&wait_for_flag::timed_wait_without_predicate, data));
+
+ {
+ boost::sync::unique_lock<boost::sync::mutex> lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_one();
+ }
+
+ thread.join();
+ BOOST_CHECK(data.woken);
+}
+
+BOOST_AUTO_TEST_CASE(test_condition_notify_one_wakes_from_timed_wait)
+{
+ timed_test(&do_test_condition_notify_one_wakes_from_timed_wait, timeout_seconds, execution_monitor::use_mutex);
+}
+
+void do_test_condition_notify_one_wakes_from_timed_wait_with_predicate()
+{
+ wait_for_flag data;
+
+ boost::thread thread(bind(&wait_for_flag::timed_wait_with_predicate, data));
+
+ {
+ boost::sync::unique_lock<boost::sync::mutex> lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_one();
+ }
+
+ thread.join();
+ BOOST_CHECK(data.woken);
+}
+
+BOOST_AUTO_TEST_CASE(test_condition_notify_one_wakes_from_timed_wait_with_predicate)
+{
+ timed_test(&do_test_condition_notify_one_wakes_from_timed_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex);
+}
+
+void do_test_condition_notify_one_wakes_from_relative_timed_wait_with_predicate()
+{
+ wait_for_flag data;
+
+ boost::thread thread(bind(&wait_for_flag::relative_timed_wait_with_predicate, data));
+
+ {
+ boost::sync::unique_lock<boost::sync::mutex> lock(data.mutex);
+ data.flag=true;
+ data.cond_var.notify_one();
+ }
+
+ thread.join();
+ BOOST_CHECK(data.woken);
+}
+
+BOOST_AUTO_TEST_CASE(test_condition_notify_one_wakes_from_relative_timed_wait_with_predicate)
+{
+ timed_test(&do_test_condition_notify_one_wakes_from_relative_timed_wait_with_predicate, timeout_seconds, execution_monitor::use_mutex);
+}
+
+namespace {
+
+boost::sync::mutex multiple_wake_mutex;
+boost::sync::condition_variable multiple_wake_cond;
+unsigned multiple_wake_count=0;
+
+void wait_for_condvar_and_increase_count()
+{
+ boost::sync::unique_lock<boost::sync::mutex> lk(multiple_wake_mutex);
+ multiple_wake_cond.wait(lk);
+ ++multiple_wake_count;
+}
+
+} // namespace
+
+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::sync::unique_lock<boost::sync::mutex> lk(multiple_wake_mutex);
+ BOOST_CHECK(multiple_wake_count==3);
+ }
+
+ thread1.join();
+ thread2.join();
+ thread3.join();
+}
+
+BOOST_AUTO_TEST_CASE(test_multiple_notify_one_calls_wakes_multiple_threads)
+{
+ timed_test(&do_test_multiple_notify_one_calls_wakes_multiple_threads, timeout_seconds, execution_monitor::use_mutex);
+}

Added: trunk/libs/sync/test/run/condition_variable_timed_wait_times_out.cpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/sync/test/run/condition_variable_timed_wait_times_out.cpp 2013-10-27 12:11:25 EDT (Sun, 27 Oct 2013) (r86480)
@@ -0,0 +1,193 @@
+// Copyright (C) 2007-8 Anthony Williams
+// 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)
+
+#include <boost/thread/thread.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <boost/date_time/posix_time/posix_time_types.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/condition_variable_any.hpp>
+#include <boost/sync/support/boost_date_time.hpp>
+#include <boost/test/unit_test.hpp>
+#include "utils.hpp"
+
+bool fake_predicate()
+{
+ return false;
+}
+
+unsigned const timeout_seconds=2;
+unsigned const timeout_grace=1;
+boost::posix_time::milliseconds const timeout_resolution(100);
+
+void do_test_timed_wait_times_out()
+{
+ boost::sync::condition_variable cond;
+ boost::sync::mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ boost::sync::unique_lock<boost::sync::mutex> lock(m);
+ boost::system_time const start = boost::get_system_time();
+ boost::system_time const timeout = start+delay;
+
+ while(cond.timed_wait(lock,timeout)) {}
+
+ boost::system_time const end = boost::get_system_time();
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+BOOST_AUTO_TEST_CASE(test_timed_wait_times_out)
+{
+ timed_test(&do_test_timed_wait_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+}
+
+void do_test_timed_wait_with_predicate_times_out()
+{
+ boost::sync::condition_variable cond;
+ boost::sync::mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ boost::sync::unique_lock<boost::sync::mutex> lock(m);
+ boost::system_time const start = boost::get_system_time();
+ boost::system_time const timeout = start+delay;
+
+ bool const res=cond.timed_wait(lock,timeout,fake_predicate);
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK(!res);
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+BOOST_AUTO_TEST_CASE(test_timed_wait_with_predicate_times_out)
+{
+ timed_test(&do_test_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+}
+
+void do_test_relative_timed_wait_with_predicate_times_out()
+{
+ boost::sync::condition_variable cond;
+ boost::sync::mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ boost::sync::unique_lock<boost::sync::mutex> lock(m);
+ boost::system_time const start=boost::get_system_time();
+
+ bool const res=cond.timed_wait(lock,delay,fake_predicate);
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK(!res);
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+BOOST_AUTO_TEST_CASE(test_relative_timed_wait_with_predicate_times_out)
+{
+ timed_test(&do_test_relative_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+}
+
+void do_test_timed_wait_relative_times_out()
+{
+ boost::sync::condition_variable cond;
+ boost::sync::mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ boost::sync::unique_lock<boost::sync::mutex> lock(m);
+ boost::system_time const start=boost::get_system_time();
+
+ while(cond.timed_wait(lock,delay)) {}
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+BOOST_AUTO_TEST_CASE(test_timed_wait_relative_times_out)
+{
+ timed_test(&do_test_timed_wait_relative_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+}
+
+void do_test_cv_any_timed_wait_times_out()
+{
+ boost::sync::condition_variable_any cond;
+ boost::sync::mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ boost::sync::unique_lock<boost::sync::mutex> lock(m);
+ boost::system_time const start=boost::get_system_time();
+ boost::system_time const timeout=start+delay;
+
+ while(cond.timed_wait(lock,timeout)) {}
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+BOOST_AUTO_TEST_CASE(test_cv_any_timed_wait_times_out)
+{
+ timed_test(&do_test_cv_any_timed_wait_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+}
+
+void do_test_cv_any_timed_wait_with_predicate_times_out()
+{
+ boost::sync::condition_variable_any cond;
+ boost::sync::mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ boost::sync::unique_lock<boost::sync::mutex> lock(m);
+ boost::system_time const start=boost::get_system_time();
+ boost::system_time const timeout=start+delay;
+
+ bool const res=cond.timed_wait(lock,timeout,fake_predicate);
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK(!res);
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+BOOST_AUTO_TEST_CASE(test_cv_any_timed_wait_with_predicate_times_out)
+{
+ timed_test(&do_test_cv_any_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+}
+
+void do_test_cv_any_relative_timed_wait_with_predicate_times_out()
+{
+ boost::sync::condition_variable_any cond;
+ boost::sync::mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ boost::sync::unique_lock<boost::sync::mutex> lock(m);
+ boost::system_time const start=boost::get_system_time();
+
+ bool const res=cond.timed_wait(lock,delay,fake_predicate);
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK(!res);
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+BOOST_AUTO_TEST_CASE(test_cv_any_relative_timed_wait_with_predicate_times_out)
+{
+ timed_test(&do_test_cv_any_relative_timed_wait_with_predicate_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+}
+
+void do_test_cv_any_timed_wait_relative_times_out()
+{
+ boost::sync::condition_variable_any cond;
+ boost::sync::mutex m;
+
+ boost::posix_time::seconds const delay(timeout_seconds);
+ boost::sync::unique_lock<boost::sync::mutex> lock(m);
+ boost::system_time const start=boost::get_system_time();
+
+ while(cond.timed_wait(lock,delay)) {}
+
+ boost::system_time const end=boost::get_system_time();
+ BOOST_CHECK((delay-timeout_resolution)<=(end-start));
+}
+
+BOOST_AUTO_TEST_CASE(test_cv_any_timed_wait_relative_times_out)
+{
+ timed_test(&do_test_cv_any_timed_wait_relative_times_out, timeout_seconds+timeout_grace, execution_monitor::use_mutex);
+}

Added: trunk/libs/sync/test/run/thread_specific_ptr.cpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/sync/test/run/thread_specific_ptr.cpp 2013-10-27 12:11:25 EDT (Sun, 27 Oct 2013) (r86480)
@@ -0,0 +1,383 @@
+// Copyright (C) 2001-2003
+// William E. Kempf
+// Copyright (C) 2007 Anthony Williams
+// 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)
+
+#include <cstddef>
+#include <new>
+#include <iostream>
+#include <boost/aligned_storage.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/thread/thread.hpp>
+#include <boost/sync/detail/config.hpp>
+#include <boost/sync/thread_specific/thread_specific_ptr.hpp>
+#include <boost/sync/mutexes/mutex.hpp>
+#include <boost/sync/locks/lock_guard.hpp>
+#include "utils.hpp"
+
+#if defined(BOOST_SYNC_DETAIL_PLATFORM_WINAPI)
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#else
+#include <pthread.h>
+#endif
+
+boost::sync::mutex check_mutex;
+boost::sync::mutex tss_mutex;
+int tss_instances = 0;
+int tss_total = 0;
+
+struct tss_value_t
+{
+ tss_value_t()
+ {
+ boost::sync::lock_guard<boost::sync::mutex> lock(tss_mutex);
+ ++tss_instances;
+ ++tss_total;
+ value = 0;
+ }
+
+ ~tss_value_t()
+ {
+ boost::sync::lock_guard<boost::sync::mutex> lock(tss_mutex);
+ --tss_instances;
+ }
+
+ int value;
+};
+
+boost::sync::thread_specific_ptr<tss_value_t> tss_value;
+
+void test_tss_thread()
+{
+ tss_value.reset(new tss_value_t());
+ for (int i=0; i<1000; ++i)
+ {
+ int& n = tss_value->value;
+ if (n != i)
+ {
+ // Don't call BOOST_CHECK_EQUAL directly, as it's not thread-safe.
+ boost::sync::lock_guard<boost::sync::mutex> lock(check_mutex);
+ BOOST_CHECK_EQUAL(n, i);
+ }
+ ++n;
+ }
+}
+
+#if defined(BOOST_SYNC_DETAIL_PLATFORM_WINAPI)
+
+typedef HANDLE native_thread_t;
+
+DWORD WINAPI test_tss_thread_native(LPVOID /*lpParameter*/)
+{
+ test_tss_thread();
+ return 0;
+}
+
+native_thread_t create_native_thread(void)
+{
+ native_thread_t const res=CreateThread
+ (
+ 0, //security attributes (0 = not inheritable)
+ 0, //stack size (0 = default)
+ &test_tss_thread_native, //function to execute
+ 0, //parameter to pass to function
+ 0, //creation flags (0 = run immediately)
+ 0 //thread id (0 = thread id not returned)
+ );
+ BOOST_CHECK(res!=0);
+ return res;
+}
+
+void join_native_thread(native_thread_t thread)
+{
+ DWORD res = WaitForSingleObject(thread, INFINITE);
+ BOOST_CHECK(res == WAIT_OBJECT_0);
+
+ res = CloseHandle(thread);
+ BOOST_CHECK(SUCCEEDED(res));
+}
+
+#else // defined(BOOST_SYNC_DETAIL_PLATFORM_WINAPI)
+
+typedef pthread_t native_thread_t;
+
+extern "C"
+{
+ void* test_tss_thread_native(void*)
+ {
+ test_tss_thread();
+ return 0;
+ }
+}
+
+native_thread_t create_native_thread()
+{
+ native_thread_t thread_handle;
+
+ int const res = pthread_create(&thread_handle, 0, &test_tss_thread_native, 0);
+ BOOST_CHECK(!res);
+ return thread_handle;
+}
+
+void join_native_thread(native_thread_t thread)
+{
+ void* result=0;
+ int const res = pthread_join(thread, &result);
+ BOOST_CHECK(!res);
+}
+
+#endif // defined(BOOST_SYNC_DETAIL_PLATFORM_WINAPI)
+
+void do_test_tss()
+{
+ tss_instances = 0;
+ tss_total = 0;
+
+ const int NUMTHREADS = 5;
+ boost::thread_group threads;
+ try
+ {
+ for (int i = 0; i < NUMTHREADS; ++i)
+ threads.create_thread(&test_tss_thread);
+ threads.join_all();
+ }
+ catch(...)
+ {
+ threads.interrupt_all();
+ threads.join_all();
+ throw;
+ }
+
+
+ std::cout
+ << "tss_instances = " << tss_instances
+ << "; tss_total = " << tss_total
+ << "\n";
+ std::cout.flush();
+
+ BOOST_CHECK_EQUAL(tss_instances, 0);
+ BOOST_CHECK_EQUAL(tss_total, 5);
+
+ tss_instances = 0;
+ tss_total = 0;
+
+ native_thread_t thread1 = create_native_thread();
+ native_thread_t thread2 = create_native_thread();
+ native_thread_t thread3 = create_native_thread();
+ native_thread_t thread4 = create_native_thread();
+ native_thread_t thread5 = create_native_thread();
+
+ join_native_thread(thread5);
+ join_native_thread(thread4);
+ join_native_thread(thread3);
+ join_native_thread(thread2);
+ join_native_thread(thread1);
+
+ std::cout
+ << "tss_instances = " << tss_instances
+ << "; tss_total = " << tss_total
+ << "\n";
+ std::cout.flush();
+
+ // The following is not really an error. TSS cleanup support still is available for boost threads.
+ // Also this usually will be triggered only when bound to the static version of thread lib.
+ // 2006-10-02 Roland Schwarz
+ //BOOST_CHECK_EQUAL(tss_instances, 0);
+ BOOST_CHECK_MESSAGE(tss_instances == 0, "Support of automatic tss cleanup for native threading API not available");
+ BOOST_CHECK_EQUAL(tss_total, 5);
+}
+
+BOOST_AUTO_TEST_CASE(test_tss)
+{
+ timed_test(&do_test_tss, 2);
+}
+
+bool tss_cleanup_called = false;
+
+struct Dummy
+{
+};
+
+void tss_custom_cleanup(Dummy* d)
+{
+ delete d;
+ tss_cleanup_called=true;
+}
+
+boost::sync::thread_specific_ptr<Dummy> tss_with_cleanup(tss_custom_cleanup);
+
+void tss_thread_with_custom_cleanup()
+{
+ tss_with_cleanup.reset(new Dummy);
+}
+
+void do_test_tss_with_custom_cleanup()
+{
+ boost::thread t(tss_thread_with_custom_cleanup);
+ try
+ {
+ t.join();
+ }
+ catch(...)
+ {
+ t.interrupt();
+ t.join();
+ throw;
+ }
+
+ BOOST_CHECK(tss_cleanup_called);
+}
+
+
+BOOST_AUTO_TEST_CASE(test_tss_with_custom_cleanup)
+{
+ timed_test(&do_test_tss_with_custom_cleanup, 2);
+}
+
+Dummy* tss_object = new Dummy;
+
+void tss_thread_with_custom_cleanup_and_release()
+{
+ tss_with_cleanup.reset(tss_object);
+ tss_with_cleanup.release();
+}
+
+void do_test_tss_does_no_cleanup_after_release()
+{
+ tss_cleanup_called = false;
+ boost::thread t(tss_thread_with_custom_cleanup_and_release);
+ try
+ {
+ t.join();
+ }
+ catch(...)
+ {
+ t.interrupt();
+ t.join();
+ throw;
+ }
+
+ BOOST_CHECK(!tss_cleanup_called);
+ if(!tss_cleanup_called)
+ {
+ delete tss_object;
+ }
+}
+
+struct dummy_class_tracks_deletions
+{
+ static unsigned deletions;
+
+ ~dummy_class_tracks_deletions()
+ {
+ ++deletions;
+ }
+};
+
+unsigned dummy_class_tracks_deletions::deletions = 0;
+
+boost::sync::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;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_tss_does_no_cleanup_after_release)
+{
+ timed_test(&do_test_tss_does_no_cleanup_after_release, 2);
+}
+
+BOOST_AUTO_TEST_CASE(test_tss_does_no_cleanup_with_null_cleanup_function)
+{
+ timed_test(&do_test_tss_does_no_cleanup_with_null_cleanup_function, 2);
+}
+
+void thread_with_local_tss_ptr()
+{
+ {
+ boost::sync::thread_specific_ptr<Dummy> local_tss(tss_custom_cleanup);
+
+ local_tss.reset(new Dummy);
+ }
+ BOOST_CHECK(tss_cleanup_called);
+ tss_cleanup_called = false;
+}
+
+
+BOOST_AUTO_TEST_CASE(test_tss_does_not_call_cleanup_after_ptr_destroyed)
+{
+ boost::thread t(thread_with_local_tss_ptr);
+ t.join();
+ BOOST_CHECK(!tss_cleanup_called);
+}
+
+BOOST_AUTO_TEST_CASE(test_tss_cleanup_not_called_for_null_pointer)
+{
+ boost::sync::thread_specific_ptr<Dummy> local_tss(tss_custom_cleanup);
+ local_tss.reset(new Dummy);
+ tss_cleanup_called = false;
+ local_tss.reset(0);
+ BOOST_CHECK(tss_cleanup_called);
+ tss_cleanup_called = false;
+ local_tss.reset(new Dummy);
+ BOOST_CHECK(!tss_cleanup_called);
+}
+
+BOOST_AUTO_TEST_CASE(test_tss_at_the_same_adress)
+{
+ typedef boost::sync::thread_specific_ptr<Dummy> ptr_t;
+ enum { size = sizeof(ptr_t) };
+ boost::aligned_storage< size > storage;
+ ptr_t* ptr = static_cast< ptr_t* >(storage.address());
+
+ // Create the first pointer
+ tss_cleanup_called = false;
+
+ new (ptr) ptr_t(tss_custom_cleanup);
+ BOOST_CHECK(!tss_cleanup_called);
+ BOOST_CHECK(ptr->get() == NULL);
+
+ ptr->reset(new Dummy);
+ BOOST_CHECK(!tss_cleanup_called);
+ BOOST_CHECK(ptr->get() != NULL);
+
+ ptr->~ptr_t();
+ BOOST_CHECK(tss_cleanup_called);
+
+ // Create the second pointer at the same address
+ tss_cleanup_called = false;
+
+ new (ptr) ptr_t(tss_custom_cleanup);
+ BOOST_CHECK(!tss_cleanup_called);
+ BOOST_CHECK(ptr->get() == NULL);
+
+ ptr->~ptr_t();
+ BOOST_CHECK(!tss_cleanup_called);
+}


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