$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: anthony_at_[hidden]
Date: 2007-12-19 05:39:46
Author: anthonyw
Date: 2007-12-19 05:39:45 EST (Wed, 19 Dec 2007)
New Revision: 42166
URL: http://svn.boost.org/trac/boost/changeset/42166
Log:
Updated thread ID, and added tests
Added:
   trunk/libs/thread/test/test_thread_id.cpp   (contents, props changed)
Text files modified: 
   trunk/boost/thread/pthread/thread.hpp      |    59 +++++++++++++++++++++++++-------------- 
   trunk/boost/thread/pthread/thread_data.hpp |     9 ++++-                                   
   trunk/boost/thread/win32/thread.hpp        |     9 +++++                                   
   trunk/libs/thread/src/pthread/thread.cpp   |    22 +++++++++-----                          
   trunk/libs/thread/test/Jamfile.v2          |     1                                         
   5 files changed, 67 insertions(+), 33 deletions(-)
Modified: trunk/boost/thread/pthread/thread.hpp
==============================================================================
--- trunk/boost/thread/pthread/thread.hpp	(original)
+++ trunk/boost/thread/pthread/thread.hpp	2007-12-19 05:39:45 EST (Wed, 19 Dec 2007)
@@ -40,44 +40,62 @@
     {
         class thread_id
         {
-            boost::optional<pthread_t> id;
-
+        private:
+            detail::thread_data_ptr thread_data;
+            
+            thread_id(detail::thread_data_ptr thread_data_):
+                thread_data(thread_data_)
+            {}
             friend class boost::thread;
-
             friend thread_id this_thread::get_id();
-
-            thread_id(pthread_t id_):
-                id(id_)
-            {}
-        
         public:
-            thread_id()
+            thread_id():
+                thread_data()
             {}
-
+            
             bool operator==(const thread_id& y) const
             {
-                return (id && y.id) && (pthread_equal(*id,*y.id)!=0);
+                return thread_data==y.thread_data;
             }
         
             bool operator!=(const thread_id& y) const
             {
-                return !(*this==y);
+                return thread_data!=y.thread_data;
+            }
+        
+            bool operator<(const thread_id& y) const
+            {
+                return thread_data<y.thread_data;
+            }
+        
+            bool operator>(const thread_id& y) const
+            {
+                return y.thread_data<thread_data;
+            }
+        
+            bool operator<=(const thread_id& y) const
+            {
+                return !(y.thread_data<thread_data);
+            }
+        
+            bool operator>=(const thread_id& y) const
+            {
+                return !(thread_data<y.thread_data);
             }
 
             template<class charT, class traits>
             friend std::basic_ostream<charT, traits>& 
             operator<<(std::basic_ostream<charT, traits>& os, const thread_id& x)
             {
-                if(x.id)
+                if(x.thread_data)
                 {
-                    return os<<*x.id;
+                    return os<<x.thread_data;
                 }
                 else
                 {
                     return os<<"{Not-any-thread}";
                 }
             }
-        
         };
     }
 
@@ -108,13 +126,13 @@
         };
         
         mutable boost::mutex thread_info_mutex;
-        boost::shared_ptr<detail::thread_data_base> thread_info;
+        detail::thread_data_ptr thread_info;
 
         void start_thread();
         
-        explicit thread(boost::shared_ptr<detail::thread_data_base> data);
+        explicit thread(detail::thread_data_ptr data);
 
-        boost::shared_ptr<detail::thread_data_base> get_thread_info() const;
+        detail::thread_data_ptr get_thread_info() const;
         
     public:
         thread();
@@ -219,10 +237,7 @@
             ~restore_interruption();
         };
 
-        inline thread::id get_id()
-        {
-            return thread::id(pthread_self());
-        }
+        BOOST_THREAD_DECL thread::id get_id();
 
         BOOST_THREAD_DECL void interruption_point();
         BOOST_THREAD_DECL bool interruption_enabled();
Modified: trunk/boost/thread/pthread/thread_data.hpp
==============================================================================
--- trunk/boost/thread/pthread/thread_data.hpp	(original)
+++ trunk/boost/thread/pthread/thread_data.hpp	2007-12-19 05:39:45 EST (Wed, 19 Dec 2007)
@@ -7,6 +7,7 @@
 
 #include <boost/thread/detail/config.hpp>
 #include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
 #include <boost/thread/mutex.hpp>
 #include <boost/optional.hpp>
 #include <pthread.h>
