Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r60991 - in branches/release: boost boost/thread boost/thread/detail boost/thread/pthread boost/thread/win32 libs/thread libs/thread/doc libs/thread/src/pthread libs/thread/src/win32 libs/thread/test
From: anthony_at_[hidden]
Date: 2010-04-01 11:04:17


Author: anthonyw
Date: 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
New Revision: 60991
URL: http://svn.boost.org/trac/boost/changeset/60991

Log:
Merged changes to boost.thread over from trunk
Added:
   branches/release/libs/thread/test/test_thread_exit.cpp
      - copied unchanged from r60990, /trunk/libs/thread/test/test_thread_exit.cpp
Properties modified:
   branches/release/boost/thread/ (props changed)
   branches/release/boost/thread.hpp (props changed)
   branches/release/libs/thread/ (props changed)
   branches/release/libs/thread/doc/ (props changed)
Text files modified:
   branches/release/boost/thread/barrier.hpp | 3
   branches/release/boost/thread/detail/thread.hpp | 36 +++++--
   branches/release/boost/thread/future.hpp | 56 ++++++-----
   branches/release/boost/thread/locks.hpp | 69 +++++++------
   branches/release/boost/thread/pthread/condition_variable.hpp | 8
   branches/release/boost/thread/pthread/condition_variable_fwd.hpp | 3
   branches/release/boost/thread/pthread/mutex.hpp | 7
   branches/release/boost/thread/pthread/once.hpp | 5 +
   branches/release/boost/thread/pthread/recursive_mutex.hpp | 17 +-
   branches/release/boost/thread/pthread/thread_heap_alloc.hpp | 2
   branches/release/boost/thread/win32/basic_timed_mutex.hpp | 67 ++++++++++---
   branches/release/boost/thread/win32/once.hpp | 190 ++++++++++++++++++++++++---------------
   branches/release/boost/thread/win32/thread_heap_alloc.hpp | 5
   branches/release/boost/thread/win32/thread_primitives.hpp | 7
   branches/release/libs/thread/doc/once.qbk | 9 +
   branches/release/libs/thread/src/pthread/thread.cpp | 3
   branches/release/libs/thread/src/pthread/timeconv.inl | 11 +
   branches/release/libs/thread/src/win32/thread.cpp | 3
   branches/release/libs/thread/test/Jamfile.v2 | 1
   branches/release/libs/thread/test/test_futures.cpp | 8
   20 files changed, 318 insertions(+), 192 deletions(-)

Modified: branches/release/boost/thread/barrier.hpp
==============================================================================
--- branches/release/boost/thread/barrier.hpp (original)
+++ branches/release/boost/thread/barrier.hpp 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -9,6 +9,7 @@
 #define BOOST_BARRIER_JDM030602_HPP
 
 #include <boost/thread/detail/config.hpp>
+#include <boost/throw_exception.hpp>
 
 #include <boost/thread/mutex.hpp>
 #include <boost/thread/condition_variable.hpp>
@@ -27,7 +28,7 @@
             : m_threshold(count), m_count(count), m_generation(0)
         {
             if (count == 0)
- throw std::invalid_argument("count cannot be zero.");
+ boost::throw_exception(std::invalid_argument("count cannot be zero."));
         }
     
         bool wait()

Modified: branches/release/boost/thread/detail/thread.hpp
==============================================================================
--- branches/release/boost/thread/detail/thread.hpp (original)
+++ branches/release/boost/thread/detail/thread.hpp 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -39,10 +39,13 @@
             public detail::thread_data_base
         {
         public:
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
             thread_data(F&& f_):
                 f(static_cast<F&&>(f_))
             {}
+ thread_data(F& f_):
+ f(f_)
+ {}
 #else
             thread_data(F f_):
                 f(f_)
@@ -119,7 +122,7 @@
 
         detail::thread_data_ptr get_thread_info() const;
 
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
         template<typename F>
         static inline detail::thread_data_ptr make_thread_info(F&& f)
         {
@@ -127,7 +130,7 @@
         }
         static inline detail::thread_data_ptr make_thread_info(void (*f)())
         {
- return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(f));
+ return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(static_cast<void(*&&)()>(f)));
         }
 #else
         template<typename F>
@@ -141,8 +144,8 @@
             return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
         }
 
- struct dummy;
 #endif
+ struct dummy;
     public:
 #ifdef __SUNPRO_CC
         thread(const volatile thread&);
@@ -150,13 +153,22 @@
         thread();
         ~thread();
 
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifdef BOOST_MSVC
+ template <class F>
+ explicit thread(F f,typename disable_if<boost::is_convertible<F&,detail::thread_move_t<F> >, dummy* >::type=0):
+ thread_info(make_thread_info(f))
+ {
+ start_thread();
+ }
+#else
         template <class F>
         thread(F&& f):
             thread_info(make_thread_info(static_cast<F&&>(f)))
         {
             start_thread();
         }
+#endif
 
         thread(thread&& other)
         {
@@ -343,10 +355,14 @@
         return lhs.swap(rhs);
     }
     
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
+ inline thread&& move(thread& t)
+ {
+ return static_cast<thread&&>(t);
+ }
     inline thread&& move(thread&& t)
     {
- return t;
+ return static_cast<thread&&>(t);
     }
 #else
     inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> t)
