From 0d9e8a0c3c53bfa945d10a08134af9b595252f02 Mon Sep 17 00:00:00 2001 From: "Vicente J. Botet Escriba" Date: Sat, 17 Nov 2012 09:00:16 +0000 Subject: [PATCH] Thread: Towards removing DateTime dependency on the library binary file. [SVN r81383] --- include/boost/thread/detail/thread.hpp | 4 +- .../thread/pthread/condition_variable.hpp | 14 +-- .../thread/pthread/condition_variable_fwd.hpp | 28 ++++-- include/boost/thread/pthread/thread_data.hpp | 58 ++++------- include/boost/thread/pthread/timespec.hpp | 97 ++++++++++++++++--- src/pthread/thread.cpp | 86 +++++++++++++++- src/win32/thread.cpp | 1 + 7 files changed, 212 insertions(+), 76 deletions(-) diff --git a/include/boost/thread/detail/thread.hpp b/include/boost/thread/detail/thread.hpp index 31f8973c..d969563d 100644 --- a/include/boost/thread/detail/thread.hpp +++ b/include/boost/thread/detail/thread.hpp @@ -3,8 +3,8 @@ // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -// (C) Copyright 2007-10 Anthony Williams -// (C) Copyright 20011-12 Vicente J. Botet Escriba +// (C) Copyright 2007-2010 Anthony Williams +// (C) Copyright 20011-2012 Vicente J. Botet Escriba #include diff --git a/include/boost/thread/pthread/condition_variable.hpp b/include/boost/thread/pthread/condition_variable.hpp index 974887dd..87360b22 100644 --- a/include/boost/thread/pthread/condition_variable.hpp +++ b/include/boost/thread/pthread/condition_variable.hpp @@ -4,7 +4,7 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // (C) Copyright 2007-10 Anthony Williams -// (C) Copyright 2011 Vicente J. Botet Escriba +// (C) Copyright 2011-2012 Vicente J. Botet Escriba #include #include @@ -75,12 +75,14 @@ namespace boost } } - inline bool condition_variable::do_timed_wait( + inline bool condition_variable::do_wait_until( unique_lock& m, struct timespec const &timeout) { if (!m.owns_lock()) - boost::throw_exception(condition_error(EPERM, "condition_variable do_timed_wait: mutex not locked")); + { + boost::throw_exception(condition_error(EPERM, "condition_variable do_wait_until: mutex not locked")); + } thread_cv_detail::lock_on_exit > guard; int cond_res; @@ -176,7 +178,7 @@ namespace boost bool timed_wait(lock_type& m,boost::system_time const& wait_until) { struct timespec const timeout=detail::to_timespec(wait_until); - return do_timed_wait(m, timeout); + return do_wait_until(m, timeout); } template bool timed_wait(lock_type& m,xtime const& wait_until) @@ -296,7 +298,7 @@ namespace boost using namespace chrono; nanoseconds d = tp.time_since_epoch(); timespec ts = boost::detail::to_timespec(d); - if (do_timed_wait(lk, ts)) return cv_status::no_timeout; + if (do_wait_until(lk, ts)) return cv_status::no_timeout; else return cv_status::timeout; } #endif @@ -315,7 +317,7 @@ namespace boost private: // used by boost::thread::try_join_until template - inline bool do_timed_wait( + inline bool do_wait_until( lock_type& m, struct timespec const &timeout) { diff --git a/include/boost/thread/pthread/condition_variable_fwd.hpp b/include/boost/thread/pthread/condition_variable_fwd.hpp index 03456baa..42bdd89f 100644 --- a/include/boost/thread/pthread/condition_variable_fwd.hpp +++ b/include/boost/thread/pthread/condition_variable_fwd.hpp @@ -4,7 +4,7 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // (C) Copyright 2007-8 Anthony Williams -// (C) Copyright 2011 Vicente J. Botet Escriba +// (C) Copyright 2011-2012 Vicente J. Botet Escriba #include #include @@ -13,6 +13,7 @@ #include #include #include +#include #include #ifdef BOOST_THREAD_USES_CHRONO #include @@ -31,6 +32,20 @@ namespace boost pthread_mutex_t internal_mutex; pthread_cond_t cond; + public: + //private: // used by boost::thread::try_join_until + + inline bool do_wait_until( + unique_lock& lock, + struct timespec const &timeout); + + bool do_wait_for( + unique_lock& lock, + struct timespec const &timeout) + { + return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now())); + } + public: BOOST_THREAD_NO_COPYABLE(condition_variable) condition_variable() @@ -73,10 +88,10 @@ namespace boost { #if defined BOOST_THREAD_WAIT_BUG struct timespec const timeout=detail::to_timespec(wait_until + BOOST_THREAD_WAIT_BUG); - return do_timed_wait(m, timeout); + return do_wait_until(m, timeout); #else struct timespec const timeout=detail::to_timespec(wait_until); - return do_timed_wait(m, timeout); + return do_wait_until(m, timeout); #endif } bool timed_wait( @@ -219,15 +234,10 @@ namespace boost using namespace chrono; nanoseconds d = tp.time_since_epoch(); timespec ts = boost::detail::to_timespec(d); - if (do_timed_wait(lk, ts)) return cv_status::no_timeout; + if (do_wait_until(lk, ts)) return cv_status::no_timeout; else return cv_status::timeout; } #endif - //private: // used by boost::thread::try_join_until - - inline bool do_timed_wait( - unique_lock& lock, - struct timespec const &timeout); }; BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock lk); diff --git a/include/boost/thread/pthread/thread_data.hpp b/include/boost/thread/pthread/thread_data.hpp index 70c5b0db..c27aa7a0 100644 --- a/include/boost/thread/pthread/thread_data.hpp +++ b/include/boost/thread/pthread/thread_data.hpp @@ -210,65 +210,43 @@ namespace boost namespace this_thread { + namespace hiden + { + void BOOST_THREAD_DECL sleep_for(const timespec& ts); + void BOOST_THREAD_DECL sleep_until(const timespec& ts); + } + #ifdef BOOST_THREAD_USES_CHRONO inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) { - using namespace chrono; - boost::detail::thread_data_base* const thread_info=boost::detail::get_current_thread_data(); - - if(thread_info) - { - unique_lock lk(thread_info->sleep_mutex); - while(cv_status::no_timeout==thread_info->sleep_condition.wait_for(lk,ns)) {} - } - else - { - if (ns >= nanoseconds::zero()) - { - - # if defined(BOOST_HAS_PTHREAD_DELAY_NP) - timespec ts = boost::detail::to_timespec(ns); - BOOST_VERIFY(!pthread_delay_np(&ts)); - # elif defined(BOOST_HAS_NANOSLEEP) - timespec ts = boost::detail::to_timespec(ns); - // nanosleep takes a timespec that is an offset, not - // an absolute time. - nanosleep(&ts, 0); - # else - mutex mx; - unique_lock lock(mx); - condition_variable cond; - cond.wait_for(lock, ns); - # endif - } - } + return boost::this_thread::hiden::sleep_for(boost::detail::to_timespec(ns)); } -#endif +#endif // BOOST_THREAD_USES_CHRONO + void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT; #if defined BOOST_THREAD_USES_DATETIME #ifdef __DECXXX /// Workaround of DECCXX issue of incorrect template substitution - template - inline void sleep(TimeDuration const& rel_time) - { - this_thread::sleep(get_system_time()+rel_time); - } - template<> +#endif void BOOST_THREAD_DECL sleep(system_time const& abs_time) +#if 1 + ; #else - void BOOST_THREAD_DECL sleep(system_time const& abs_time); + { + return boost::this_thread::hiden::sleep_until(boost::detail::to_timespec(abs_time)); + } +#endif template inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) { this_thread::sleep(get_system_time()+rel_time); } -#endif -#endif - } +#endif // BOOST_THREAD_USES_DATETIME + } // this_thread } #include diff --git a/include/boost/thread/pthread/timespec.hpp b/include/boost/thread/pthread/timespec.hpp index 553f340d..8cc3bdff 100644 --- a/include/boost/thread/pthread/timespec.hpp +++ b/include/boost/thread/pthread/timespec.hpp @@ -1,6 +1,7 @@ #ifndef BOOST_THREAD_PTHREAD_TIMESPEC_HPP #define BOOST_THREAD_PTHREAD_TIMESPEC_HPP // (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2012 Vicente J. Botet Escriba // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -19,33 +20,99 @@ #include #endif +#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) +# define BOOST_THREAD_TIMESPEC_MAC_API +#include //for gettimeofday and timeval +#else +#include // for clock_gettime +#endif + #include namespace boost { - namespace detail - { + namespace detail + { #if defined BOOST_THREAD_USES_DATETIME - inline struct timespec to_timespec(boost::system_time const& abs_time) - { - struct timespec timeout={0,0}; - boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0); + inline struct timespec to_timespec(boost::system_time const& abs_time) + { + struct timespec timeout = { 0,0}; + boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0); - timeout.tv_sec=time_since_epoch.total_seconds(); - timeout.tv_nsec=(long)(time_since_epoch.fractional_seconds()*(1000000000l/time_since_epoch.ticks_per_second())); - return timeout; - } + timeout.tv_sec=time_since_epoch.total_seconds(); + timeout.tv_nsec=(long)(time_since_epoch.fractional_seconds()*(1000000000l/time_since_epoch.ticks_per_second())); + return timeout; + } #endif #if defined BOOST_THREAD_USES_CHRONO - inline timespec to_timespec(chrono::nanoseconds const& ns) + inline timespec to_timespec(chrono::nanoseconds const& ns) + { + struct timespec ts; + ts.tv_sec = static_cast(chrono::duration_cast(ns).count()); + ts.tv_nsec = static_cast((ns - chrono::duration_cast(ns)).count()); + return ts; + } + +#endif + + inline timespec to_timespec(boost::intmax_t const& ns) + { + boost::intmax_t s = ns / 1000000000l; + struct timespec ts; + ts.tv_sec = static_cast (s); + ts.tv_nsec = static_cast (ns - s * 1000000000l); + return ts; + } + inline boost::intmax_t to_nanoseconds_int_max(timespec const& ts) + { + return ts.tv_sec * 1000000000l + ts.tv_nsec; + } + inline bool timespec_ge_zero(timespec const& ts) + { + return (ts.tv_sec >= 0) || (ts.tv_nsec >= 0); + } + inline timespec timespec_now() + { + timespec ts; + +#if defined(BOOST_THREAD_TIMESPEC_MAC_API) + timeval tv; + ::gettimeofday(&tv, 0); + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; +#else + if ( ::clock_gettime( CLOCK_REALTIME, &ts ) ) { - struct timespec ts; - ts.tv_sec = static_cast(no::duration_cast(ns).count()); - ts.tv_nsec = static_cast((ns - no::duration_cast(ns)).count()); - return ts; + BOOST_ASSERT(0 && "Boost::Thread - Internal Error"); } #endif + return ts; } + inline timespec timespec_zero() + { + timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 0; + return ts; + } + inline timespec timespec_plus(timespec const& lhs, timespec const& rhs) + { + return to_timespec(to_nanoseconds_int_max(lhs) + to_nanoseconds_int_max(rhs)); + } + inline timespec timespec_minus(timespec const& lhs, timespec const& rhs) + { + return to_timespec(to_nanoseconds_int_max(lhs) - to_nanoseconds_int_max(rhs)); + } + inline bool timespec_gt(timespec const& lhs, timespec const& rhs) + { + return to_nanoseconds_int_max(lhs) > to_nanoseconds_int_max(rhs); + } + inline bool timespec_ge(timespec const& lhs, timespec const& rhs) + { + return to_nanoseconds_int_max(lhs) >= to_nanoseconds_int_max(rhs); + } + + } } #include diff --git a/src/pthread/thread.cpp b/src/pthread/thread.cpp index abb9128c..44efe222 100644 --- a/src/pthread/thread.cpp +++ b/src/pthread/thread.cpp @@ -1,7 +1,7 @@ // Copyright (C) 2001-2003 // William E. Kempf // Copyright (C) 2007-8 Anthony Williams -// (C) Copyright 2011 Vicente J. Botet Escriba +// (C) Copyright 2011-2012 Vicente J. Botet Escriba // // 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) @@ -351,7 +351,7 @@ namespace boost unique_lock lock(local_thread_info->data_mutex); while(!local_thread_info->done) { - if(!local_thread_info->done_condition.do_timed_wait(lock,timeout)) + if(!local_thread_info->done_condition.do_wait_until(lock,timeout)) { res=false; return true; @@ -418,11 +418,88 @@ namespace boost namespace this_thread { + namespace hiden + { + void BOOST_THREAD_DECL sleep_for(const timespec& ts) + { + boost::detail::thread_data_base* const thread_info=boost::detail::get_current_thread_data(); + if(thread_info) + { + unique_lock lk(thread_info->sleep_mutex); + while( thread_info->sleep_condition.do_wait_for(lk,ts)) {} + } + else + { + + if (boost::detail::timespec_ge(ts, boost::detail::timespec_zero())) + { + + # if defined(BOOST_HAS_PTHREAD_DELAY_NP) + BOOST_VERIFY(!pthread_delay_np(&ts)); + # elif defined(BOOST_HAS_NANOSLEEP) + // nanosleep takes a timespec that is an offset, not + // an absolute time. + nanosleep(&ts, 0); + # else + mutex mx; + unique_lock lock(mx); + condition_variable cond; + cond.do_wait_for(lock, ts); + # endif + } + } + } + + void BOOST_THREAD_DECL sleep_until(const timespec& ts) + { + boost::detail::thread_data_base* const thread_info=boost::detail::get_current_thread_data(); + + if(thread_info) + { + unique_lock lk(thread_info->sleep_mutex); + while(thread_info->sleep_condition.do_wait_until(lk,ts)) {} + } + else + { + timespec now = boost::detail::timespec_now(); + if (boost::detail::timespec_gt(ts, now)) + { + for (int foo=0; foo < 5; ++foo) + { + + # if defined(BOOST_HAS_PTHREAD_DELAY_NP) + timespec d = boost::detail::timespec_minus(ts, now); + BOOST_VERIFY(!pthread_delay_np(&d)); + # elif defined(BOOST_HAS_NANOSLEEP) + // nanosleep takes a timespec that is an offset, not + // an absolute time. + timespec d = boost::detail::timespec_minus(ts, now); + nanosleep(&d, 0); + # else + mutex mx; + unique_lock lock(mx); + condition_variable cond; + cond.do_wait_until(lock, ts); + # endif + timespec now2 = boost::detail::timespec_now(); + if (boost::detail::timespec_ge(now2, ts)) + { + return; + } + } + } + } + } + } // hiden + } // this_thread + namespace this_thread + { +#if 1 #ifdef __DECXXX /// Workaround of DECCXX issue of incorrect template substitution template<> -#endif +#endif // __DECXXX #if defined BOOST_THREAD_USES_DATETIME void sleep(const system_time& st) { @@ -463,7 +540,8 @@ namespace boost } } } -#endif +#endif // BOOST_THREAD_USES_DATETIME +#endif //1 void yield() BOOST_NOEXCEPT { # if defined(BOOST_HAS_SCHED_YIELD) diff --git a/src/win32/thread.cpp b/src/win32/thread.cpp index 61f70804..e9c0eafe 100644 --- a/src/win32/thread.cpp +++ b/src/win32/thread.cpp @@ -3,6 +3,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // (C) Copyright 2007 Anthony Williams // (C) Copyright 2007 David Deakins +// (C) Copyright 2011-2012 Vicente J. Botet Escriba #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x400