@@ -21,10 +22,14 @@
     {
         struct thread_exit_callback_node;
         struct tss_data_node;
+
+        struct thread_data_base;
+        typedef boost::shared_ptr<thread_data_base> thread_data_ptr;
         
-        struct thread_data_base
+        struct thread_data_base:
+            enable_shared_from_this<thread_data_base>
         {
-            boost::shared_ptr<thread_data_base> self;
+            thread_data_ptr self;
             pthread_t thread_handle;
             boost::mutex data_mutex;
             boost::condition_variable done_condition;
Modified: trunk/boost/thread/win32/thread.hpp
==============================================================================
--- trunk/boost/thread/win32/thread.hpp	(original)
+++ trunk/boost/thread/win32/thread.hpp	2007-12-19 05:39:45 EST (Wed, 19 Dec 2007)
@@ -364,7 +364,14 @@
         friend std::basic_ostream<charT, traits>& 
         operator<<(std::basic_ostream<charT, traits>& os, const id& x)
         {
-            return os<<x.thread_data;
+            if(x.thread_data)
+            {
+                return os<<x.thread_data;
+            }
+            else
+            {
+                return os<<"{Not-any-thread}";
+            }
         }
 
         void interrupt()
Modified: trunk/libs/thread/src/pthread/thread.cpp
==============================================================================
--- trunk/libs/thread/src/pthread/thread.cpp	(original)
+++ trunk/libs/thread/src/pthread/thread.cpp	2007-12-19 05:39:45 EST (Wed, 19 Dec 2007)
@@ -229,7 +229,7 @@
         return !operator==(other);
     }
 
-    boost::shared_ptr<detail::thread_data_base> thread::get_thread_info() const
+    detail::thread_data_ptr thread::get_thread_info() const
     {
         lock_guard<mutex> l(thread_info_mutex);
         return thread_info;
@@ -237,7 +237,7 @@
 
     void thread::join()
     {
-        boost::shared_ptr<detail::thread_data_base> const local_thread_info=get_thread_info();
+        detail::thread_data_ptr const local_thread_info=get_thread_info();
         if(local_thread_info)
         {
             bool do_join=false;
@@ -281,7 +281,7 @@
 
     bool thread::timed_join(system_time const& wait_until)
     {
-        boost::shared_ptr<detail::thread_data_base> const local_thread_info=get_thread_info();
+        detail::thread_data_ptr const local_thread_info=get_thread_info();
         if(local_thread_info)
         {
             bool do_join=false;
@@ -335,7 +335,7 @@
 
     void thread::detach()
     {
-        boost::shared_ptr<detail::thread_data_base> local_thread_info;
+        detail::thread_data_ptr local_thread_info;
         {
             lock_guard<mutex> l1(thread_info_mutex);
             thread_info.swap(local_thread_info);
@@ -413,10 +413,10 @@
 
     thread::id thread::get_id() const
     {
-        boost::shared_ptr<detail::thread_data_base> local_thread_info=get_thread_info();
+        detail::thread_data_ptr const local_thread_info=get_thread_info();
         if(local_thread_info)
         {
-            return id(local_thread_info->thread_handle);
+            return id(local_thread_info);
         }
         else
         {
@@ -426,7 +426,7 @@
 
     void thread::interrupt()
     {
-        boost::shared_ptr<detail::thread_data_base> local_thread_info=get_thread_info();
+        detail::thread_data_ptr const local_thread_info=get_thread_info();
         if(local_thread_info)
         {
             lock_guard<mutex> lk(local_thread_info->data_mutex);
@@ -440,7 +440,7 @@
 
     bool thread::interruption_requested() const
     {
-        boost::shared_ptr<detail::thread_data_base> local_thread_info=get_thread_info();
+        detail::thread_data_ptr const local_thread_info=get_thread_info();
         if(local_thread_info)
         {
             lock_guard<mutex> lk(local_thread_info->data_mutex);
@@ -455,6 +455,12 @@
 
     namespace this_thread
     {
+        thread::id get_id()
+        {
+            boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data();
+            return thread::id(thread_info?thread_info->shared_from_this():detail::thread_data_ptr());
+        }
+
         void interruption_point()
         {
             boost::detail::thread_data_base* const thread_info=detail::get_current_thread_data();
Modified: trunk/libs/thread/test/Jamfile.v2
==============================================================================
--- trunk/libs/thread/test/Jamfile.v2	(original)
+++ trunk/libs/thread/test/Jamfile.v2	2007-12-19 05:39:45 EST (Wed, 19 Dec 2007)
@@ -35,6 +35,7 @@
 {
     test-suite "threads"
         : [ thread-run test_thread.cpp ]
+          [ thread-run test_thread_id.cpp ]
           [ thread-run test_thread_move.cpp ]
           [ thread-run test_move_function.cpp ]
           [ thread-run test_mutex.cpp ]
Added: trunk/libs/thread/test/test_thread_id.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/thread/test/test_thread_id.cpp	2007-12-19 05:39:45 EST (Wed, 19 Dec 2007)
@@ -0,0 +1,147 @@
+// Copyright (C) 2007 Anthony Williams
+//
+//  Distributed under the Boost Software License, Version 1.0. (See accompanying 
+//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#include <boost/thread/thread.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/bind.hpp>
+
+void do_nothing()
+{}
+
+void test_thread_id_for_default_constructed_thread_is_default_constructed_id()
+{
+    boost::thread t;
+    BOOST_CHECK(t.get_id()==boost::thread::id());
+}
+
+void test_thread_id_for_running_thread_is_not_default_constructed_id()
+{
+    boost::thread t(do_nothing);
+    BOOST_CHECK(t.get_id()!=boost::thread::id());
+    t.join();
+}
+
+void test_different_threads_have_different_ids()
+{
+    boost::thread t(do_nothing);
+    boost::thread t2(do_nothing);
+    BOOST_CHECK(t.get_id()!=t2.get_id());
+    t.join();
+    t2.join();
+}
+
+void test_thread_ids_have_a_total_order()
+{
+    boost::thread t(do_nothing);
+    boost::thread t2(do_nothing);
+    boost::thread t3(do_nothing);
+    BOOST_CHECK(t.get_id()!=t2.get_id());
+    BOOST_CHECK(t.get_id()!=t3.get_id());
+    BOOST_CHECK(t2.get_id()!=t3.get_id());
+
+    BOOST_CHECK((t.get_id()<t2.get_id()) != (t2.get_id()<t.get_id()));
+    BOOST_CHECK((t.get_id()<t3.get_id()) != (t3.get_id()<t.get_id()));
+    BOOST_CHECK((t2.get_id()<t3.get_id()) != (t3.get_id()<t2.get_id()));
+
+    BOOST_CHECK((t.get_id()>t2.get_id()) != (t2.get_id()>t.get_id()));
+    BOOST_CHECK((t.get_id()>t3.get_id()) != (t3.get_id()>t.get_id()));
+    BOOST_CHECK((t2.get_id()>t3.get_id()) != (t3.get_id()>t2.get_id()));
+
+    BOOST_CHECK((t.get_id()<t2.get_id()) == (t2.get_id()>t.get_id()));
+    BOOST_CHECK((t2.get_id()<t.get_id()) == (t.get_id()>t2.get_id()));
+    BOOST_CHECK((t.get_id()<t3.get_id()) == (t3.get_id()>t.get_id()));
+    BOOST_CHECK((t3.get_id()<t.get_id()) == (t.get_id()>t3.get_id()));
+    BOOST_CHECK((t2.get_id()<t3.get_id()) == (t3.get_id()>t2.get_id()));
+    BOOST_CHECK((t3.get_id()<t2.get_id()) == (t2.get_id()>t3.get_id()));
+
+    BOOST_CHECK((t.get_id()<t2.get_id()) == (t2.get_id()>=t.get_id()));
+    BOOST_CHECK((t2.get_id()<t.get_id()) == (t.get_id()>=t2.get_id()));
+    BOOST_CHECK((t.get_id()<t3.get_id()) == (t3.get_id()>=t.get_id()));
+    BOOST_CHECK((t3.get_id()<t.get_id()) == (t.get_id()>=t3.get_id()));
+    BOOST_CHECK((t2.get_id()<t3.get_id()) == (t3.get_id()>=t2.get_id()));
+    BOOST_CHECK((t3.get_id()<t2.get_id()) == (t2.get_id()>=t3.get_id()));
+    
+    BOOST_CHECK((t.get_id()<=t2.get_id()) == (t2.get_id()>t.get_id()));
+    BOOST_CHECK((t2.get_id()<=t.get_id()) == (t.get_id()>t2.get_id()));
+    BOOST_CHECK((t.get_id()<=t3.get_id()) == (t3.get_id()>t.get_id()));
+    BOOST_CHECK((t3.get_id()<=t.get_id()) == (t.get_id()>t3.get_id()));
+    BOOST_CHECK((t2.get_id()<=t3.get_id()) == (t3.get_id()>t2.get_id()));
+    BOOST_CHECK((t3.get_id()<=t2.get_id()) == (t2.get_id()>t3.get_id()));
+
+    if((t.get_id()<t2.get_id()) && (t2.get_id()<t3.get_id()))
+    {
+        BOOST_CHECK(t.get_id()<t3.get_id());
+    }
+    else if((t.get_id()<t3.get_id()) && (t3.get_id()<t2.get_id()))
+    {
+        BOOST_CHECK(t.get_id()<t2.get_id());
+    }
+    else if((t2.get_id()<t3.get_id()) && (t3.get_id()<t.get_id()))
+    {
+        BOOST_CHECK(t2.get_id()<t.get_id());
+    }
+    else if((t2.get_id()<t.get_id()) && (t.get_id()<t3.get_id()))
+    {
+        BOOST_CHECK(t2.get_id()<t3.get_id());
+    }
+    else if((t3.get_id()<t.get_id()) && (t.get_id()<t2.get_id()))
+    {
+        BOOST_CHECK(t3.get_id()<t2.get_id());
+    }
+    else if((t3.get_id()<t2.get_id()) && (t2.get_id()<t.get_id()))
+    {
+        BOOST_CHECK(t3.get_id()<t.get_id());
+    }
+    else
+    {
+        BOOST_CHECK(false);
+    }
+
+    BOOST_CHECK(boost::thread::id() < t.get_id());
+    BOOST_CHECK(boost::thread::id() < t2.get_id());
+    BOOST_CHECK(boost::thread::id() < t3.get_id());
+
+    BOOST_CHECK(boost::thread::id() <= t.get_id());
+    BOOST_CHECK(boost::thread::id() <= t2.get_id());
+    BOOST_CHECK(boost::thread::id() <= t3.get_id());
+
+    BOOST_CHECK(!(boost::thread::id() > t.get_id()));
+    BOOST_CHECK(!(boost::thread::id() > t2.get_id()));
+    BOOST_CHECK(!(boost::thread::id() > t2.get_id()));
+    
+    BOOST_CHECK(!(boost::thread::id() >= t.get_id()));
+    BOOST_CHECK(!(boost::thread::id() >= t2.get_id()));
+    BOOST_CHECK(!(boost::thread::id() >= t2.get_id()));
+
+    t.join();
+    t2.join();
+    t3.join();
+}
+    
+void get_thread_id(boost::thread::id* id)
+{
+    *id=boost::this_thread::get_id();
+}
+
+void test_thread_id_of_running_thread_returned_by_this_thread_get_id()
+{
+    boost::thread::id id;
+    boost::thread t(boost::bind(get_thread_id,&id));
+    boost::thread::id t_id=t.get_id();
+    t.join();
+    BOOST_CHECK(id==t_id);
+}
+
+boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
+{
+    boost::unit_test_framework::test_suite* test =
+        BOOST_TEST_SUITE("Boost.Threads: thread move test suite");
+
+    test->add(BOOST_TEST_CASE(test_thread_id_for_default_constructed_thread_is_default_constructed_id));
+    test->add(BOOST_TEST_CASE(test_thread_id_for_running_thread_is_not_default_constructed_id));
+    test->add(BOOST_TEST_CASE(test_different_threads_have_different_ids));
+    test->add(BOOST_TEST_CASE(test_thread_ids_have_a_total_order));
+    test->add(BOOST_TEST_CASE(test_thread_id_of_running_thread_returned_by_this_thread_get_id));
+    return test;
+}