@@ -445,7 +461,7 @@
         {
             virtual ~thread_exit_function_base()
             {}
- virtual void operator()() const=0;
+ virtual void operator()()=0;
         };
         
         template<typename F>
@@ -458,13 +474,13 @@
                 f(f_)
             {}
             
- void operator()() const
+ void operator()()
             {
                 f();
             }
         };
         
- void add_thread_exit_function(thread_exit_function_base*);
+ void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
     }
     
     namespace this_thread

Modified: branches/release/boost/thread/future.hpp
==============================================================================
--- branches/release/boost/thread/future.hpp (original)
+++ branches/release/boost/thread/future.hpp 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -1,4 +1,4 @@
-// (C) Copyright 2008-9 Anthony Williams
+// (C) Copyright 2008-10 Anthony Williams
 //
 // Distributed under the Boost Software License, Version 1.0. (See
 // accompanying file LICENSE_1_0.txt or copy at
@@ -16,6 +16,7 @@
 #include <boost/type_traits/is_convertible.hpp>
 #include <boost/mpl/if.hpp>
 #include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
 #include <algorithm>
 #include <boost/function.hpp>
 #include <boost/bind.hpp>
@@ -218,7 +219,7 @@
         struct future_traits
         {
             typedef boost::scoped_ptr<T> storage_type;
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
             typedef T const& source_reference_type;
             struct dummy;
             typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,T&&>::type rvalue_source_type;
@@ -323,7 +324,7 @@
             move_dest_type get()
             {
                 wait();
- return *result;
+ return static_cast<move_dest_type>(*result);
             }
 
             future_state::state get_state()
@@ -403,13 +404,14 @@
             
             struct all_futures_lock
             {
- unsigned count;
+ typedef std::vector<registered_waiter>::size_type count_type;
+ count_type count;
                 boost::scoped_array<boost::unique_lock<boost::mutex> > locks;
                 
                 all_futures_lock(std::vector<registered_waiter>& futures):
                     count(futures.size()),locks(new boost::unique_lock<boost::mutex>[count])
                 {
- for(unsigned i=0;i<count;++i)
+ for(count_type i=0;i<count;++i)
                     {
                         locks[i]=boost::unique_lock<boost::mutex>(futures[i].future->mutex);
                     }
@@ -632,7 +634,7 @@
         ~unique_future()
         {}
 
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
         unique_future(unique_future && other)
         {
             future.swap(other.future);
@@ -673,7 +675,7 @@
         {
             if(!future)
             {
- throw future_uninitialized();
+ boost::throw_exception(future_uninitialized());
             }
 
             return future->get();
@@ -709,7 +711,7 @@
         {
             if(!future)
             {
- throw future_uninitialized();
+ boost::throw_exception(future_uninitialized());
             }
             future->wait(false);
         }
@@ -724,7 +726,7 @@
         {
             if(!future)
             {
- throw future_uninitialized();
+ boost::throw_exception(future_uninitialized());
             }
             return future->timed_wait_until(abs_time);
         }
@@ -767,7 +769,7 @@
             future=other.future;
             return *this;
         }
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
         shared_future(shared_future && other)
         {
             future.swap(other.future);
@@ -830,7 +832,7 @@
         {
             if(!future)
             {
- throw future_uninitialized();
+ boost::throw_exception(future_uninitialized());
             }
 
             return future->get();
@@ -866,7 +868,7 @@
         {
             if(!future)
             {
- throw future_uninitialized();
+ boost::throw_exception(future_uninitialized());
             }
             future->wait(false);
         }
@@ -881,7 +883,7 @@
         {
             if(!future)
             {
- throw future_uninitialized();
+ boost::throw_exception(future_uninitialized());
             }
             return future->timed_wait_until(abs_time);
         }
@@ -929,7 +931,7 @@
         }
 
         // Assignment
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
         promise(promise && rhs):
             future_obtained(rhs.future_obtained)
         {
@@ -974,7 +976,7 @@
             lazy_init();
             if(future_obtained)
             {
- throw future_already_retrieved();
+ boost::throw_exception(future_already_retrieved());
             }
             future_obtained=true;
             return unique_future<R>(future);
@@ -986,7 +988,7 @@
             boost::lock_guard<boost::mutex> lock(future->mutex);
             if(future->done)
             {
- throw promise_already_satisfied();
+ boost::throw_exception(promise_already_satisfied());
             }
             future->mark_finished_with_result_internal(r);
         }
@@ -998,7 +1000,7 @@
             boost::lock_guard<boost::mutex> lock(future->mutex);
             if(future->done)
             {
- throw promise_already_satisfied();
+ boost::throw_exception(promise_already_satisfied());
             }
             future->mark_finished_with_result_internal(static_cast<typename detail::future_traits<R>::rvalue_source_type>(r));
         }
@@ -1009,7 +1011,7 @@
             boost::lock_guard<boost::mutex> lock(future->mutex);
             if(future->done)
             {
- throw promise_already_satisfied();
+ boost::throw_exception(promise_already_satisfied());
             }
             future->mark_exceptional_finish_internal(p);
         }
@@ -1063,7 +1065,7 @@
         }
 
         // Assignment
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
         promise(promise && rhs):
             future_obtained(rhs.future_obtained)
         {
@@ -1109,7 +1111,7 @@
             
             if(future_obtained)
             {
- throw future_already_retrieved();
+ boost::throw_exception(future_already_retrieved());
             }
             future_obtained=true;
             return unique_future<void>(future);
@@ -1121,7 +1123,7 @@
             boost::lock_guard<boost::mutex> lock(future->mutex);
             if(future->done)
             {
- throw promise_already_satisfied();
+ boost::throw_exception(promise_already_satisfied());
             }
             future->mark_finished_with_result_internal();
         }
@@ -1132,7 +1134,7 @@
             boost::lock_guard<boost::mutex> lock(future->mutex);
             if(future->done)
             {
- throw promise_already_satisfied();
+ boost::throw_exception(promise_already_satisfied());
             }
             future->mark_exceptional_finish_internal(p);
         }
@@ -1164,7 +1166,7 @@
                     boost::lock_guard<boost::mutex> lk(this->mutex);
                     if(started)
                     {
- throw task_already_started();
+ boost::throw_exception(task_already_started());
                     }
                     started=true;
                 }
