diff --git a/include/boost/thread/detail/config.hpp b/include/boost/thread/detail/config.hpp index 4e3f402b..c6737d7f 100644 --- a/include/boost/thread/detail/config.hpp +++ b/include/boost/thread/detail/config.hpp @@ -16,21 +16,4 @@ # define BOOST_THREAD_DECL #endif // BOOST_THREAD_SHARED_LIB -#if defined(BOOST_HAS_WINTHREADS) -# define BOOST_THREAD_ATTRIBUTES_STACKSIZE -# define BOOST_THREAD_STACK_MIN 0 -# define BOOST_THREAD_PRIORITY_SCHEDULING -#elif defined(BOOST_HAS_PTHREADS) -# if defined(_POSIX_THREAD_ATTR_STACKSIZE) -# define BOOST_THREAD_ATTRIBUTES_STACKSIZE -# define BOOST_THREAD_STACK_MIN PTHREAD_STACK_MIN -# endif -# if defined(_POSIX_THREAD_ATTR_STACKADDR) -# define BOOST_THREAD_ATTRIBUTES_STACKADDR -# endif -# if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) -# define BOOST_THREAD_PRIORITY_SCHEDULING -# endif -#endif - #endif // BOOST_THREAD_CONFIG_WEK1032003_HPP diff --git a/include/boost/thread/exceptions.hpp b/include/boost/thread/exceptions.hpp index 2342674c..a4ecf6e4 100644 --- a/include/boost/thread/exceptions.hpp +++ b/include/boost/thread/exceptions.hpp @@ -25,16 +25,71 @@ namespace boost { -class BOOST_THREAD_DECL lock_error : public std::logic_error +class BOOST_THREAD_DECL thread_exception : public std::exception { +protected: + thread_exception(); + thread_exception(int sys_err_code); + public: - lock_error(); + ~thread_exception() throw(); + + int native_error() const { return m_sys_err; } + + const char* message() const; + +private: + int m_sys_err; }; -class BOOST_THREAD_DECL thread_resource_error : public std::runtime_error +class BOOST_THREAD_DECL lock_error : public thread_exception { public: - thread_resource_error(); + lock_error(); + lock_error(int sys_err_code); + ~lock_error() throw(); + + virtual const char* what() const throw(); +}; + +class BOOST_THREAD_DECL thread_resource_error : public thread_exception +{ +public: + thread_resource_error(); + thread_resource_error(int sys_err_code); + ~thread_resource_error() throw(); + + virtual const char* what() const throw(); +}; + +class BOOST_THREAD_DECL unsupported_thread_option : public thread_exception +{ +public: + unsupported_thread_option(); + unsupported_thread_option(int sys_err_code); + ~unsupported_thread_option() throw(); + + virtual const char* what() const throw(); +}; + +class BOOST_THREAD_DECL invalid_thread_argument : public thread_exception +{ +public: + invalid_thread_argument(); + invalid_thread_argument(int sys_err_code); + ~invalid_thread_argument() throw(); + + virtual const char* what() const throw(); +}; + +class BOOST_THREAD_DECL thread_permission_error : public thread_exception +{ +public: + thread_permission_error(); + thread_permission_error(int sys_err_code); + ~thread_permission_error() throw(); + + virtual const char* what() const throw(); }; } // namespace boost diff --git a/include/boost/thread/thread.hpp b/include/boost/thread/thread.hpp index 7be8a475..dfcf2e23 100644 --- a/include/boost/thread/thread.hpp +++ b/include/boost/thread/thread.hpp @@ -14,7 +14,6 @@ #include -#include #include #include #include @@ -28,12 +27,6 @@ # include #endif -// Config macros -// BOOST_THREAD_ATTRIBUTES_STACKSIZE -// BOOST_THREAD_ATTRIBUTES_STACKADDR -// BOOST_THREAD_PRIORITY_SCHEDULING -// - namespace boost { struct xtime; @@ -45,25 +38,24 @@ public: ~thread_cancel(); }; -#if defined(BOOST_THREAD_PRIORITY_SCHEDULING) -# if defined(BOOST_HAS_WINTHREADS) +#if defined(BOOST_HAS_WINTHREADS) struct sched_param { int priority; }; -enum { sched_fifo, sched_rr, sched_other }; +enum { sched_fifo, sched_round_robin, sched_other }; enum { scope_process, scope_system }; -# elif defined(BOOST_HAS_PTHREADS) +#elif defined(BOOST_HAS_PTHREADS) using ::sched_param; enum { sched_fifo = SCHED_FIFO, - sched_rr = SCHED_RR, + sched_round_robin = SCHED_RR, sched_other = SCHED_OTHER }; @@ -73,10 +65,9 @@ enum scope_system = PTHREAD_SCOPE_SYSTEM }; -# endif -#endif // BOOST_THREAD_PRIORITY_SCHEDULING +#endif -class BOOST_THREAD_DECL thread : private noncopyable +class BOOST_THREAD_DECL thread { public: class BOOST_THREAD_DECL attributes @@ -85,26 +76,18 @@ public: attributes(); ~attributes(); -#if defined(BOOST_THREAD_ATTRIBUTES_STACKSIZE) - attributes& stack_size(size_t size); - size_t stack_size() const; -#endif // BOOST_THREAD_ATTRIBUTES_STACKSIZE + attributes& set_stack_size(size_t size); + size_t get_stack_size() const; -#if defined(BOOST_THREAD_ATTRIBUTES_STACKADDR) - attributes& stack_address(void* addr); - void* stack_address() const; -#endif // BOOST_THREAD_ATTRIBUTES_STACKADDR + attributes& set_stack_address(void* addr); + void* get_stack_address() const; -#if defined(BOOST_THREAD_PRIORITY_SCHEDULING) attributes& inherit_scheduling(bool inherit); bool inherit_scheduling() const; - attributes& scheduling_parameter(const sched_param& param); - sched_param scheduling_parameter() const; - attributes& scheduling_policy(int policy); - int scheduling_policy() const; + attributes& set_schedule(int policy, const sched_param& param); + void get_schedule(int& policy, sched_param& param); attributes& scope(int scope); int scope() const; -#endif // BOOST_THREAD_PRIORITY_SCHEDULING private: friend class thread; @@ -132,18 +115,18 @@ public: void join(); void cancel(); -#if defined(BOOST_THREAD_PRIORITY_SCHEDULING) void set_scheduling_parameter(int policy, const sched_param& param); void get_scheduling_parameter(int& policy, sched_param& param) const; static int max_priority(int policy); static int min_priority(int policy); -#endif // BOOST_THREAD_PRIORITY_SCHEDULING static void test_cancel(); static void sleep(const xtime& xt); static void yield(); + static const int stack_min; + // This is an implementation detail and should be private, // but we need it to be public to access the type in some // unnamed namespace free functions in the implementation. diff --git a/src/exceptions.cpp b/src/exceptions.cpp index f99d9d81..fa5cb0c0 100644 --- a/src/exceptions.cpp +++ b/src/exceptions.cpp @@ -12,14 +12,165 @@ #include #include +# ifdef BOOST_NO_STDC_NAMESPACE + namespace std { using ::strerror; } +# endif + +// BOOST_POSIX or BOOST_WINDOWS specify which API to use. +# if !defined( BOOST_WINDOWS ) && !defined( BOOST_POSIX ) +# if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__) +# define BOOST_WINDOWS +# else +# define BOOST_POSIX +# endif +# endif + +# if defined( BOOST_WINDOWS ) +# include "windows.h" +# else +# include // for POSIX error codes +# endif + +namespace +{ + +std::string system_message(int sys_err_code) +{ + std::string str; +# ifdef BOOST_WINDOWS + LPVOID lpMsgBuf; + ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + sys_err_code, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPSTR)&lpMsgBuf, + 0, + NULL); + str += static_cast(lpMsgBuf); + ::LocalFree(lpMsgBuf); // free the buffer + while (str.size() && (str[str.size()-1] == '\n' || str[str.size()-1] == '\r')) + str.erase(str.size()-1); +# else + str += std::strerror(errno); +# endif + return str; +} + +} // unnamed namespace + namespace boost { -lock_error::lock_error() : std::logic_error("thread lock error") +thread_exception::thread_exception() + : m_sys_err(0) { } -thread_resource_error::thread_resource_error() : std::runtime_error("thread resource error") +thread_exception::thread_exception(int sys_err_code) + : m_sys_err(sys_err_code) { } +thread_exception::~thread_exception() throw() +{ +} + +const char* thread_exception::message() const +{ + if (m_sys_err != 0) + return system_message(m_sys_err).c_str(); + return what(); +} + +lock_error::lock_error() +{ +} + +lock_error::lock_error(int sys_err_code) + : thread_exception(sys_err_code) +{ +} + +lock_error::~lock_error() throw() +{ +} + +const char* lock_error::what() const throw() +{ + return "boost::lock_error"; +} + +thread_resource_error::thread_resource_error() +{ +} + +thread_resource_error::thread_resource_error(int sys_err_code) + : thread_exception(sys_err_code) +{ +} + +thread_resource_error::~thread_resource_error() throw() +{ +} + +const char* thread_resource_error::what() const throw() +{ + return "boost::thread_resource_error"; +} + +unsupported_thread_option::unsupported_thread_option() +{ +} + +unsupported_thread_option::unsupported_thread_option(int sys_err_code) + : thread_exception(sys_err_code) +{ +} + +unsupported_thread_option::~unsupported_thread_option() throw() +{ +} + +const char* unsupported_thread_option::what() const throw() +{ + return "boost::unsupported_thread_option"; +} + +invalid_thread_argument::invalid_thread_argument() +{ +} + +invalid_thread_argument::invalid_thread_argument(int sys_err_code) + : thread_exception(sys_err_code) +{ +} + +invalid_thread_argument::~invalid_thread_argument() throw() +{ +} + +const char* invalid_thread_argument::what() const throw() +{ + return "boost::invalid_thread_argument"; +} + +thread_permission_error::thread_permission_error() +{ +} + +thread_permission_error::thread_permission_error(int sys_err_code) + : thread_exception(sys_err_code) +{ +} + +thread_permission_error::~thread_permission_error() throw() +{ +} + +const char* thread_permission_error::what() const throw() +{ + return "boost::thread_permission_error"; +} + } // namespace boost diff --git a/src/thread.cpp b/src/thread.cpp index 67dc9278..c17f5f92 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -61,10 +61,8 @@ public: const void* id() const; #endif -#if defined(BOOST_THREAD_PRIORITY_SCHEDULING) void set_scheduling_parameter(int policy, const sched_param& param); void get_scheduling_parameter(int& policy, sched_param& param) const; -#endif // BOOST_THREAD_PRIORITY_SCHEDULING private: mutable boost::mutex m_mutex; @@ -82,6 +80,7 @@ private: MPTaskID m_pTaskID; #endif bool m_canceled; + bool m_native; }; } // namespace boost @@ -158,12 +157,12 @@ static OSStatus thread_proxy(void* param) namespace boost { thread::data::data(const boost::function0& threadfunc) - : m_threadfunc(threadfunc), m_refcount(2), m_state(creating), m_canceled(false) + : m_threadfunc(threadfunc), m_refcount(2), m_state(creating), m_canceled(false), m_native(false) { } thread::data::data() - : m_refcount(2), m_state(running), m_canceled(false) + : m_refcount(2), m_state(running), m_canceled(false), m_native(true) { #if defined(BOOST_HAS_WINTHREADS) DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), @@ -187,8 +186,11 @@ thread::data::~data() res = CloseHandle(m_thread); assert(res); #elif defined(BOOST_HAS_PTHREADS) - res = pthread_detach(m_thread); - assert(res == 0); + if (!m_native) + { + res = pthread_detach(m_thread); + assert(res == 0); + } #elif defined(BOOST_HAS_MPTASKS) OSStatus lStatus = threads::mac::detail::safe_wait_on_queue(m_pJoinQueueID, NULL, NULL, NULL, kDurationForever); assert(lStatus == noErr); @@ -297,27 +299,33 @@ const void* thread::data::id() const } #endif -#if defined(BOOST_THREAD_PRIORITY_SCHEDULING) - void thread::data::set_scheduling_parameter(int policy, const sched_param& param) { #if defined(BOOST_HAS_WINTHREADS) if (policy != sched_other) - throw std::invalid_argument("policy"); + throw boost::invalid_thread_argument(); if (param.priority < THREAD_PRIORITY_LOWEST || param.priority > THREAD_PRIORITY_HIGHEST) - throw std::invalid_argument("param"); + throw boost::invalid_thread_argument(); boost::mutex::scoped_lock lock(m_mutex); BOOL res = FALSE; res = SetThreadPriority(m_thread, param.priority); + if (res == ERROR_ACCESS_DENIED) // guessing about possible return value + throw boost::thread_permission_error(res); assert(res); #elif defined(BOOST_HAS_PTHREADS) +# if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) int res = 0; res = pthread_setschedparam(m_thread, policy, ¶m); - if (res == EINVAL || res == ENOTSUP) - throw std::invalid_argument("policy/param"); + if (res == EINVAL) + throw boost::invalid_thread_argument(res); + if (res == ENOTSUP) + throw unsupported_thread_option(res); if (res == EPERM) - throw std::runtime_error("permission denied"); + throw boost::thread_permission_error(res); assert(res == 0); +# else + throw unsupported_thread_option(ENOTSUP); +# endif #endif } @@ -328,15 +336,17 @@ void thread::data::get_scheduling_parameter(int& policy, sched_param& param) con boost::mutex::scoped_lock lock(m_mutex); param.priority = GetThreadPriority(m_thread); #elif defined(BOOST_HAS_PTHREADS) +# if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) int res = 0; boost::mutex::scoped_lock lock(m_mutex); res = pthread_getschedparam(m_thread, &policy, ¶m); assert(res == 0); +# else + throw unsupported_thread_option(ENOTSUP); +# endif #endif } -#endif // BOOST_THREAD_PRIORITY_SCHEDULING - thread_cancel::thread_cancel() { } @@ -354,7 +364,7 @@ thread::attributes::attributes() #elif defined(BOOST_HAS_PTHREADS) int res = pthread_attr_init(&m_attr); if (res == ENOMEM) - throw thread_resource_error(); + throw thread_resource_error(res); assert(res == 0); #endif } @@ -366,74 +376,88 @@ thread::attributes::~attributes() #endif } -#if defined(BOOST_THREAD_ATTRIBUTES_STACKSIZE) - -thread::attributes& thread::attributes::stack_size(size_t size) +thread::attributes& thread::attributes::set_stack_size(size_t size) { #if defined(BOOST_HAS_WINTHREADS) m_stacksize = size; #elif defined(BOOST_HAS_PTHREADS) +# if defined(_POSIX_THREAD_ATTR_STACKSIZE) int res = 0; res = pthread_attr_setstacksize(&m_attr, size); if (res == EINVAL) - throw std::invalid_argument("size"); + throw invalid_thread_argument(res); assert(res == 0); +# else + throw unsupported_thread_option(ENOTSUP); +# endif #endif return *this; } -size_t thread::attributes::stack_size() const +size_t thread::attributes::get_stack_size() const { #if defined(BOOST_HAS_WINTHREADS) return m_stacksize; #elif defined(BOOST_HAS_PTHREADS) +# if defined(_POSIX_THREAD_ATTR_STACKSIZE) size_t size; int res = 0; res = pthread_attr_getstacksize(&m_attr, &size); assert(res == 0); return size; +# else + throw unsupported_thread_option(ENOTSUP); +# endif #endif } -#endif // BOOST_THREAD_ATTRIBUTES_STACKSIZE - -#if defined(BOOST_THREAD_ATTRIBUTES_STACKADDR) - -thread::attributes& thread::attributes::stack_address(void* addr) +thread::attributes& thread::attributes::set_stack_address(void* addr) { -#if defined(BOOST_HAS_PTHREADS) +#if defined(BOOST_HAS_WINTHREADS) + throw unsupported_thread_option(); +#elif defined(BOOST_HAS_PTHREADS) +# if defined(_POSIX_THREAD_ATTR_STACKADDR) int res = 0; res = pthread_attr_setstackaddr(&m_attr, addr); assert(res == 0); +# else + throw unsupported_thread_option(ENOTSUP); +# endif #endif return *this; } -void* thread::attributes::stack_address() const +void* thread::attributes::get_stack_address() const { -#if defined(BOOST_HAS_PTHREADS) +#if defined(BOOST_HAS_WINTHREADS) + throw unsupported_thread_option(); +#elif defined(BOOST_HAS_PTHREADS) +# if defined(_POSIX_THREAD_ATTR_STACKADDR) void* addr; int res = 0; res = pthread_attr_getstackaddr(&m_attr, &addr); assert(res == 0); return addr; +# else + throw unsupported_thread_option(ENOTSUP); +# endif #endif } -#endif // BOOST_THREAD_ATTRIBUTES_STACKADDR - -#if defined(BOOST_THREAD_PRIORITY_SCHEDULING) - thread::attributes& thread::attributes::inherit_scheduling(bool inherit) { #if defined(BOOST_HAS_WINTHREADS) m_schedinherit = inherit; #elif defined(BOOST_HAS_PTHREADS) +# if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) int res = 0; res = pthread_attr_setinheritsched(&m_attr, inherit ? PTHREAD_INHERIT_SCHED : PTHREAD_EXPLICIT_SCHED); if (res == ENOTSUP) - throw std::invalid_argument("inherit"); + throw invalid_thread_argument(res); assert(res == 0); +# else + throw unsupported_thread_option(ENOTSUP); +# endif #endif return *this; } @@ -443,65 +467,70 @@ bool thread::attributes::inherit_scheduling() const #if defined(BOOST_HAS_WINTHREADS) return m_schedinherit; #elif defined (BOOST_HAS_PTHREADS) +# if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) int inherit = 0; int res = 0; res = pthread_attr_getinheritsched(&m_attr, &inherit); assert(res == 0); return inherit == PTHREAD_INHERIT_SCHED; +# else + throw unsupported_thread_option(ENOTSUP); +# endif #endif } -thread::attributes& thread::attributes::scheduling_parameter(const sched_param& param) -{ -#if defined(BOOST_HAS_WINTHREADS) - m_schedparam = param; -#elif defined(BOOST_HAS_PTHREADS) - int res = 0; - res = pthread_attr_setschedparam(&m_attr, ¶m); - if (res == EINVAL || res == ENOTSUP) - throw std::invalid_argument("param"); -#endif - return *this; -} - -sched_param thread::attributes::scheduling_parameter() const -{ -#if defined(BOOST_HAS_WINTHREADS) - return m_schedparam; -#elif defined(BOOST_HAS_PTHREADS) - sched_param param; - int res = 0; - res = pthread_attr_getschedparam(&m_attr, ¶m); - assert(res == 0); - return param; -#endif -} - -thread::attributes& thread::attributes::scheduling_policy(int policy) +thread::attributes& thread::attributes::set_schedule(int policy, const sched_param& param) { #if defined(BOOST_HAS_WINTHREADS) if (policy != sched_other) - throw std::invalid_argument("policy"); + throw unsupported_thread_option(); + if (param.priority < THREAD_PRIORITY_LOWEST || param.priority > THREAD_PRIORITY_HIGHEST) + throw invalid_thread_argument(); + m_schedparam = param; #elif defined(BOOST_HAS_PTHREADS) +# if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) int res = 0; res = pthread_attr_setschedpolicy(&m_attr, policy); + if (res == EINVAL) + throw invalid_thread_argument(res); if (res == ENOTSUP) - throw std::invalid_argument("policy"); + throw unsupported_thread_option(res); assert(res); + res = pthread_attr_setschedparam(&m_attr, ¶m); + // This one leaves me puzzled. POSIX clearly indicates this can return EINVAL + // if the sched_param supplied is invalid. But you don't know if it's invalid + // unless you know what policy it's meant for. This leaves us with a chicken + // and the egg dillema, but I'm going to assume we should set the policy first + // (which won't return EINVAL based on current parameter), then we set the + // parameter, which may return EINVAL if the current policy indicates so. + // Big assumption... does anyone know the definative answer? + if (res == EINVAL) + throw invalid_thread_argument(res); + if (res == ENOTSUP) + throw unsupported_thread_option(res); + assert(res); +# else + throw unsupported_thread_option(ENOTSUP); +# endif #endif return *this; } -int thread::attributes::scheduling_policy() const +void thread::attributes::get_schedule(int& policy, sched_param& param) { #if defined(BOOST_HAS_WINTHREADS) - return sched_other; + policy = sched_other; + param = m_schedparam; #elif defined(BOOST_HAS_PTHREADS) - int policy = 0; +# if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) int res = 0; res = pthread_attr_getschedpolicy(&m_attr, &policy); assert(res == 0); - return policy; + res = pthread_attr_getschedparam(&m_attr, ¶m); + assert(res == 0); +# else + throw unsupported_thread_option(ENOTSUP); +# endif #endif } @@ -509,13 +538,19 @@ thread::attributes& thread::attributes::scope(int scope) { #if defined(BOOST_HAS_WINTHREADS) if (scope != scope_system) - throw std::invalid_argument("scope"); + throw invalid_thread_argument(); #elif defined(BOOST_HAS_PTHREADS) +# if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) int res = 0; res = pthread_attr_setscope(&m_attr, scope); - if (res == EINVAL || res == ENOTSUP) - throw std::invalid_argument("scope"); + if (res == EINVAL) + throw invalid_thread_argument(res); + if (res == ENOTSUP) + throw unsupported_thread_option(res); assert(res == 0); +# else + throw unsupported_thread_option(ENOTSUP); +# endif #endif return *this; } @@ -525,15 +560,17 @@ int thread::attributes::scope() const #if defined(BOOST_HAS_WINTHREADS) return scope_system; #elif defined(BOOST_HAS_PTHREADS) +# if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) int scope = 0; int res = 0; res = pthread_attr_getscope(&m_attr, &scope); return scope; +# else + throw unsupported_thread_option(ENOTSUP); +# endif #endif } -#endif // BOOST_THREAD_PRIORITY_SCHEDULING - thread::thread() : m_handle(0) { @@ -575,7 +612,7 @@ thread::thread(const function0& threadfunc, attributes attr) pthread_t t; res = pthread_create(&t, &attr.m_attr, &thread_proxy, param.get()); if (res != 0) - throw thread_resource_error(); + throw thread_resource_error(res); #elif defined(BOOST_HAS_MPTASKS) threads::mac::detail::thread_init(); threads::mac::detail::create_singletons(); @@ -585,7 +622,8 @@ thread::thread(const function0& threadfunc, attributes attr) m_pTaskID = kInvalidID; lStatus = MPCreateQueue(&m_pJoinQueueID); - if(lStatus != noErr) throw thread_resource_error(); + if (lStatus != noErr) + throw thread_resource_error(); lStatus = MPCreateTask(&thread_proxy, param.get(), 0UL, m_pJoinQueueID, NULL, NULL, 0UL, &m_pTaskID); @@ -651,8 +689,6 @@ void thread::test_cancel() self.m_handle->test_cancel(); } -#if defined(BOOST_THREAD_PRIORITY_SCHEDULING) - void thread::set_scheduling_parameter(int policy, const sched_param& param) { m_handle->set_scheduling_parameter(policy, param); @@ -667,9 +703,11 @@ int thread::max_priority(int policy) { #if defined(BOOST_HAS_WINTHREADS) if (policy != sched_other) - throw std::invalid_argument("policy"); + throw invalid_thread_argument(); return THREAD_PRIORITY_HIGHEST; #elif defined(BOOST_HAS_PTHREADS) +# if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) +# endif #endif return 0; } @@ -678,15 +716,15 @@ int thread::min_priority(int policy) { #if defined(BOOST_HAS_WINTHREADS) if (policy != sched_other) - throw std::invalid_argument("policy"); + throw invalid_thread_argument(); return THREAD_PRIORITY_LOWEST; #elif defined(BOOST_HAS_PTHREADS) +# if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) +# endif #endif return 0; } -#endif // BOOST_THREAD_PRIORITY_SCHEDULING - void thread::sleep(const xtime& xt) { for (;;) @@ -765,6 +803,16 @@ const void* thread::id() const return m_handle->id(); } +#if defined(BOOST_HAS_WINTHREADS) +const int thread::stack_min = 0; +#elif defined(BOOST_HAS_PTHREADS) +# if defined(PTHREAD_STACK_MIN) +const int thread::stack_min = PTHREAD_STACK_MIN; +# else +const int thread::stack_min = 0; +# endif +#endif + thread_group::thread_group() { }