$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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);
+}