@@ -1283,7 +1285,7 @@
         }
 
         // assignment
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
         packaged_task(packaged_task&& other):
             future_obtained(other.future_obtained)
         {
@@ -1326,7 +1328,7 @@
         {
             if(!task)
             {
- throw task_moved();
+ boost::throw_exception(task_moved());
             }
             else if(!future_obtained)
             {
@@ -1335,7 +1337,7 @@
             }
             else
             {
- throw future_already_retrieved();
+ boost::throw_exception(future_already_retrieved());
             }
         }
         
@@ -1345,7 +1347,7 @@
         {
             if(!task)
             {
- throw task_moved();
+ boost::throw_exception(task_moved());
             }
             task->run();
         }

Modified: branches/release/boost/thread/locks.hpp
==============================================================================
--- branches/release/boost/thread/locks.hpp (original)
+++ branches/release/boost/thread/locks.hpp 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -248,7 +248,7 @@
         {
             timed_lock(target_time);
         }
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
         unique_lock(unique_lock&& other):
             m(other.m),is_locked(other.is_locked)
         {
@@ -321,17 +321,17 @@
             swap(temp);
             return *this;
         }
- void swap(unique_lock& other)
- {
- std::swap(m,other.m);
- std::swap(is_locked,other.is_locked);
- }
         void swap(detail::thread_move_t<unique_lock<Mutex> > other)
         {
             std::swap(m,other->m);
             std::swap(is_locked,other->is_locked);
         }
 #endif
+ void swap(unique_lock& other)
+ {
+ std::swap(m,other.m);
+ std::swap(is_locked,other.is_locked);
+ }
         
         ~unique_lock()
         {
@@ -344,7 +344,7 @@
         {
             if(owns_lock())
             {
- throw boost::lock_error();
+ boost::throw_exception(boost::lock_error());
             }
             m->lock();
             is_locked=true;
@@ -353,7 +353,7 @@
         {
             if(owns_lock())
             {
- throw boost::lock_error();
+ boost::throw_exception(boost::lock_error());
             }
             is_locked=m->try_lock();
             return is_locked;
@@ -379,7 +379,7 @@
         {
             if(!owns_lock())
             {
- throw boost::lock_error();
+ boost::throw_exception(boost::lock_error());
             }
             m->unlock();
             is_locked=false;
@@ -416,25 +416,30 @@
         friend class upgrade_lock<Mutex>;
     };
 
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
     template<typename Mutex>
     void swap(unique_lock<Mutex>&& lhs,unique_lock<Mutex>&& rhs)
     {
         lhs.swap(rhs);
     }
-#else
+#endif
     template<typename Mutex>
     void swap(unique_lock<Mutex>& lhs,unique_lock<Mutex>& rhs)
     {
         lhs.swap(rhs);
     }
-#endif
 
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
     template<typename Mutex>
     inline unique_lock<Mutex>&& move(unique_lock<Mutex>&& ul)
     {
- return ul;
+ return static_cast<unique_lock<Mutex>&&>(ul);
+ }
+
+ template<typename Mutex>
+ inline unique_lock<Mutex>&& move(unique_lock<Mutex>& ul)
+ {
+ return static_cast<unique_lock<Mutex>&&>(ul);
     }
 #endif
 
@@ -535,24 +540,24 @@
             return *this;
         }
 
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
         void swap(shared_lock&& other)
         {
             std::swap(m,other.m);
             std::swap(is_locked,other.is_locked);
         }
 #else
- void swap(shared_lock& other)
- {
- std::swap(m,other.m);
- std::swap(is_locked,other.is_locked);
- }
         void swap(boost::detail::thread_move_t<shared_lock<Mutex> > other)
         {
             std::swap(m,other->m);
             std::swap(is_locked,other->is_locked);
         }
 #endif
+ void swap(shared_lock& other)
+ {
+ std::swap(m,other.m);
+ std::swap(is_locked,other.is_locked);
+ }
 
         Mutex* mutex() const
         {
@@ -570,7 +575,7 @@
         {
             if(owns_lock())
             {
- throw boost::lock_error();
+ boost::throw_exception(boost::lock_error());
             }
             m->lock_shared();
             is_locked=true;
@@ -579,7 +584,7 @@
         {
             if(owns_lock())
             {
- throw boost::lock_error();
+ boost::throw_exception(boost::lock_error());
             }
             is_locked=m->try_lock_shared();
             return is_locked;
@@ -588,7 +593,7 @@
         {
             if(owns_lock())
             {
- throw boost::lock_error();
+ boost::throw_exception(boost::lock_error());
             }
             is_locked=m->timed_lock_shared(target_time);
             return is_locked;
@@ -598,7 +603,7 @@
         {
             if(owns_lock())
             {
- throw boost::lock_error();
+ boost::throw_exception(boost::lock_error());
             }
             is_locked=m->timed_lock_shared(target_time);
             return is_locked;
@@ -607,7 +612,7 @@
         {
             if(!owns_lock())
             {
- throw boost::lock_error();
+ boost::throw_exception(boost::lock_error());
             }
             m->unlock_shared();
             is_locked=false;
@@ -629,7 +634,7 @@
 
     };
 
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
     template<typename Mutex>
     void swap(shared_lock<Mutex>&& lhs,shared_lock<Mutex>&& rhs)
     {
@@ -733,7 +738,7 @@
         {
             if(owns_lock())
             {
- throw boost::lock_error();
+ boost::throw_exception(boost::lock_error());
             }
             m->lock_upgrade();
             is_locked=true;
@@ -742,7 +747,7 @@
         {
             if(owns_lock())
             {
- throw boost::lock_error();
+ boost::throw_exception(boost::lock_error());
             }
             is_locked=m->try_lock_upgrade();
             return is_locked;
@@ -751,7 +756,7 @@
         {
             if(!owns_lock())
             {
- throw boost::lock_error();
+ boost::throw_exception(boost::lock_error());
             }
             m->unlock_upgrade();
             is_locked=false;
@@ -775,7 +780,7 @@
     };
 
 
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
     template<typename Mutex>
     unique_lock<Mutex>::unique_lock(upgrade_lock<Mutex>&& other):
         m(other.m),is_locked(other.is_locked)
@@ -875,7 +880,7 @@
             try_lock_wrapper(Mutex& m_,try_to_lock_t):
                 base(m_,try_to_lock)
             {}
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
             try_lock_wrapper(try_lock_wrapper&& other):
                 base(other.move())
             {}
@@ -963,7 +968,7 @@
             }
         };
 
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
         template<typename Mutex>
         void swap(try_lock_wrapper<Mutex>&& lhs,try_lock_wrapper<Mutex>&& rhs)
         {

Modified: branches/release/boost/thread/pthread/condition_variable.hpp
==============================================================================
--- branches/release/boost/thread/pthread/condition_variable.hpp (original)
+++ branches/release/boost/thread/pthread/condition_variable.hpp 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -57,13 +57,13 @@
             int const res=pthread_mutex_init(&internal_mutex,NULL);
             if(res)
             {
- throw thread_resource_error();
+ boost::throw_exception(thread_resource_error());
             }
             int const res2=pthread_cond_init(&cond,NULL);
             if(res2)
             {
                 BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
- throw thread_resource_error();
+ boost::throw_exception(thread_resource_error());
             }
         }
         ~condition_variable_any()
@@ -87,7 +87,7 @@
             }
             if(res)
             {
- throw condition_error();
+ boost::throw_exception(condition_error());
             }
         }
 
@@ -117,7 +117,7 @@
             }
             if(res)
             {
- throw condition_error();
+ boost::throw_exception(condition_error());
             }
             return true;
         }

Modified: branches/release/boost/thread/pthread/condition_variable_fwd.hpp
==============================================================================
--- branches/release/boost/thread/pthread/condition_variable_fwd.hpp (original)
+++ branches/release/boost/thread/pthread/condition_variable_fwd.hpp 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -6,6 +6,7 @@
 // (C) Copyright 2007-8 Anthony Williams
 
 #include <boost/assert.hpp>
+#include <boost/throw_exception.hpp>
 #include <pthread.h>
 #include <boost/thread/mutex.hpp>
 #include <boost/thread/locks.hpp>
@@ -30,7 +31,7 @@
             int const res=pthread_cond_init(&cond,NULL);
             if(res)
             {
- throw thread_resource_error();
+ boost::throw_exception(thread_resource_error());
             }
         }
         ~condition_variable()

Modified: branches/release/boost/thread/pthread/mutex.hpp
==============================================================================
--- branches/release/boost/thread/pthread/mutex.hpp (original)
+++ branches/release/boost/thread/pthread/mutex.hpp 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -7,6 +7,7 @@
 
 #include <pthread.h>
 #include <boost/utility.hpp>
+#include <boost/throw_exception.hpp>
 #include <boost/thread/exceptions.hpp>
 #include <boost/thread/locks.hpp>
 #include <boost/thread/thread_time.hpp>
@@ -37,7 +38,7 @@
             int const res=pthread_mutex_init(&m,NULL);
             if(res)
             {
- throw thread_resource_error();
+ boost::throw_exception(thread_resource_error());
             }
         }
         ~mutex()
@@ -89,14 +90,14 @@
             int const res=pthread_mutex_init(&m,NULL);
             if(res)
             {
- throw thread_resource_error();
+ boost::throw_exception(thread_resource_error());
             }
 #ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
             int const res2=pthread_cond_init(&cond,NULL);
             if(res2)
             {
                 BOOST_VERIFY(!pthread_mutex_destroy(&m));
- throw thread_resource_error();
+ boost::throw_exception(thread_resource_error());
             }
             is_locked=false;
 #endif

Modified: branches/release/boost/thread/pthread/once.hpp
==============================================================================
--- branches/release/boost/thread/pthread/once.hpp (original)
+++ branches/release/boost/thread/pthread/once.hpp 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -10,6 +10,7 @@
 // http://www.boost.org/LICENSE_1_0.txt)
 
 #include <boost/thread/detail/config.hpp>
+#include <boost/config.hpp>
 
 #include <pthread.h>
 #include <boost/assert.hpp>
@@ -58,10 +59,13 @@
                 if(flag.epoch==uninitialized_flag)
                 {
                     flag.epoch=being_initialized;
+#ifndef BOOST_NO_EXCEPTIONS
                     try
                     {
+#endif
                         pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex);
                         f();
+#ifndef BOOST_NO_EXCEPTIONS
                     }
                     catch(...)
                     {
@@ -69,6 +73,7 @@
                         BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
                         throw;
                     }
+#endif
                     flag.epoch=--detail::once_global_epoch;
                     BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
                 }

Modified: branches/release/boost/thread/pthread/recursive_mutex.hpp
==============================================================================
--- branches/release/boost/thread/pthread/recursive_mutex.hpp (original)
+++ branches/release/boost/thread/pthread/recursive_mutex.hpp 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -7,6 +7,7 @@
 
 #include <pthread.h>
 #include <boost/utility.hpp>
+#include <boost/throw_exception.hpp>
 #include <boost/thread/exceptions.hpp>
 #include <boost/thread/locks.hpp>
 #include <boost/thread/thread_time.hpp>
@@ -42,18 +43,18 @@
             int const init_attr_res=pthread_mutexattr_init(&attr);
             if(init_attr_res)
             {
- throw thread_resource_error();
+ boost::throw_exception(thread_resource_error());
             }
             int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
             if(set_attr_res)
             {
- throw thread_resource_error();
+ boost::throw_exception(thread_resource_error());
             }
             
             int const res=pthread_mutex_init(&m,&attr);
             if(res)
             {
- throw thread_resource_error();
+ boost::throw_exception(thread_resource_error());
             }
             BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
         }
@@ -111,32 +112,32 @@
             int const init_attr_res=pthread_mutexattr_init(&attr);
             if(init_attr_res)
             {
- throw thread_resource_error();
+ boost::throw_exception(thread_resource_error());
             }
             int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
             if(set_attr_res)
             {
- throw thread_resource_error();
+ boost::throw_exception(thread_resource_error());
             }
             
             int const res=pthread_mutex_init(&m,&attr);
             if(res)
             {
                 BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
- throw thread_resource_error();
+ boost::throw_exception(thread_resource_error());
             }
             BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
 #else
             int const res=pthread_mutex_init(&m,NULL);
             if(res)
             {
- throw thread_resource_error();
+ boost::throw_exception(thread_resource_error());
             }
             int const res2=pthread_cond_init(&cond,NULL);
             if(res2)
             {
                 BOOST_VERIFY(!pthread_mutex_destroy(&m));
- throw thread_resource_error();
+ boost::throw_exception(thread_resource_error());
             }
             is_locked=false;
             count=0;

Modified: branches/release/boost/thread/pthread/thread_heap_alloc.hpp
==============================================================================
--- branches/release/boost/thread/pthread/thread_heap_alloc.hpp (original)
+++ branches/release/boost/thread/pthread/thread_heap_alloc.hpp 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -17,7 +17,7 @@
             return new T();
         }
 
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
         template<typename T,typename A1>
         inline T* heap_new(A1&& a1)
         {

Modified: branches/release/boost/thread/win32/basic_timed_mutex.hpp
==============================================================================
--- branches/release/boost/thread/win32/basic_timed_mutex.hpp (original)
+++ branches/release/boost/thread/win32/basic_timed_mutex.hpp 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -61,15 +61,30 @@
             
             void lock()
             {
- BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
- }
- bool timed_lock(::boost::system_time const& wait_until)
- {
- if(!win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit))
+ if(try_lock())
                 {
- return true;
+ return;
                 }
                 long old_count=active_count;
+ mark_waiting_and_try_lock(old_count);
+
+ if(old_count&lock_flag_value)
+ {
+ bool lock_acquired=false;
+ void* const sem=get_event();
+
+ do
+ {
+ BOOST_VERIFY(win32::WaitForSingleObject(
+ sem,::boost::detail::win32::infinite)==0);
+ clear_waiting_and_try_lock(old_count);
+ lock_acquired=!(old_count&lock_flag_value);
+ }
+ while(!lock_acquired);
+ }
+ }
+ void mark_waiting_and_try_lock(long& old_count)
+ {
                 for(;;)
                 {
                     long const new_count=(old_count&lock_flag_value)?(old_count+1):(old_count|lock_flag_value);
@@ -80,6 +95,33 @@
                     }
                     old_count=current;
                 }
