|
Boost-Commit : |
From: anthony_at_[hidden]
Date: 2007-10-24 11:39:15
Author: anthonyw
Date: 2007-10-24 11:39:14 EDT (Wed, 24 Oct 2007)
New Revision: 40424
URL: http://svn.boost.org/trac/boost/changeset/40424
Log:
updated pthreads code to support move and multiple joins
Text files modified:
trunk/boost/thread/pthread/condition_variable.hpp | 5
trunk/boost/thread/pthread/thread.hpp | 199 ++++++++++++++++-
trunk/boost/thread/win32/thread.hpp | 8
trunk/libs/thread/src/pthread/thread.cpp | 444 +++++++++++++++++++++++++--------------
trunk/libs/thread/src/pthread/tss.cpp | 59 -----
trunk/libs/thread/src/win32/thread.cpp | 6
6 files changed, 474 insertions(+), 247 deletions(-)
Modified: trunk/boost/thread/pthread/condition_variable.hpp
==============================================================================
--- trunk/boost/thread/pthread/condition_variable.hpp (original)
+++ trunk/boost/thread/pthread/condition_variable.hpp 2007-10-24 11:39:14 EDT (Wed, 24 Oct 2007)
@@ -1,5 +1,5 @@
-#ifndef BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP
-#define BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP
+#ifndef BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP
+#define BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP
// 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)
@@ -9,7 +9,6 @@
#include <limits.h>
#include <boost/assert.hpp>
#include <algorithm>
-#include <boost/thread/thread.hpp>
#include <boost/thread/thread_time.hpp>
#include <pthread.h>
#include "timespec.hpp"
Modified: trunk/boost/thread/pthread/thread.hpp
==============================================================================
--- trunk/boost/thread/pthread/thread.hpp (original)
+++ trunk/boost/thread/pthread/thread.hpp 2007-10-24 11:39:14 EDT (Wed, 24 Oct 2007)
@@ -1,3 +1,5 @@
+#ifndef BOOST_THREAD_THREAD_PTHREAD_HPP
+#define BOOST_THREAD_THREAD_PTHREAD_HPP
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright (C) 2007 Anthony Williams
@@ -5,21 +7,22 @@
// 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)
-#ifndef BOOST_THREAD_WEK070601_HPP
-#define BOOST_THREAD_WEK070601_HPP
-
#include <boost/thread/detail/config.hpp>
#include <boost/utility.hpp>
#include <boost/function.hpp>
#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
#include <list>
#include <memory>
#include <pthread.h>
#include <boost/optional.hpp>
+#include <boost/thread/detail/move.hpp>
+#include <boost/shared_ptr.hpp>
-namespace boost {
+namespace boost
+{
class thread;
@@ -78,40 +81,198 @@
};
}
+ class thread_cancelled
+ {};
+
+ namespace detail
+ {
+ struct thread_exit_callback_node;
+
+ struct thread_data_base
+ {
+ boost::shared_ptr<thread_data_base> self;
+ pthread_t thread_handle;
+ boost::mutex done_mutex;
+ boost::condition_variable done_condition;
+ bool done;
+ bool join_started;
+ bool joined;
+ boost::detail::thread_exit_callback_node* thread_exit_callbacks;
+ bool cancel_enabled;
+
+ thread_data_base():
+ done(false),join_started(false),joined(false),
+ thread_exit_callbacks(0),
+ cancel_enabled(true)
+ {}
+ virtual ~thread_data_base()
+ {}
+
+ virtual void run()=0;
+ };
+ }
+
struct xtime;
- class BOOST_THREAD_DECL thread : private noncopyable
+ class BOOST_THREAD_DECL thread
{
+ private:
+ thread(thread&);
+ thread& operator=(thread&);
+
+ template<typename F>
+ struct thread_data:
+ detail::thread_data_base
+ {
+ F f;
+
+ thread_data(F f_):
+ f(f_)
+ {}
+ thread_data(boost::move_t<F> f_):
+ f(f_)
+ {}
+
+ void run()
+ {
+ f();
+ }
+ };
+
+ mutable boost::mutex thread_info_mutex;
+ boost::shared_ptr<detail::thread_data_base> thread_info;
+
+ void start_thread();
+
+ explicit thread(boost::shared_ptr<detail::thread_data_base> data);
+
+ boost::shared_ptr<detail::thread_data_base> get_thread_info() const;
+
public:
thread();
- explicit thread(const function0<void>& threadfunc);
~thread();
+
+ template <class F>
+ explicit thread(F f):
+ thread_info(new thread_data<F>(f))
+ {
+ start_thread();
+ }
+ template <class F>
+ explicit thread(boost::move_t<F> f):
+ thread_info(new thread_data<F>(f))
+ {
+ start_thread();
+ }
- bool operator==(const thread& other) const;
- bool operator!=(const thread& other) const;
+ explicit thread(boost::move_t<thread> x);
+ thread& operator=(boost::move_t<thread> x);
+ operator boost::move_t<thread>();
+ boost::move_t<thread> move();
+ void swap(thread& x);
+
+ typedef detail::thread_id id;
+
+ id get_id() const;
+
+ bool joinable() const;
void join();
+ void detach();
- static void sleep(const xtime& xt);
+ static unsigned hardware_concurrency();
+
+ // backwards compatibility
+ bool operator==(const thread& other) const;
+ bool operator!=(const thread& other) const;
+
+ static void sleep(const system_time& xt);
static void yield();
- typedef detail::thread_id id;
-
- id get_id() const
- {
- return m_id;
- }
+ // extensions
+ class cancel_handle;
+ cancel_handle get_cancel_handle() const;
+ void cancel();
+ bool cancellation_requested() const;
- private:
- id m_id;
- bool m_joinable;
+ static thread self();
};
namespace this_thread
{
+ class disable_cancellation
+ {
+ disable_cancellation(const disable_cancellation&);
+ disable_cancellation& operator=(const disable_cancellation&);
+
+ bool cancel_was_enabled;
+ friend class enable_cancellation;
+ public:
+ disable_cancellation();
+ ~disable_cancellation();
+ };
+
+ class enable_cancellation
+ {
+ enable_cancellation(const enable_cancellation&);
+ enable_cancellation& operator=(const enable_cancellation&);
+ public:
+ explicit enable_cancellation(disable_cancellation& d);
+ ~enable_cancellation();
+ };
+
inline thread::id get_id()
{
return thread::id(pthread_self());
}
+
+ void BOOST_THREAD_DECL cancellation_point();
+ bool BOOST_THREAD_DECL cancellation_enabled();
+ bool BOOST_THREAD_DECL cancellation_requested();
+
+ void BOOST_THREAD_DECL yield();
+ template<typename TimeDuration>
+ void sleep(TimeDuration const& rel_time)
+ {
+ thread::sleep(get_system_time()+rel_time);
+ }
+ }
+
+ namespace detail
+ {
+ struct thread_exit_function_base
+ {
+ virtual ~thread_exit_function_base()
+ {}
+ virtual void operator()() const=0;
+ };
+
+ template<typename F>
+ struct thread_exit_function:
+ thread_exit_function_base
+ {
+ F f;
+
+ thread_exit_function(F f_):
+ f(f_)
+ {}
+
+ void operator()() const
+ {
+ f();
+ }
+ };
+
+ void add_thread_exit_function(thread_exit_function_base*);
+ }
+
+ namespace this_thread
+ {
+ template<typename F>
+ void at_thread_exit(F f)
+ {
+ detail::thread_exit_function_base* const thread_exit_func=new detail::thread_exit_function<F>(f);
+ detail::add_thread_exit_function(thread_exit_func);
+ }
}
class BOOST_THREAD_DECL thread_group : private noncopyable
@@ -133,4 +294,4 @@
} // namespace boost
-#endif // BOOST_THREAD_WEK070601_HPP
+#endif
Modified: trunk/boost/thread/win32/thread.hpp
==============================================================================
--- trunk/boost/thread/win32/thread.hpp (original)
+++ trunk/boost/thread/win32/thread.hpp 2007-10-24 11:39:14 EDT (Wed, 24 Oct 2007)
@@ -20,7 +20,7 @@
namespace boost
{
- class thread_canceled
+ class thread_cancelled
{};
namespace detail
@@ -105,19 +105,19 @@
~thread();
template <class F>
- thread(F f):
+ explicit thread(F f):
thread_info(detail::heap_new<thread_data<F> >(f))
{
start_thread();
}
template <class F>
- thread(boost::move_t<F> f):
+ explicit thread(boost::move_t<F> f):
thread_info(detail::heap_new<thread_data<F> >(f))
{
start_thread();
}
- thread(boost::move_t<thread> x);
+ explicit thread(boost::move_t<thread> x);
thread& operator=(boost::move_t<thread> x);
operator boost::move_t<thread>();
boost::move_t<thread> move();
Modified: trunk/libs/thread/src/pthread/thread.cpp
==============================================================================
--- trunk/libs/thread/src/pthread/thread.cpp (original)
+++ trunk/libs/thread/src/pthread/thread.cpp 2007-10-24 11:39:14 EDT (Wed, 24 Oct 2007)
@@ -11,213 +11,339 @@
#include <boost/thread/xtime.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/locks.hpp>
-#include <cassert>
+#include <boost/thread/once.hpp>
#include "timeconv.inl"
-namespace {
-
-class thread_param
+namespace boost
{
-public:
- thread_param(const boost::function0<void>& threadfunc)
- : m_threadfunc(threadfunc), m_started(false)
- {
- }
- void wait()
+ namespace detail
{
- boost::mutex::scoped_lock scoped_lock(m_mutex);
- while (!m_started)
- m_condition.wait(scoped_lock);
+ struct thread_exit_callback_node
+ {
+ boost::detail::thread_exit_function_base* func;
+ thread_exit_callback_node* next;
+ };
}
- void started()
+ namespace
{
- boost::mutex::scoped_lock scoped_lock(m_mutex);
- m_started = true;
- m_condition.notify_one();
+ boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT;
+ pthread_key_t current_thread_tls_key;
+
+ extern "C"
+ {
+ void tls_destructor(void* data)
+ {
+ boost::detail::thread_data_base* thread_info=static_cast<boost::detail::thread_data_base*>(data);
+ if(thread_info)
+ {
+ while(thread_info->thread_exit_callbacks)
+ {
+ boost::detail::thread_exit_callback_node* const current_node=thread_info->thread_exit_callbacks;
+ thread_info->thread_exit_callbacks=current_node->next;
+ if(current_node->func)
+ {
+ (*current_node->func)();
+ delete current_node->func;
+ }
+ delete current_node;
+ }
+ }
+ }
+ }
+
+
+ void create_current_thread_tls_key()
+ {
+ int const res=pthread_key_create(¤t_thread_tls_key,NULL);
+ BOOST_ASSERT(!res);
+ }
+
+ boost::detail::thread_data_base* get_current_thread_data()
+ {
+ boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
+ return (boost::detail::thread_data_base*)pthread_getspecific(current_thread_tls_key);
+ }
+
+ void set_current_thread_data(detail::thread_data_base* new_data)
+ {
+ boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
+ int const res=pthread_setspecific(current_thread_tls_key,new_data);
+ BOOST_ASSERT(!res);
+ }
+
+
+ extern "C"
+ {
+ void* thread_proxy(void* param)
+ {
+ boost::shared_ptr<boost::detail::thread_data_base> thread_info = static_cast<boost::detail::thread_data_base*>(param)->self;
+ thread_info->self.reset();
+ set_current_thread_data(thread_info.get());
+ try
+ {
+ thread_info->run();
+ }
+ catch(thread_cancelled const&)
+ {
+ }
+ catch(...)
+ {
+ std::terminate();
+ }
+
+ tls_destructor(thread_info.get());
+ set_current_thread_data(0);
+ boost::lock_guard<boost::mutex> lock(thread_info->done_mutex);
+ thread_info->done=true;
+ thread_info->done_condition.notify_all();
+ return 0;
+ }
+
+ }
}
- boost::mutex m_mutex;
- boost::condition m_condition;
- const boost::function0<void>& m_threadfunc;
- bool m_started;
-};
-} // unnamed namespace
+ thread::thread()
+ {}
-extern "C" {
- static void* thread_proxy(void* param)
+ void thread::start_thread()
{
- thread_param* p = static_cast<thread_param*>(param);
- boost::function0<void> threadfunc = p->m_threadfunc;
- p->started();
- threadfunc();
- return 0;
+ thread_info->self=thread_info;
+ int const res = pthread_create(&thread_info->thread_handle, 0, &thread_proxy, thread_info.get());
+ if (res != 0)
+ {
+ thread_info->self.reset();
+ throw thread_resource_error();
+ }
}
-}
+ thread::~thread()
+ {
+ detach();
+ }
-namespace boost {
+ bool thread::operator==(const thread& other) const
+ {
+ return get_id()==other.get_id();
+ }
-thread::thread():
- m_joinable(false)
-{}
+ bool thread::operator!=(const thread& other) const
+ {
+ return !operator==(other);
+ }
-thread::thread(const function0<void>& threadfunc)
- : m_joinable(true)
-{
- thread_param param(threadfunc);
- int res = 0;
- pthread_t m_thread;
- res = pthread_create(&m_thread, 0, &thread_proxy, ¶m);
- if (res != 0)
- throw thread_resource_error();
- m_id=m_thread;
- param.wait();
-}
+ boost::shared_ptr<detail::thread_data_base> thread::get_thread_info() const
+ {
+ lock_guard<mutex> l(thread_info_mutex);
+ return thread_info;
+ }
-thread::~thread()
-{
- if (m_joinable)
+ void thread::join()
{
- pthread_detach(*m_id.id);
+ boost::shared_ptr<detail::thread_data_base> const local_thread_info=get_thread_info();
+ if(local_thread_info)
+ {
+ bool do_join=false;
+
+ {
+ unique_lock<mutex> lock(local_thread_info->done_mutex);
+ while(!local_thread_info->done)
+ {
+ local_thread_info->done_condition.wait(lock);
+ }
+ do_join=!local_thread_info->join_started;
+
+ if(do_join)
+ {
+ local_thread_info->join_started=true;
+ }
+ else
+ {
+ while(!local_thread_info->joined)
+ {
+ local_thread_info->done_condition.wait(lock);
+ }
+ }
+ }
+ if(do_join)
+ {
+ void* result=0;
+ int const res=pthread_join(local_thread_info->thread_handle,&result);
+ BOOST_ASSERT(!res);
+ lock_guard<mutex> lock(local_thread_info->done_mutex);
+ local_thread_info->joined=true;
+ local_thread_info->done_condition.notify_all();
+ }
+
+ lock_guard<mutex> l1(thread_info_mutex);
+ if(thread_info==local_thread_info)
+ {
+ thread_info.reset();
+ }
+ }
}
-}
-bool thread::operator==(const thread& other) const
-{
- return m_id==other.m_id;
-}
+ bool thread::joinable() const
+ {
+ return get_thread_info();
+ }
-bool thread::operator!=(const thread& other) const
-{
- return !operator==(other);
-}
-void thread::join()
-{
- assert(m_joinable); //See race condition comment below
- int res = 0;
- res = pthread_join(*m_id.id, 0);
- assert(res == 0);
- // This isn't a race condition since any race that could occur would
- // have us in undefined behavior territory any way.
- m_joinable = false;
-}
+ void thread::detach()
+ {
+ boost::shared_ptr<detail::thread_data_base> local_thread_info;
+ {
+ lock_guard<mutex> l1(thread_info_mutex);
+ thread_info.swap(local_thread_info);
+ }
+
+ if(local_thread_info)
+ {
+ lock_guard<mutex> lock(local_thread_info->done_mutex);
+ if(!local_thread_info->join_started)
+ {
+ int const res=pthread_detach(local_thread_info->thread_handle);
+ BOOST_ASSERT(!res);
+ local_thread_info->join_started=true;
+ local_thread_info->joined=true;
+ }
+ }
+ }
-void thread::sleep(const xtime& xt)
-{
- for (int foo=0; foo < 5; ++foo)
+ void thread::sleep(const system_time& st)
{
+ xtime const xt=get_xtime(st);
+
+ for (int foo=0; foo < 5; ++foo)
+ {
# if defined(BOOST_HAS_PTHREAD_DELAY_NP)
- timespec ts;
- to_timespec_duration(xt, ts);
- int res = 0;
- res = pthread_delay_np(&ts);
- assert(res == 0);
+ timespec ts;
+ to_timespec_duration(xt, ts);
+ int res = 0;
+ res = pthread_delay_np(&ts);
+ BOOST_ASSERT(res == 0);
# elif defined(BOOST_HAS_NANOSLEEP)
- timespec ts;
- to_timespec_duration(xt, ts);
+ timespec ts;
+ to_timespec_duration(xt, ts);
- // nanosleep takes a timespec that is an offset, not
- // an absolute time.
- nanosleep(&ts, 0);
+ // nanosleep takes a timespec that is an offset, not
+ // an absolute time.
+ nanosleep(&ts, 0);
# else
- mutex mx;
- mutex::scoped_lock lock(mx);
- condition cond;
- cond.timed_wait(lock, xt);
+ mutex mx;
+ mutex::scoped_lock lock(mx);
+ condition cond;
+ cond.timed_wait(lock, xt);
# endif
- xtime cur;
- xtime_get(&cur, TIME_UTC);
- if (xtime_cmp(xt, cur) <= 0)
- return;
+ xtime cur;
+ xtime_get(&cur, TIME_UTC);
+ if (xtime_cmp(xt, cur) <= 0)
+ return;
+ }
}
-}
-void thread::yield()
-{
+ void thread::yield()
+ {
# if defined(BOOST_HAS_SCHED_YIELD)
- int res = 0;
- res = sched_yield();
- assert(res == 0);
+ int res = 0;
+ res = sched_yield();
+ BOOST_ASSERT(res == 0);
# elif defined(BOOST_HAS_PTHREAD_YIELD)
- int res = 0;
- res = pthread_yield();
- assert(res == 0);
+ int res = 0;
+ res = pthread_yield();
+ BOOST_ASSERT(res == 0);
# else
- xtime xt;
- xtime_get(&xt, TIME_UTC);
- sleep(xt);
+ xtime xt;
+ xtime_get(&xt, TIME_UTC);
+ sleep(xt);
# endif
-}
+ }
-thread_group::thread_group()
-{
-}
+ unsigned thread::hardware_concurrency()
+ {
+ return 1;
+ }
-thread_group::~thread_group()
-{
- // We shouldn't have to scoped_lock here, since referencing this object
- // from another thread while we're deleting it in the current thread is
- // going to lead to undefined behavior any way.
- for (std::list<thread*>::iterator it = m_threads.begin();
- it != m_threads.end(); ++it)
+ thread::id thread::get_id() const
{
- delete (*it);
+ boost::shared_ptr<detail::thread_data_base> local_thread_info=get_thread_info();
+ if(local_thread_info)
+ {
+ return id(local_thread_info->thread_handle);
+ }
+ else
+ {
+ return id();
+ }
}
-}
-thread* thread_group::create_thread(const function0<void>& threadfunc)
-{
- // No scoped_lock required here since the only "shared data" that's
- // modified here occurs inside add_thread which does scoped_lock.
- std::auto_ptr<thread> thrd(new thread(threadfunc));
- add_thread(thrd.get());
- return thrd.release();
-}
+ thread_group::thread_group()
+ {
+ }
-void thread_group::add_thread(thread* thrd)
-{
- mutex::scoped_lock scoped_lock(m_mutex);
+ thread_group::~thread_group()
+ {
+ // We shouldn't have to scoped_lock here, since referencing this object
+ // from another thread while we're deleting it in the current thread is
+ // going to lead to undefined behavior any way.
+ for (std::list<thread*>::iterator it = m_threads.begin();
+ it != m_threads.end(); ++it)
+ {
+ delete (*it);
+ }
+ }
- // For now we'll simply ignore requests to add a thread object multiple
- // times. Should we consider this an error and either throw or return an
- // error value?
- std::list<thread*>::iterator it = std::find(m_threads.begin(),
- m_threads.end(), thrd);
- assert(it == m_threads.end());
- if (it == m_threads.end())
- m_threads.push_back(thrd);
-}
+ thread* thread_group::create_thread(const function0<void>& threadfunc)
+ {
+ // No scoped_lock required here since the only "shared data" that's
+ // modified here occurs inside add_thread which does scoped_lock.
+ std::auto_ptr<thread> thrd(new thread(threadfunc));
+ add_thread(thrd.get());
+ return thrd.release();
+ }
-void thread_group::remove_thread(thread* thrd)
-{
- mutex::scoped_lock scoped_lock(m_mutex);
+ void thread_group::add_thread(thread* thrd)
+ {
+ mutex::scoped_lock scoped_lock(m_mutex);
- // For now we'll simply ignore requests to remove a thread object that's
- // not in the group. Should we consider this an error and either throw or
- // return an error value?
- std::list<thread*>::iterator it = std::find(m_threads.begin(),
- m_threads.end(), thrd);
- assert(it != m_threads.end());
- if (it != m_threads.end())
- m_threads.erase(it);
-}
+ // For now we'll simply ignore requests to add a thread object multiple
+ // times. Should we consider this an error and either throw or return an
+ // error value?
+ std::list<thread*>::iterator it = std::find(m_threads.begin(),
+ m_threads.end(), thrd);
+ BOOST_ASSERT(it == m_threads.end());
+ if (it == m_threads.end())
+ m_threads.push_back(thrd);
+ }
-void thread_group::join_all()
-{
- mutex::scoped_lock scoped_lock(m_mutex);
- for (std::list<thread*>::iterator it = m_threads.begin();
- it != m_threads.end(); ++it)
+ void thread_group::remove_thread(thread* thrd)
{
- (*it)->join();
+ mutex::scoped_lock scoped_lock(m_mutex);
+
+ // For now we'll simply ignore requests to remove a thread object that's
+ // not in the group. Should we consider this an error and either throw or
+ // return an error value?
+ std::list<thread*>::iterator it = std::find(m_threads.begin(),
+ m_threads.end(), thrd);
+ BOOST_ASSERT(it != m_threads.end());
+ if (it != m_threads.end())
+ m_threads.erase(it);
}
-}
-int thread_group::size() const
-{
+ void thread_group::join_all()
+ {
+ mutex::scoped_lock scoped_lock(m_mutex);
+ for (std::list<thread*>::iterator it = m_threads.begin();
+ it != m_threads.end(); ++it)
+ {
+ (*it)->join();
+ }
+ }
+
+ int thread_group::size() const
+ {
return m_threads.size();
-}
+ }
-} // namespace boost
+}
Modified: trunk/libs/thread/src/pthread/tss.cpp
==============================================================================
--- trunk/libs/thread/src/pthread/tss.cpp (original)
+++ trunk/libs/thread/src/pthread/tss.cpp 2007-10-24 11:39:14 EDT (Wed, 24 Oct 2007)
@@ -30,13 +30,7 @@
boost::once_flag tss_data_once = BOOST_ONCE_INIT;
boost::mutex* tss_data_mutex = 0;
tss_data_cleanup_handlers_type* tss_data_cleanup_handlers = 0;
-#if defined(BOOST_HAS_WINTHREADS)
- DWORD tss_data_native_key=TLS_OUT_OF_INDEXES;
-#elif defined(BOOST_HAS_PTHREADS)
pthread_key_t tss_data_native_key;
-#elif defined(BOOST_HAS_MPTASKS)
- TaskStorageIndex tss_data_native_key;
-#endif
int tss_data_use = 0;
void tss_data_inc_use(boost::mutex::scoped_lock& lk)
@@ -58,15 +52,7 @@
lk.unlock();
delete tss_data_mutex;
tss_data_mutex = 0;
-#if defined(BOOST_HAS_WINTHREADS)
- TlsFree(tss_data_native_key);
- tss_data_native_key=TLS_OUT_OF_INDEXES;
-#elif defined(BOOST_HAS_PTHREADS)
pthread_key_delete(tss_data_native_key);
-#elif defined(BOOST_HAS_MPTASKS)
- // Don't know what to put here.
- // But MPTASKS isn't currently maintained anyways...
-#endif
}
}
@@ -79,9 +65,6 @@
(*(*tss_data_cleanup_handlers)[i])((*slots)[i]);
(*slots)[i] = 0;
}
-#if defined(BOOST_HAS_WINTHREADS)
- TlsSetValue(tss_data_native_key,0);
-#endif
tss_data_dec_use(lock);
delete slots;
}
@@ -95,23 +78,9 @@
if (temp_mutex.get() == 0)
throw boost::thread_resource_error();
-#if defined(BOOST_HAS_WINTHREADS)
- //Force the cleanup implementation library to be linked in
- tss_cleanup_implemented();
-
- //Allocate tls slot
- tss_data_native_key = TlsAlloc();
- if (tss_data_native_key == TLS_OUT_OF_INDEXES)
- return;
-#elif defined(BOOST_HAS_PTHREADS)
int res = pthread_key_create(&tss_data_native_key, &cleanup_slots);
if (res != 0)
return;
-#elif defined(BOOST_HAS_MPTASKS)
- OSStatus status = MPAllocateTaskStorageIndex(&tss_data_native_key);
- if (status != noErr)
- return;
-#endif
// The life time of cleanup handlers and mutex is beeing
// managed by a reference counting technique.
@@ -123,48 +92,20 @@
tss_data_mutex = temp_mutex.release();
}
-#if defined(BOOST_HAS_WINTHREADS)
-tss_slots* get_slots(bool alloc);
-
-void __cdecl tss_thread_exit()
-{
- tss_slots* slots = get_slots(false);
- if (slots)
- cleanup_slots(slots);
-}
-#endif
tss_slots* get_slots(bool alloc)
{
tss_slots* slots = 0;
-#if defined(BOOST_HAS_WINTHREADS)
- slots = static_cast<tss_slots*>(
- TlsGetValue(tss_data_native_key));
-#elif defined(BOOST_HAS_PTHREADS)
slots = static_cast<tss_slots*>(
pthread_getspecific(tss_data_native_key));
-#elif defined(BOOST_HAS_MPTASKS)
- slots = static_cast<tss_slots*>(
- MPGetTaskStorageValue(tss_data_native_key));
-#endif
if (slots == 0 && alloc)
{
std::auto_ptr<tss_slots> temp(new tss_slots);
-#if defined(BOOST_HAS_WINTHREADS)
- if (at_thread_exit(&tss_thread_exit) == -1)
- return 0;
- if (!TlsSetValue(tss_data_native_key, temp.get()))
- return 0;
-#elif defined(BOOST_HAS_PTHREADS)
if (pthread_setspecific(tss_data_native_key, temp.get()) != 0)
return 0;
-#elif defined(BOOST_HAS_MPTASKS)
- if (MPSetTaskStorageValue(tss_data_native_key, temp.get()) != noErr)
- return 0;
-#endif
{
boost::mutex::scoped_lock lock(*tss_data_mutex);
tss_data_inc_use(lock);
Modified: trunk/libs/thread/src/win32/thread.cpp
==============================================================================
--- trunk/libs/thread/src/win32/thread.cpp (original)
+++ trunk/libs/thread/src/win32/thread.cpp 2007-10-24 11:39:14 EDT (Wed, 24 Oct 2007)
@@ -88,7 +88,7 @@
{
thread_info->run();
}
- catch(thread_canceled const&)
+ catch(thread_cancelled const&)
{
}
catch(...)
@@ -302,7 +302,7 @@
else if(notified_index==cancel_index)
{
detail::win32::ResetEvent(get_current_thread_data()->cancel_handle);
- throw thread_canceled();
+ throw thread_cancelled();
}
}
else
@@ -322,7 +322,7 @@
if(cancellation_enabled() && cancellation_requested())
{
detail::win32::ResetEvent(get_current_thread_data()->cancel_handle);
- throw thread_canceled();
+ throw thread_cancelled();
}
}
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