summaryrefslogtreecommitdiff
path: root/boost/thread/detail/thread.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/thread/detail/thread.hpp')
-rw-r--r--boost/thread/detail/thread.hpp340
1 files changed, 217 insertions, 123 deletions
diff --git a/boost/thread/detail/thread.hpp b/boost/thread/detail/thread.hpp
index 7ac342bfc6..3c71b53cf7 100644
--- a/boost/thread/detail/thread.hpp
+++ b/boost/thread/detail/thread.hpp
@@ -4,7 +4,9 @@
// 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
+#include <boost/thread/detail/config.hpp>
#include <boost/thread/exceptions.hpp>
#ifndef BOOST_NO_IOSTREAM
#include <ostream>
@@ -13,7 +15,6 @@
#include <boost/thread/mutex.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/thread/detail/thread_heap_alloc.hpp>
-#include <boost/utility.hpp>
#include <boost/assert.hpp>
#include <list>
#include <algorithm>
@@ -25,6 +26,13 @@
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/io/ios_state.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/decay.hpp>
+#include <boost/functional/hash.hpp>
+#ifdef BOOST_THREAD_USES_CHRONO
+#include <boost/chrono/system_clocks.hpp>
+#include <boost/chrono/ceil.hpp>
+#endif
#include <boost/config/abi_prefix.hpp>
@@ -35,6 +43,7 @@
namespace boost
{
+
namespace detail
{
template<typename F>
@@ -42,18 +51,21 @@ namespace boost
public detail::thread_data_base
{
public:
+ BOOST_THREAD_NO_COPYABLE(thread_data)
#ifndef BOOST_NO_RVALUE_REFERENCES
- thread_data(F&& f_):
- f(static_cast<F&&>(f_))
- {}
- thread_data(F& f_):
- f(f_)
- {}
+ thread_data(BOOST_THREAD_RV_REF(F) f_):
+ f(boost::forward<F>(f_))
+ {}
+// This overloading must be removed if we want the packaged_task's tests to pass.
+// thread_data(F& f_):
+// f(f_)
+// {}
#else
- thread_data(F f_):
- f(f_)
+
+ thread_data(BOOST_THREAD_RV_REF(F) f_):
+ f(f_)
{}
- thread_data(detail::thread_move_t<F> f_):
+ thread_data(F f_):
f(f_)
{}
#endif
@@ -63,9 +75,6 @@ namespace boost
}
private:
F f;
-
- void operator=(thread_data&);
- thread_data(thread_data&);
};
template<typename F>
@@ -74,14 +83,11 @@ namespace boost
{
private:
F& f;
-
- void operator=(thread_data&);
- thread_data(thread_data&);
public:
+ BOOST_THREAD_NO_COPYABLE(thread_data)
thread_data(boost::reference_wrapper<F> f_):
f(f_)
{}
-
void run()
{
f();
@@ -94,13 +100,11 @@ namespace boost
{
private:
F& f;
- void operator=(thread_data&);
- thread_data(thread_data&);
public:
+ BOOST_THREAD_NO_COPYABLE(thread_data)
thread_data(const boost::reference_wrapper<F> f_):
f(f_)
{}
-
void run()
{
f();
@@ -110,15 +114,18 @@ namespace boost
class BOOST_THREAD_DECL thread
{
+ public:
+ typedef thread_attributes attributes;
+
+ BOOST_THREAD_MOVABLE_ONLY(thread)
private:
- thread(thread&);
- thread& operator=(thread&);
void release_handle();
detail::thread_data_ptr thread_info;
void start_thread();
+ void start_thread(const attributes& attr);
explicit thread(detail::thread_data_ptr data);
@@ -126,13 +133,15 @@ namespace boost
#ifndef BOOST_NO_RVALUE_REFERENCES
template<typename F>
- static inline detail::thread_data_ptr make_thread_info(F&& f)
+ static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f)
{
- return detail::thread_data_ptr(detail::heap_new<detail::thread_data<typename boost::remove_reference<F>::type> >(static_cast<F&&>(f)));
+ return detail::thread_data_ptr(detail::heap_new<detail::thread_data<typename boost::remove_reference<F>::type> >(
+ boost::forward<F>(f)));
}
static inline detail::thread_data_ptr make_thread_info(void (*f)())
{
- return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(static_cast<void(*&&)()>(f)));
+ return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(
+ boost::forward<void(*)()>(f)));
}
#else
template<typename F>
@@ -141,7 +150,7 @@ namespace boost
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
}
template<typename F>
- static inline detail::thread_data_ptr make_thread_info(boost::detail::thread_move_t<F> f)
+ static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f)
{
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
}
@@ -149,44 +158,40 @@ namespace boost
#endif
struct dummy;
public:
+#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
thread(const volatile thread&);
#endif
- thread();
- ~thread();
-
-#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(static_cast<F&&>(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)
+ thread() BOOST_NOEXCEPT;
+ ~thread()
{
- thread_info.swap(other.thread_info);
+ #if defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE
+ if (joinable()) {
+ std::terminate();
+ }
+ #else
+ detach();
+ #endif
}
-
- thread& operator=(thread&& other)
+#ifndef BOOST_NO_RVALUE_REFERENCES
+ template <
+ class F
+ >
+ explicit thread(BOOST_THREAD_RV_REF(F) f
+ , typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
+ ):
+ thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f))))
{
- thread_info=other.thread_info;
- other.thread_info.reset();
- return *this;
+ start_thread();
}
-
- thread&& move()
+ template <
+ class F
+ >
+ thread(attributes& attrs, BOOST_THREAD_RV_REF(F) f):
+ thread_info(make_thread_info(thread_detail::decay_copy(boost::forward<F>(f))))
{
- return static_cast<thread&&>(*this);
+ start_thread(attrs);
}
#else
@@ -197,57 +202,73 @@ namespace boost
{
start_thread();
}
+ template <class F>
+ thread(attributes& attrs, F f):
+ thread_info(make_thread_info(f))
+ {
+ start_thread(attrs);
+ }
#else
template <class F>
- explicit thread(F f,typename disable_if<boost::is_convertible<F&,detail::thread_move_t<F> >, dummy* >::type=0):
+ explicit thread(F f
+ // todo Disable also if Or is_same<typename decay<F>::type, thread>
+ , typename disable_if<boost::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0):
thread_info(make_thread_info(f))
{
start_thread();
}
+ template <class F>
+ thread(attributes& attrs, F f
+ , typename disable_if<boost::is_convertible<F&,BOOST_THREAD_RV_REF(F) >, dummy* >::type=0):
+ thread_info(make_thread_info(f))
+ {
+ start_thread(attrs);
+ }
#endif
-
template <class F>
- explicit thread(detail::thread_move_t<F> f):
+ explicit thread(BOOST_THREAD_RV_REF(F) f
+ , typename disable_if<is_same<typename decay<F>::type, thread>, dummy* >::type=0
+ ):
thread_info(make_thread_info(f))
{
start_thread();
}
- thread(detail::thread_move_t<thread> x)
+ template <class F>
+ thread(attributes& attrs, BOOST_THREAD_RV_REF(F) f):
+ thread_info(make_thread_info(f))
{
- thread_info=x->thread_info;
- x->thread_info.reset();
+ start_thread(attrs);
}
-
+#endif
+ thread(BOOST_THREAD_RV_REF(thread) x)
+ {
+ thread_info=BOOST_THREAD_RV(x).thread_info;
+ BOOST_THREAD_RV(x).thread_info.reset();
+ }
+#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF.
#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100)
thread& operator=(thread x)
{
swap(x);
return *this;
}
-#else
- thread& operator=(detail::thread_move_t<thread> x)
- {
- thread new_thread(x);
- swap(new_thread);
- return *this;
- }
#endif
- operator detail::thread_move_t<thread>()
- {
- return move();
- }
+#endif
- detail::thread_move_t<thread> move()
+ thread& operator=(BOOST_THREAD_RV_REF(thread) other) BOOST_NOEXCEPT
{
- detail::thread_move_t<thread> x(*this);
- return x;
- }
+#if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE
+ if (joinable()) std::terminate();
#endif
+ thread_info=BOOST_THREAD_RV(other).thread_info;
+ BOOST_THREAD_RV(other).thread_info.reset();
+ return *this;
+ }
template <class F,class A1>
- thread(F f,A1 a1):
+ thread(F f,A1 a1,typename disable_if<boost::is_convertible<F&,thread_attributes >, dummy* >::type=0):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1)))
{
start_thread();
@@ -308,36 +329,92 @@ namespace boost
start_thread();
}
- void swap(thread& x)
+ void swap(thread& x) BOOST_NOEXCEPT
{
thread_info.swap(x.thread_info);
}
class BOOST_SYMBOL_VISIBLE id;
- id get_id() const;
+ id get_id() const BOOST_NOEXCEPT;
- bool joinable() const;
+ bool joinable() const BOOST_NOEXCEPT;
void join();
- bool timed_join(const system_time& wait_until);
+#ifdef BOOST_THREAD_USES_CHRONO
+ template <class Rep, class Period>
+ bool try_join_for(const chrono::duration<Rep, Period>& rel_time)
+ {
+ return try_join_until(chrono::steady_clock::now() + rel_time);
+ }
+ template <class Clock, class Duration>
+ bool try_join_until(const chrono::time_point<Clock, Duration>& t)
+ {
+ using namespace chrono;
+ system_clock::time_point s_now = system_clock::now();
+ typename Clock::time_point c_now = Clock::now();
+ return try_join_until(s_now + ceil<nanoseconds>(t - c_now));
+ }
+ template <class Duration>
+ bool try_join_until(const chrono::time_point<chrono::system_clock, Duration>& t)
+ {
+ using namespace chrono;
+ typedef time_point<system_clock, nanoseconds> nano_sys_tmpt;
+ return try_join_until(nano_sys_tmpt(ceil<nanoseconds>(t.time_since_epoch())));
+ }
+#endif
+#if defined(BOOST_THREAD_PLATFORM_WIN32)
+ bool timed_join(const system_time& abs_time);
+
+#ifdef BOOST_THREAD_USES_CHRONO
+ bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp);
+#endif
+ public:
+
+#else
+ bool timed_join(const system_time& abs_time)
+ {
+ struct timespec const ts=detail::get_timespec(abs_time);
+ return do_try_join_until(ts);
+ }
+#ifdef BOOST_THREAD_USES_CHRONO
+ bool try_join_until(const chrono::time_point<chrono::system_clock, chrono::nanoseconds>& tp)
+ {
+ using namespace chrono;
+ nanoseconds d = tp.time_since_epoch();
+ timespec ts;
+ seconds s = duration_cast<seconds>(d);
+ ts.tv_sec = static_cast<long>(s.count());
+ ts.tv_nsec = static_cast<long>((d - s).count());
+ return do_try_join_until(ts);
+ }
+#endif
+ private:
+ bool do_try_join_until(struct timespec const &timeout);
+ public:
+
+#endif
template<typename TimeDuration>
inline bool timed_join(TimeDuration const& rel_time)
{
return timed_join(get_system_time()+rel_time);
}
- void detach();
- static unsigned hardware_concurrency();
+ void detach() BOOST_NOEXCEPT;
+
+ static unsigned hardware_concurrency() BOOST_NOEXCEPT;
+#define BOOST_THREAD_DEFINES_THREAD_NATIVE_HANDLE
typedef detail::thread_data_base::native_handle_type native_handle_type;
native_handle_type native_handle();
+#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
+ // Use thread::id when comparisions are needed
// backwards compatibility
bool operator==(const thread& other) const;
bool operator!=(const thread& other) const;
-
- static inline void yield()
+#endif
+ static inline void yield() BOOST_NOEXCEPT
{
this_thread::yield();
}
@@ -349,37 +426,30 @@ namespace boost
// extensions
void interrupt();
- bool interruption_requested() const;
+ bool interruption_requested() const BOOST_NOEXCEPT;
};
- inline void swap(thread& lhs,thread& rhs)
+ inline void swap(thread& lhs,thread& rhs) BOOST_NOEXCEPT
{
return lhs.swap(rhs);
}
#ifndef BOOST_NO_RVALUE_REFERENCES
- inline thread&& move(thread& t)
+ inline thread&& move(thread& t) BOOST_NOEXCEPT
{
return static_cast<thread&&>(t);
}
- inline thread&& move(thread&& t)
- {
- return static_cast<thread&&>(t);
- }
-#else
- inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> t)
- {
- return t;
- }
#endif
+ BOOST_THREAD_DCL_MOVABLE(thread)
+
namespace this_thread
{
- thread::id BOOST_THREAD_DECL get_id();
+ thread::id BOOST_THREAD_DECL get_id() BOOST_NOEXCEPT;
void BOOST_THREAD_DECL interruption_point();
- bool BOOST_THREAD_DECL interruption_enabled();
- bool BOOST_THREAD_DECL interruption_requested();
+ bool BOOST_THREAD_DECL interruption_enabled() BOOST_NOEXCEPT;
+ bool BOOST_THREAD_DECL interruption_requested() BOOST_NOEXCEPT;
inline BOOST_SYMBOL_VISIBLE void sleep(xtime const& abs_time)
{
@@ -390,48 +460,76 @@ namespace boost
class BOOST_SYMBOL_VISIBLE thread::id
{
private:
- detail::thread_data_ptr thread_data;
+ friend inline
+ std::size_t
+ hash_value(const thread::id &v)
+ {
+#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
+ return hash_value(v.thread_data);
+#else
+ return hash_value(v.thread_data.get());
+#endif
+ }
- id(detail::thread_data_ptr thread_data_):
+#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
+#if defined(BOOST_THREAD_PLATFORM_WIN32)
+ typedef unsigned int data;
+#else
+ typedef thread::native_handle_type data;
+#endif
+#else
+ typedef detail::thread_data_ptr data;
+#endif
+ data thread_data;
+
+ id(data thread_data_):
thread_data(thread_data_)
{}
friend class thread;
- friend id BOOST_THREAD_DECL this_thread::get_id();
+ friend id BOOST_THREAD_DECL this_thread::get_id() BOOST_NOEXCEPT;
public:
- id():
- thread_data()
+ id() BOOST_NOEXCEPT:
+#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID
+#if defined(BOOST_THREAD_PLATFORM_WIN32)
+ thread_data(0)
+#else
+ thread_data(0)
+#endif
+#else
+ thread_data()
+#endif
{}
- id(const id& other):
+ id(const id& other) BOOST_NOEXCEPT :
thread_data(other.thread_data)
{}
- bool operator==(const id& y) const
+ bool operator==(const id& y) const BOOST_NOEXCEPT
{
return thread_data==y.thread_data;
}
- bool operator!=(const id& y) const
+ bool operator!=(const id& y) const BOOST_NOEXCEPT
{
return thread_data!=y.thread_data;
}
- bool operator<(const id& y) const
+ bool operator<(const id& y) const BOOST_NOEXCEPT
{
return thread_data<y.thread_data;
}
- bool operator>(const id& y) const
+ bool operator>(const id& y) const BOOST_NOEXCEPT
{
return y.thread_data<thread_data;
}
- bool operator<=(const id& y) const
+ bool operator<=(const id& y) const BOOST_NOEXCEPT
{
return !(y.thread_data<thread_data);
}
- bool operator>=(const id& y) const
+ bool operator>=(const id& y) const BOOST_NOEXCEPT
{
return !(thread_data<y.thread_data);
}
@@ -440,7 +538,7 @@ namespace boost
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
template<class charT, class traits>
friend BOOST_SYMBOL_VISIBLE
- std::basic_ostream<charT, traits>&
+ std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const id& x)
{
if(x.thread_data)
@@ -456,12 +554,13 @@ namespace boost
#else
template<class charT, class traits>
BOOST_SYMBOL_VISIBLE
- std::basic_ostream<charT, traits>&
+ std::basic_ostream<charT, traits>&
print(std::basic_ostream<charT, traits>& os) const
{
if(thread_data)
{
- return os<<thread_data;
+ io::ios_flags_saver ifs( os );
+ return os<< std::hex << thread_data;
}
else
{
@@ -483,6 +582,7 @@ namespace boost
}
#endif
+#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
inline bool thread::operator==(const thread& other) const
{
return get_id()==other.get_id();
@@ -492,6 +592,7 @@ namespace boost
{
return get_id()!=other.get_id();
}
+#endif
namespace detail
{
@@ -521,13 +622,6 @@ namespace boost
void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*);
}
-#ifdef BOOST_NO_RVALUE_REFERENCES
- template <>
- struct has_move_emulation_enabled_aux<thread>
- : BOOST_MOVE_BOOST_NS::integral_constant<bool, true>
- {};
-#endif
-
namespace this_thread
{
template<typename F>