+ }
+
+ void clear_waiting_and_try_lock(long& old_count)
+ {
+ old_count&=~lock_flag_value;
+ old_count|=event_set_flag_value;
+ for(;;)
+ {
+ long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value;
+ long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
+ if(current==old_count)
+ {
+ break;
+ }
+ old_count=current;
+ }
+ }
+
+
+ bool timed_lock(::boost::system_time const& wait_until)
+ {
+ if(try_lock())
+ {
+ return true;
+ }
+ long old_count=active_count;
+ mark_waiting_and_try_lock(old_count);
 
                 if(old_count&lock_flag_value)
                 {
@@ -93,18 +135,7 @@
                             BOOST_INTERLOCKED_DECREMENT(&active_count);
                             return false;
                         }
- old_count&=~lock_flag_value;
- old_count|=event_set_flag_value;
- for(;;)
- {
- long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value;
- long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
- if(current==old_count)
- {
- break;
- }
- old_count=current;
- }
+ clear_waiting_and_try_lock(old_count);
                         lock_acquired=!(old_count&lock_flag_value);
                     }
                     while(!lock_acquired);

Modified: branches/release/boost/thread/win32/once.hpp
==============================================================================
--- branches/release/boost/thread/win32/once.hpp (original)
+++ branches/release/boost/thread/win32/once.hpp 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -30,81 +30,47 @@
 
 namespace boost
 {
- typedef long once_flag;
-
-#define BOOST_ONCE_INIT 0
-
- namespace detail
+ struct once_flag
     {
- struct win32_mutex_scoped_lock
- {
- void* const mutex_handle;
- explicit win32_mutex_scoped_lock(void* mutex_handle_):
- mutex_handle(mutex_handle_)
- {
- BOOST_VERIFY(!win32::WaitForSingleObject(mutex_handle,win32::infinite));
- }
- ~win32_mutex_scoped_lock()
- {
- BOOST_VERIFY(win32::ReleaseMutex(mutex_handle)!=0);
- }
- private:
- void operator=(win32_mutex_scoped_lock&);
- };
+ long status;
+ long count;
+ long throw_count;
+ void* event_handle;
 
-#ifdef BOOST_NO_ANSI_APIS
- template <class I>
- void int_to_string(I p, wchar_t* buf)
+ ~once_flag()
         {
- for(unsigned i=0; i < sizeof(I)*2; ++i,++buf)
+ if(count)
             {
- *buf = L'A' + static_cast<wchar_t>((p >> (i*4)) & 0x0f);
+ BOOST_ASSERT(count==throw_count);
             }
- *buf = 0;
- }
-#else
- template <class I>
- void int_to_string(I p, char* buf)
- {
- for(unsigned i=0; i < sizeof(I)*2; ++i,++buf)
+
+ void* const old_event=BOOST_INTERLOCKED_EXCHANGE_POINTER(&event_handle,0);
+ if(old_event)
             {
- *buf = 'A' + static_cast<char>((p >> (i*4)) & 0x0f);
+ ::boost::detail::win32::CloseHandle(old_event);
             }
- *buf = 0;
         }
-#endif
+ };
+
+#define BOOST_ONCE_INIT {0,0,0,0}
 
- // create a named mutex. It doesn't really matter what this name is
- // as long as it is unique both to this process, and to the address of "flag":
- inline void* create_once_mutex(void* flag_address)
+ namespace detail
+ {
+ inline void* allocate_event_handle(void*& handle)
         {
-
-#ifdef BOOST_NO_ANSI_APIS
- typedef wchar_t char_type;
- static const char_type fixed_mutex_name[]=L"{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
-#else
- typedef char char_type;
- static const char_type fixed_mutex_name[]="{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag";
-#endif
- unsigned const once_mutex_name_fixed_buffer_size=sizeof(fixed_mutex_name)/sizeof(char_type);
- unsigned const once_mutex_name_fixed_length=once_mutex_name_fixed_buffer_size-1;
- unsigned const once_mutex_name_length=once_mutex_name_fixed_buffer_size+sizeof(void*)*2+sizeof(unsigned long)*2;
- char_type mutex_name[once_mutex_name_length];
+ void* const new_handle=::boost::detail::win32::create_anonymous_event(
+ ::boost::detail::win32::manual_reset_event,
+ ::boost::detail::win32::event_initially_reset);
             
- std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name));
-
- BOOST_STATIC_ASSERT(sizeof(void*) == sizeof(std::ptrdiff_t));
- detail::int_to_string(reinterpret_cast<std::ptrdiff_t>(flag_address), mutex_name + once_mutex_name_fixed_length);
- detail::int_to_string(win32::GetCurrentProcessId(), mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2);
-
-#ifdef BOOST_NO_ANSI_APIS
- return win32::CreateMutexW(0, 0, mutex_name);
-#else
- return win32::CreateMutexA(0, 0, mutex_name);
-#endif
+ void* event_handle=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&handle,
+ new_handle,0);
+ if(event_handle)
+ {
+ ::boost::detail::win32::CloseHandle(new_handle);
+ return event_handle;
+ }
+ return new_handle;
         }
-
-
     }
     
 
@@ -114,18 +80,98 @@
         // Try for a quick win: if the procedure has already been called
         // just skip through:
         long const function_complete_flag_value=0xc15730e2;
+ long const running_value=0x7f0725e3;
+ long status;
+ bool counted=false;
+ void* event_handle=0;
+ long throw_count=0;
 
- if(::boost::detail::interlocked_read_acquire(&flag)!=function_complete_flag_value)
+ while((status=::boost::detail::interlocked_read_acquire(&flag.status))
+ !=function_complete_flag_value)
+ {
+ status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,running_value,0);
+ if(!status)
+ {
+ try
+ {
+ if(!event_handle)
+ {
+ event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle);
+ }
+ if(event_handle)
+ {
+ ::boost::detail::win32::ResetEvent(event_handle);
+ }
+ f();
+ if(!counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ counted=true;
+ }
+ BOOST_INTERLOCKED_EXCHANGE(&flag.status,function_complete_flag_value);
+ if(!event_handle &&
+ (::boost::detail::interlocked_read_acquire(&flag.count)>1))
+ {
+ event_handle=::boost::detail::allocate_event_handle(flag.event_handle);
+ }
+ if(event_handle)
+ {
+ ::boost::detail::win32::SetEvent(event_handle);
+ }
+ throw_count=::boost::detail::interlocked_read_acquire(&flag.throw_count);
+ break;
+ }
+ catch(...)
+ {
+ if(counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.throw_count);
+ }
+ BOOST_INTERLOCKED_EXCHANGE(&flag.status,0);
+ if(!event_handle)
+ {
+ event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle);
+ }
+ if(event_handle)
+ {
+ ::boost::detail::win32::SetEvent(event_handle);
+ }
+ throw;
+ }
+ }
+
+ if(!counted)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&flag.count);
+ counted=true;
+ status=::boost::detail::interlocked_read_acquire(&flag.status);
+ if(status==function_complete_flag_value)
+ {
+ break;
+ }
+ event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle);
+ if(!event_handle)
+ {
+ event_handle=::boost::detail::allocate_event_handle(flag.event_handle);
+ continue;
+ }
+ }
+ BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObject(
+ event_handle,::boost::detail::win32::infinite));
+ }
+ if(counted || throw_count)
         {
- void* const mutex_handle(::boost::detail::create_once_mutex(&flag));
- BOOST_ASSERT(mutex_handle);
- detail::win32::handle_manager const closer(mutex_handle);
- detail::win32_mutex_scoped_lock const lock(mutex_handle);
-
- if(flag!=function_complete_flag_value)
+ if(!BOOST_INTERLOCKED_EXCHANGE_ADD(&flag.count,(counted?-1:0)-throw_count))
             {
- f();
- BOOST_INTERLOCKED_EXCHANGE(&flag,function_complete_flag_value);
+ if(!event_handle)
+ {
+ event_handle=::boost::detail::interlocked_read_acquire(&flag.event_handle);
+ }
+ if(event_handle)
+ {
+ BOOST_INTERLOCKED_EXCHANGE_POINTER(&flag.event_handle,0);
+ ::boost::detail::win32::CloseHandle(event_handle);
+ }
             }
         }
     }

Modified: branches/release/boost/thread/win32/thread_heap_alloc.hpp
==============================================================================
--- branches/release/boost/thread/win32/thread_heap_alloc.hpp (original)
+++ branches/release/boost/thread/win32/thread_heap_alloc.hpp 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -8,6 +8,7 @@
 #include "thread_primitives.hpp"
 #include <stdexcept>
 #include <boost/assert.hpp>
+#include <boost/throw_exception.hpp>
 
 #if defined( BOOST_USE_WINDOWS_H )
 # include <windows.h>
@@ -60,7 +61,7 @@
             void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,size);
             if(!heap_memory)
             {
- throw std::bad_alloc();
+ boost::throw_exception(std::bad_alloc());
             }
             return heap_memory;
         }
@@ -86,7 +87,7 @@
             }
         }
 
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
         template<typename T,typename A1>
         inline T* heap_new(A1&& a1)
         {

Modified: branches/release/boost/thread/win32/thread_primitives.hpp
==============================================================================
--- branches/release/boost/thread/win32/thread_primitives.hpp (original)
+++ branches/release/boost/thread/win32/thread_primitives.hpp 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -11,6 +11,7 @@
 // http://www.boost.org/LICENSE_1_0.txt)
 
 #include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
 #include <boost/assert.hpp>
 #include <boost/thread/exceptions.hpp>
 #include <boost/detail/interlocked.hpp>
@@ -177,7 +178,7 @@
 #endif
                 if(!res)
                 {
- throw thread_resource_error();
+ boost::throw_exception(thread_resource_error());
                 }
                 return res;
             }
@@ -191,7 +192,7 @@
 #endif
                 if(!res)
                 {
- throw thread_resource_error();
+ boost::throw_exception(thread_resource_error());
                 }
                 return res;
             }
@@ -204,7 +205,7 @@
                 bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0;
                 if(!success)
                 {
- throw thread_resource_error();
+ boost::throw_exception(thread_resource_error());
                 }
                 return new_handle;
             }

Modified: branches/release/libs/thread/doc/once.qbk
==============================================================================
--- branches/release/libs/thread/doc/once.qbk (original)
+++ branches/release/libs/thread/doc/once.qbk 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -45,6 +45,15 @@
 
 [[Throws:] [`thread_resource_error` when the effects cannot be achieved. or any exception propagated from `func`.]]
 
+[[Note:] [The function passed to `call_once` must not also call
+`call_once` passing the same `once_flag` object. This may cause
+deadlock, or invoking the passed function a second time. The
+alternative is to allow the second call to return immediately, but
+that assumes the code knows it has been called recursively, and can
+proceed even though the call to `call_once` didn't actually call the
+function, in which case it could also avoid calling `call_once`
+recursively.]]
+
 ]
 
     void call_once(void (*func)(),once_flag& flag);

Modified: branches/release/libs/thread/src/pthread/thread.cpp
==============================================================================
--- branches/release/libs/thread/src/pthread/thread.cpp (original)
+++ branches/release/libs/thread/src/pthread/thread.cpp 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -13,6 +13,7 @@
 #include <boost/thread/locks.hpp>
 #include <boost/thread/once.hpp>
 #include <boost/thread/tss.hpp>
+#include <boost/throw_exception.hpp>
 #ifdef __linux__
 #include <sys/sysinfo.h>
 #elif defined(__APPLE__) || defined(__FreeBSD__)
@@ -186,7 +187,7 @@
         if (res != 0)
         {
             thread_info->self.reset();
- throw thread_resource_error();
+ boost::throw_exception(thread_resource_error());
         }
     }
 

Modified: branches/release/libs/thread/src/pthread/timeconv.inl
==============================================================================
--- branches/release/libs/thread/src/pthread/timeconv.inl (original)
+++ branches/release/libs/thread/src/pthread/timeconv.inl 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -1,11 +1,14 @@
 // Copyright (C) 2001-2003
 // William E. Kempf
+// Copyright (C) 2009 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)
 
 // boostinspect:nounnamed
 
+#include <boost/assert.hpp>
+
 namespace {
 const int MILLISECONDS_PER_SECOND = 1000;
 const int NANOSECONDS_PER_SECOND = 1000000000;
@@ -18,7 +21,7 @@
 {
     int res = 0;
     res = boost::xtime_get(&xt, boost::TIME_UTC);
- assert(res == boost::TIME_UTC);
+ BOOST_ASSERT(res == boost::TIME_UTC);
 
     xt.sec += (milliseconds / MILLISECONDS_PER_SECOND);
     xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
@@ -55,7 +58,7 @@
     boost::xtime cur;
     int res = 0;
     res = boost::xtime_get(&cur, boost::TIME_UTC);
- assert(res == boost::TIME_UTC);
+ BOOST_ASSERT(res == boost::TIME_UTC);
 
     if (boost::xtime_cmp(xt, cur) <= 0)
     {
@@ -86,7 +89,7 @@
     boost::xtime cur;
     int res = 0;
     res = boost::xtime_get(&cur, boost::TIME_UTC);
- assert(res == boost::TIME_UTC);
+ BOOST_ASSERT(res == boost::TIME_UTC);
 
     if (boost::xtime_cmp(xt, cur) <= 0)
         milliseconds = 0;
@@ -108,7 +111,7 @@
     boost::xtime cur;
     int res = 0;
     res = boost::xtime_get(&cur, boost::TIME_UTC);
- assert(res == boost::TIME_UTC);
+ BOOST_ASSERT(res == boost::TIME_UTC);
 
     if (boost::xtime_cmp(xt, cur) <= 0)
         microseconds = 0;

Modified: branches/release/libs/thread/src/win32/thread.cpp
==============================================================================
--- branches/release/libs/thread/src/win32/thread.cpp (original)
+++ branches/release/libs/thread/src/win32/thread.cpp 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -17,6 +17,7 @@
 #include <boost/thread/once.hpp>
 #include <boost/thread/tss.hpp>
 #include <boost/assert.hpp>
+#include <boost/throw_exception.hpp>
 #include <boost/thread/detail/tss_hooks.hpp>
 #include <boost/date_time/posix_time/conversion.hpp>
 
@@ -188,7 +189,7 @@
         uintptr_t const new_thread=_beginthreadex(0,0,&thread_start_function,thread_info.get(),CREATE_SUSPENDED,&thread_info->id);
         if(!new_thread)
         {
- throw thread_resource_error();
+ boost::throw_exception(thread_resource_error());
         }
         intrusive_ptr_add_ref(thread_info.get());
         thread_info->thread_handle=(detail::win32::handle)(new_thread);

Modified: branches/release/libs/thread/test/Jamfile.v2
==============================================================================
--- branches/release/libs/thread/test/Jamfile.v2 (original)
+++ branches/release/libs/thread/test/Jamfile.v2 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -42,6 +42,7 @@
           [ thread-run test_thread_move_return.cpp ]
           [ thread-run test_thread_launching.cpp ]
           [ thread-run test_thread_mf.cpp ]
+ [ thread-run test_thread_exit.cpp ]
           [ thread-run test_move_function.cpp ]
           [ thread-run test_mutex.cpp ]
           [ thread-run test_condition_notify_one.cpp ]

Modified: branches/release/libs/thread/test/test_futures.cpp
==============================================================================
--- branches/release/libs/thread/test/test_futures.cpp (original)
+++ branches/release/libs/thread/test/test_futures.cpp 2010-04-01 11:04:15 EDT (Thu, 01 Apr 2010)
@@ -1,4 +1,4 @@
-// (C) Copyright 2008-9 Anthony Williams
+// (C) Copyright 2008-10 Anthony Williams
 //
 // Distributed under the Boost Software License, Version 1.0. (See
 // accompanying file LICENSE_1_0.txt or copy at
@@ -14,7 +14,7 @@
 
 #include <boost/test/unit_test.hpp>
 
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
     template<typename T>
     typename boost::remove_reference<T>::type&& cast_to_rval(T&& t)
     {
@@ -41,7 +41,7 @@
     X():
         i(42)
     {}
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
     X(X&& other):
         i(other.i)
     {
@@ -89,7 +89,7 @@
 void test_store_value_from_thread()
 {
     boost::promise<int> pi2;
- boost::unique_future<int> fi2=pi2.get_future();
+ boost::unique_future<int> fi2(pi2.get_future());
     boost::thread(set_promise_thread,&pi2);
     int j=fi2.get();
     BOOST_CHECK(j==42);


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