|
Boost-Commit : |
From: anthony_at_[hidden]
Date: 2007-10-23 04:57:20
Author: anthonyw
Date: 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
New Revision: 40348
URL: http://svn.boost.org/trac/boost/changeset/40348
Log:
platform split for pthread and win32 builds so can use pthread-win32 library on Windows with <thrd-api>pthread feature; new C++0x-alike thread class interface on win32.
Added:
trunk/boost/thread/pthread/thread.hpp (contents, props changed)
trunk/boost/thread/win32/thread.hpp (contents, props changed)
trunk/boost/thread/win32/thread_heap_alloc.hpp (contents, props changed)
trunk/libs/thread/src/pthread/
trunk/libs/thread/src/pthread/exceptions.cpp
- copied unchanged from r40277, /trunk/libs/thread/src/exceptions.cpp
trunk/libs/thread/src/pthread/thread.cpp
- copied, changed from r40277, /trunk/libs/thread/src/thread.cpp
trunk/libs/thread/src/pthread/timeconv.inl (props changed)
- copied unchanged from r40277, /trunk/libs/thread/src/timeconv.inl
trunk/libs/thread/src/pthread/tss.cpp
- copied unchanged from r40277, /trunk/libs/thread/src/tss.cpp
trunk/libs/thread/src/pthread/xtime.cpp
- copied unchanged from r40277, /trunk/libs/thread/src/xtime.cpp
trunk/libs/thread/src/win32/
trunk/libs/thread/src/win32/exceptions.cpp
- copied unchanged from r40277, /trunk/libs/thread/src/exceptions.cpp
trunk/libs/thread/src/win32/thread.cpp
- copied, changed from r40277, /trunk/libs/thread/src/thread.cpp
trunk/libs/thread/src/win32/timeconv.inl (props changed)
- copied unchanged from r40277, /trunk/libs/thread/src/timeconv.inl
trunk/libs/thread/src/win32/tss.cpp
- copied unchanged from r40277, /trunk/libs/thread/src/tss.cpp
trunk/libs/thread/src/win32/tss_dll.cpp
- copied unchanged from r40277, /trunk/libs/thread/src/tss_dll.cpp
trunk/libs/thread/src/win32/tss_hooks.cpp
- copied unchanged from r40277, /trunk/libs/thread/src/tss_hooks.cpp
trunk/libs/thread/src/win32/tss_pe.cpp
- copied unchanged from r40277, /trunk/libs/thread/src/tss_pe.cpp
trunk/libs/thread/src/win32/xtime.cpp
- copied unchanged from r40277, /trunk/libs/thread/src/xtime.cpp
Removed:
trunk/libs/thread/src/exceptions.cpp
trunk/libs/thread/src/mac/
trunk/libs/thread/src/thread.cpp
trunk/libs/thread/src/timeconv.inl
trunk/libs/thread/src/tss.cpp
trunk/libs/thread/src/tss_dll.cpp
trunk/libs/thread/src/tss_hooks.cpp
trunk/libs/thread/src/tss_pe.cpp
trunk/libs/thread/src/xtime.cpp
Text files modified:
trunk/boost/thread/pthread/mutex.hpp | 2
trunk/boost/thread/pthread/recursive_mutex.hpp | 2
trunk/boost/thread/thread.hpp | 95 ----
trunk/boost/thread/win32/thread_primitives.hpp | 19
trunk/libs/thread/build/Jamfile.v2 | 106 ++++-
trunk/libs/thread/src/pthread/thread.cpp | 157 --------
trunk/libs/thread/src/win32/thread.cpp | 725 ++++++++++++++++++++++-----------------
trunk/libs/thread/test/test_shared_mutex.cpp | 34 +
trunk/libs/thread/test/test_thread.cpp | 26
9 files changed, 553 insertions(+), 613 deletions(-)
Modified: trunk/boost/thread/pthread/mutex.hpp
==============================================================================
--- trunk/boost/thread/pthread/mutex.hpp (original)
+++ trunk/boost/thread/pthread/mutex.hpp 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
@@ -11,7 +11,9 @@
#include <boost/thread/locks.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/assert.hpp>
+#ifndef WIN32
#include <unistd.h>
+#endif
#include <errno.h>
#include "timespec.hpp"
#include "pthread_mutex_scoped_lock.hpp"
Modified: trunk/boost/thread/pthread/recursive_mutex.hpp
==============================================================================
--- trunk/boost/thread/pthread/recursive_mutex.hpp (original)
+++ trunk/boost/thread/pthread/recursive_mutex.hpp 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
@@ -11,7 +11,9 @@
#include <boost/thread/locks.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/assert.hpp>
+#ifndef WIN32
#include <unistd.h>
+#endif
#include <boost/date_time/posix_time/conversion.hpp>
#include <errno.h>
#include "timespec.hpp"
Added: trunk/boost/thread/pthread/thread.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/thread/pthread/thread.hpp 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
@@ -0,0 +1,136 @@
+// Copyright (C) 2001-2003
+// William E. Kempf
+// Copyright (C) 2007 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)
+
+#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 <list>
+#include <memory>
+
+#include <pthread.h>
+#include <boost/optional.hpp>
+
+namespace boost {
+
+ class thread;
+
+ namespace detail
+ {
+ class thread_id;
+ }
+
+ namespace this_thread
+ {
+ detail::thread_id get_id();
+ }
+
+ namespace detail
+ {
+ class thread_id
+ {
+ boost::optional<pthread_t> id;
+
+ friend class boost::thread;
+
+ friend thread_id this_thread::get_id();
+
+ thread_id(pthread_t id_):
+ id(id_)
+ {}
+
+ public:
+ thread_id()
+ {}
+
+ bool operator==(const thread_id& y) const
+ {
+ return (id && y.id) && (pthread_equal(*id,*y.id)!=0);
+ }
+
+ bool operator!=(const thread_id& y) const
+ {
+ return !(*this==y);
+ }
+
+ template<class charT, class traits>
+ friend std::basic_ostream<charT, traits>&
+ operator<<(std::basic_ostream<charT, traits>& os, const thread_id& x)
+ {
+ if(x.id)
+ {
+ return os<<*x.id;
+ }
+ else
+ {
+ return os<<"{Not-any-thread}";
+ }
+ }
+
+ };
+ }
+
+ struct xtime;
+ class BOOST_THREAD_DECL thread : private noncopyable
+ {
+ public:
+ thread();
+ explicit thread(const function0<void>& threadfunc);
+ ~thread();
+
+ bool operator==(const thread& other) const;
+ bool operator!=(const thread& other) const;
+
+ void join();
+
+ static void sleep(const xtime& xt);
+ static void yield();
+
+ typedef detail::thread_id id;
+
+ id get_id() const
+ {
+ return m_id;
+ }
+
+ private:
+ id m_id;
+ bool m_joinable;
+ };
+
+ namespace this_thread
+ {
+ inline thread::id get_id()
+ {
+ return thread::id(pthread_self());
+ }
+ }
+
+ class BOOST_THREAD_DECL thread_group : private noncopyable
+ {
+ public:
+ thread_group();
+ ~thread_group();
+
+ thread* create_thread(const function0<void>& threadfunc);
+ void add_thread(thread* thrd);
+ void remove_thread(thread* thrd);
+ void join_all();
+ int size() const;
+
+ private:
+ std::list<thread*> m_threads;
+ mutex m_mutex;
+ };
+} // namespace boost
+
+
+#endif // BOOST_THREAD_WEK070601_HPP
Modified: trunk/boost/thread/thread.hpp
==============================================================================
--- trunk/boost/thread/thread.hpp (original)
+++ trunk/boost/thread/thread.hpp 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
@@ -1,88 +1,15 @@
-// Copyright (C) 2001-2003
-// William E. Kempf
-//
-// 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 <list>
-#include <memory>
-
-#if defined(BOOST_HAS_PTHREADS)
-# include <pthread.h>
-#elif defined(BOOST_HAS_MPTASKS)
-# include <Multiprocessing.h>
-#endif
-
-namespace boost {
-
-struct xtime;
-// disable warnings about non dll import
-// see: http://www.boost.org/more/separate_compilation.html#dlls
-#ifdef BOOST_MSVC
-# pragma warning(push)
-# pragma warning(disable: 4251 4231 4660 4275)
-#endif
-class BOOST_THREAD_DECL thread : private noncopyable
-{
-public:
- thread();
- explicit thread(const function0<void>& threadfunc);
- ~thread();
+#ifndef BOOST_THREAD_THREAD_HPP
+#define BOOST_THREAD_THREAD_HPP
- bool operator==(const thread& other) const;
- bool operator!=(const thread& other) const;
-
- void join();
-
- static void sleep(const xtime& xt);
- static void yield();
-
-private:
-#if defined(BOOST_HAS_WINTHREADS)
- void* m_thread;
- unsigned int m_id;
-#elif defined(BOOST_HAS_PTHREADS)
-private:
- pthread_t m_thread;
-#elif defined(BOOST_HAS_MPTASKS)
- MPQueueID m_pJoinQueueID;
- MPTaskID m_pTaskID;
-#endif
- bool m_joinable;
-};
-
-class BOOST_THREAD_DECL thread_group : private noncopyable
-{
-public:
- thread_group();
- ~thread_group();
+// thread.hpp
+//
+// (C) Copyright 2007 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)
- thread* create_thread(const function0<void>& threadfunc);
- void add_thread(thread* thrd);
- void remove_thread(thread* thrd);
- void join_all();
- int size() const;
+#include <boost/thread/detail/platform.hpp>
+#include BOOST_THREAD_PLATFORM(thread.hpp)
-private:
- std::list<thread*> m_threads;
- mutex m_mutex;
-};
-#ifdef BOOST_MSVC
-# pragma warning(pop)
#endif
-} // namespace boost
-
-// Change Log:
-// 8 Feb 01 WEKEMPF Initial version.
-// 1 Jun 01 WEKEMPF Added boost::thread initial implementation.
-// 3 Jul 01 WEKEMPF Redesigned boost::thread to be noncopyable.
-
-#endif // BOOST_THREAD_WEK070601_HPP
Added: trunk/boost/thread/win32/thread.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/thread/win32/thread.hpp 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
@@ -0,0 +1,413 @@
+#ifndef BOOST_THREAD_THREAD_WIN32_HPP
+#define BOOST_THREAD_THREAD_WIN32_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)
+// (C) Copyright 2007 Anthony Williams
+
+#include <exception>
+#include <boost/thread/exceptions.hpp>
+#include <ostream>
+#include <boost/thread/detail/move.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/thread_time.hpp>
+#include "thread_primitives.hpp"
+#include "thread_heap_alloc.hpp"
+#include <boost/utility.hpp>
+#include <list>
+#include <algorithm>
+
+namespace boost
+{
+ class thread_canceled
+ {};
+
+ namespace detail
+ {
+ struct thread_exit_callback_node;
+
+ struct thread_data_base
+ {
+ long count;
+ detail::win32::handle_manager thread_handle;
+ detail::win32::handle_manager cancel_handle;
+ boost::detail::thread_exit_callback_node* thread_exit_callbacks;
+ bool cancel_enabled;
+ unsigned id;
+
+ thread_data_base():
+ count(0),thread_handle(detail::win32::invalid_handle_value),
+ cancel_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)),
+ thread_exit_callbacks(0),
+ cancel_enabled(true),
+ id(0)
+ {}
+ virtual ~thread_data_base()
+ {}
+
+ friend void intrusive_ptr_add_ref(thread_data_base * p)
+ {
+ BOOST_INTERLOCKED_INCREMENT(&p->count);
+ }
+
+ friend void intrusive_ptr_release(thread_data_base * p)
+ {
+ if(!BOOST_INTERLOCKED_DECREMENT(&p->count))
+ {
+ detail::heap_delete(p);
+ }
+ }
+
+ virtual void run()=0;
+ };
+ }
+
+ class BOOST_THREAD_DECL thread
+ {
+ private:
+ thread(thread&);
+ thread& operator=(thread&);
+
+ void release_handle();
+
+ 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::intrusive_ptr<detail::thread_data_base> thread_info;
+
+ static unsigned __stdcall thread_start_function(void* param);
+
+ void start_thread();
+
+ explicit thread(boost::intrusive_ptr<detail::thread_data_base> data);
+
+ boost::intrusive_ptr<detail::thread_data_base> get_thread_info() const;
+ public:
+ thread();
+ ~thread();
+
+ template <class F>
+ thread(F f):
+ thread_info(detail::heap_new<thread_data<F> >(f))
+ {
+ start_thread();
+ }
+ template <class F>
+ thread(boost::move_t<F> f):
+ thread_info(detail::heap_new<thread_data<F> >(f))
+ {
+ start_thread();
+ }
+
+ 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);
+
+ class id;
+ id get_id() const;
+
+
+ bool joinable() const;
+ void join();
+ void detach();
+
+ static unsigned hardware_concurrency();
+
+ typedef detail::win32::handle native_handle_type;
+ native_handle_type native_handle();
+
+ // backwards compatibility
+ bool operator==(const thread& other) const;
+ bool operator!=(const thread& other) const;
+
+ static void yield();
+ static void sleep(const system_time& xt);
+
+ // extensions
+ class cancel_handle;
+ cancel_handle get_cancel_handle() const;
+ void cancel();
+ bool cancellation_requested() const;
+
+ 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();
+ };
+
+ thread::id BOOST_THREAD_DECL get_id();
+
+ bool BOOST_THREAD_DECL cancellable_wait(detail::win32::handle handle_to_wait_for,unsigned long milliseconds);
+
+ void BOOST_THREAD_DECL cancellation_point();
+ bool BOOST_THREAD_DECL cancellation_enabled();
+ bool BOOST_THREAD_DECL cancellation_requested();
+ thread::cancel_handle BOOST_THREAD_DECL get_cancel_handle();
+
+ void BOOST_THREAD_DECL yield();
+ template<typename TimeDuration>
+ void sleep(TimeDuration const& rel_time)
+ {
+ cancellable_wait(detail::win32::invalid_handle_value,static_cast<unsigned long>(rel_time.total_milliseconds()));
+ }
+ }
+
+ class thread::id
+ {
+ private:
+ unsigned thread_id;
+
+ id(unsigned thread_id_):
+ thread_id(thread_id_)
+ {}
+ friend class thread;
+ friend id this_thread::get_id();
+ public:
+ id():
+ thread_id(0)
+ {}
+
+ bool operator==(const id& y) const
+ {
+ return thread_id==y.thread_id;
+ }
+
+ bool operator!=(const id& y) const
+ {
+ return thread_id!=y.thread_id;
+ }
+
+ bool operator<(const id& y) const
+ {
+ return thread_id<y.thread_id;
+ }
+
+ bool operator>(const id& y) const
+ {
+ return thread_id>y.thread_id;
+ }
+
+ bool operator<=(const id& y) const
+ {
+ return thread_id<=y.thread_id;
+ }
+
+ bool operator>=(const id& y) const
+ {
+ return thread_id>=y.thread_id;
+ }
+
+ template<class charT, class traits>
+ friend std::basic_ostream<charT, traits>&
+ operator<<(std::basic_ostream<charT, traits>& os, const id& x)
+ {
+ return os<<x.thread_id;
+ }
+ };
+
+ inline bool thread::operator==(const thread& other) const
+ {
+ return get_id()==other.get_id();
+ }
+
+ inline bool thread::operator!=(const thread& other) const
+ {
+ return get_id()!=other.get_id();
+ }
+
+ class thread::cancel_handle
+ {
+ private:
+ boost::detail::win32::handle_manager handle;
+ friend class thread;
+ friend cancel_handle this_thread::get_cancel_handle();
+
+ cancel_handle(detail::win32::handle h_):
+ handle(h_)
+ {}
+ public:
+ cancel_handle(cancel_handle const& other):
+ handle(other.handle.duplicate())
+ {}
+ cancel_handle():
+ handle(0)
+ {}
+
+ void swap(cancel_handle& other)
+ {
+ handle.swap(other.handle);
+ }
+
+ cancel_handle& operator=(cancel_handle const& other)
+ {
+ cancel_handle temp(other);
+ swap(temp);
+ return *this;
+ }
+
+ void reset()
+ {
+ handle=0;
+ }
+
+ void cancel()
+ {
+ if(handle)
+ {
+ detail::win32::SetEvent(handle);
+ }
+ }
+
+ typedef void(cancel_handle::*bool_type)();
+ operator bool_type() const
+ {
+ return handle?&cancel_handle::cancel:0;
+ }
+ };
+
+ 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=detail::heap_new<detail::thread_exit_function<F> >(f);
+ detail::add_thread_exit_function(thread_exit_func);
+ }
+ }
+
+ class thread_group:
+ private noncopyable
+ {
+ public:
+ ~thread_group()
+ {
+ for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
+ it!=end;
+ ++it)
+ {
+ delete *it;
+ }
+ }
+
+ template<typename F>
+ thread* create_thread(F threadfunc)
+ {
+ boost::lock_guard<mutex> guard(m);
+ thread* const new_thread=new thread(threadfunc);
+ threads.push_back(new_thread);
+ return new_thread;
+ }
+
+ void add_thread(thread* thrd)
+ {
+ if(thrd)
+ {
+ boost::lock_guard<mutex> guard(m);
+ threads.push_back(thrd);
+ }
+ }
+
+ void remove_thread(thread* thrd)
+ {
+ boost::lock_guard<mutex> guard(m);
+ std::list<thread*>::iterator const it=std::find(threads.begin(),threads.end(),thrd);
+ if(it!=threads.end())
+ {
+ threads.erase(it);
+ }
+ }
+
+ void join_all()
+ {
+ boost::lock_guard<mutex> guard(m);
+
+ for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
+ it!=end;
+ ++it)
+ {
+ (*it)->join();
+ }
+ }
+
+ int size() const
+ {
+ boost::lock_guard<mutex> guard(m);
+ return threads.size();
+ }
+
+ private:
+ std::list<thread*> threads;
+ mutable mutex m;
+ };
+}
+
+#endif
Added: trunk/boost/thread/win32/thread_heap_alloc.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/thread/win32/thread_heap_alloc.hpp 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
@@ -0,0 +1,105 @@
+// 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 Anthony Williams
+#ifndef THREAD_HEAP_ALLOC_HPP
+#define THREAD_HEAP_ALLOC_HPP
+#include <new>
+#include "thread_primitives.hpp"
+
+#if defined( BOOST_USE_WINDOWS_H )
+# include <windows.h>
+
+namespace boost
+{
+ namespace detail
+ {
+ namespace win32
+ {
+ using ::GetProcessHeap;
+ using ::HeapAlloc;
+ using ::HeapFree;
+ }
+ }
+}
+
+#else
+
+namespace boost
+{
+ namespace detail
+ {
+ namespace win32
+ {
+ extern "C"
+ {
+ __declspec(dllimport) handle __stdcall GetProcessHeap();
+ __declspec(dllimport) void* __stdcall HeapAlloc(handle,unsigned long,ulong_ptr);
+ __declspec(dllimport) int __stdcall HeapFree(handle,unsigned long,void*);
+ }
+ }
+ }
+}
+
+#endif
+
+namespace boost
+{
+ namespace detail
+ {
+ template<typename T>
+ T* heap_new()
+ {
+ void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,sizeof(T));
+ T* const data=new (heap_memory) T();
+ return data;
+ }
+
+ template<typename T,typename A1>
+ T* heap_new(A1 a1)
+ {
+ void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,sizeof(T));
+ T* const data=new (heap_memory) T(a1);
+ return data;
+ }
+
+ template<typename T,typename A1,typename A2>
+ T* heap_new(A1 a1,A2 a2)
+ {
+ void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,sizeof(T));
+ T* const data=new (heap_memory) T(a1,a2);
+ return data;
+ }
+
+ template<typename T>
+ void heap_delete(T* data)
+ {
+ data->~T();
+ detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,data);
+ }
+
+ template<typename T>
+ struct do_delete
+ {
+ T* data;
+
+ do_delete(T* data_):
+ data(data_)
+ {}
+
+ void operator()() const
+ {
+ detail::heap_delete(data);
+ }
+ };
+
+ template<typename T>
+ do_delete<T> make_heap_deleter(T* data)
+ {
+ return do_delete<T>(data);
+ }
+ }
+}
+
+
+#endif
Modified: trunk/boost/thread/win32/thread_primitives.hpp
==============================================================================
--- trunk/boost/thread/win32/thread_primitives.hpp (original)
+++ trunk/boost/thread/win32/thread_primitives.hpp 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
@@ -12,6 +12,7 @@
#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/thread/exceptions.hpp>
+#include <algorithm>
#if defined( BOOST_USE_WINDOWS_H )
# include <windows.h>
@@ -25,6 +26,7 @@
typedef HANDLE handle;
unsigned const infinite=INFINITE;
unsigned const timeout=WAIT_TIMEOUT;
+ handle const invalid_handle_value=INVALID_HANDLE_VALUE;
using ::CreateMutexA;
using ::CreateEventA;
@@ -42,6 +44,7 @@
using ::GetCurrentProcess;
using ::DuplicateHandle;
using ::SleepEx;
+ using ::Sleep;
using ::QueueUserAPC;
}
}
@@ -62,6 +65,7 @@
typedef void* handle;
unsigned const infinite=~0U;
unsigned const timeout=258U;
+ handle const invalid_handle_value=(handle)(-1);
extern "C"
{
@@ -79,6 +83,7 @@
__declspec(dllimport) void* __stdcall GetCurrentProcess();
__declspec(dllimport) int __stdcall DuplicateHandle(void*,void*,void*,void**,unsigned long,int,unsigned long);
__declspec(dllimport) unsigned long __stdcall SleepEx(unsigned long,int);
+ __declspec(dllimport) void __stdcall Sleep(unsigned long);
typedef void (__stdcall *queue_user_apc_callback_function)(ulong_ptr);
__declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr);
__declspec(dllimport) int __stdcall SetEvent(void*);
@@ -158,9 +163,9 @@
void cleanup()
{
- if(handle_to_manage)
+ if(handle_to_manage && handle_to_manage!=invalid_handle_value)
{
- unsigned long result=CloseHandle(handle_to_manage);
+ unsigned long const result=CloseHandle(handle_to_manage);
BOOST_ASSERT(result);
}
}
@@ -185,6 +190,16 @@
return handle_to_manage;
}
+ handle duplicate() const
+ {
+ return duplicate_handle(handle_to_manage);
+ }
+
+ void swap(handle_manager& other)
+ {
+ std::swap(handle_to_manage,other.handle_to_manage);
+ }
+
handle release()
{
handle const res=handle_to_manage;
Modified: trunk/libs/thread/build/Jamfile.v2
==============================================================================
--- trunk/libs/thread/build/Jamfile.v2 (original)
+++ trunk/libs/thread/build/Jamfile.v2 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
@@ -1,39 +1,83 @@
-# (C) Copyright Vladimir Prus, David Abrahams, Michael Stevens, Hartmut Kaiser,
-# William E Kempf 2002-2006
-# Use, modification and distribution are subject to 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)
+# Copyright 2006 Roland Schwarz.
+# Copyright 2007 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)
import os ;
-
+import feature ;
project boost/thread
- : source-location ../src
- : requirements <link>shared:<define>BOOST_THREAD_BUILD_DLL=1 <threading>multi
- : default-build <threading>multi
+ : source-location ../src
+ : requirements <threading>multi
+ <link>static:<define>BOOST_THREAD_BUILD_LIB=1
+ <link>shared:<define>BOOST_THREAD_BUILD_DLL=1
+ : default-build <threading>multi
;
-CPP_SOURCES =
-# barrier
-# condition
- exceptions
-# mutex
-# once
-# recursive_mutex
-# read_write_mutex
- thread
- tss_hooks
- tss_dll
- tss_pe
- tss
- xtime
- ;
+BOOST_PTHREAD_OPTS = <define>BOOST_THREAD_POSIX ;
+
+if [ os.name ] = "NT"
+{
+ AVAILABLE_THREAD_APIS = win32 ;
+
+ local PTW32_INCLUDE = [ modules.peek : PTW32_INCLUDE ] ;
+ local PTW32_LIB = [ modules.peek : PTW32_LIB ] ;
+ if $(PTW32_INCLUDE) && $(PTW32_LIB)
+ {
+ BOOST_PTHREAD_OPTS +=
+ <define>BOOST_HAS_PTHREADS
+ <include>$(PTW32_INCLUDE)
+ <library>$(PTW32_LIB) ;
+
+ AVAILABLE_THREAD_APIS += pthread ;
+ }
+ else
+ {
+ echo "******************************************************" ;
+ echo "Building Boost.Thread without optional pthread support" ;
+ echo "If you need pthread you should specify the paths." ;
+ echo "For example:" ;
+ echo "PTW32_INCLUDE=C:\\Program Files\\ptw32\\Pre-built2\\include" ;
+ echo "PTW32_LIB=C:\\Program Files\\ptw32\\Pre-built2\\lib\\pthreadVC2.lib" ;
+ echo "******************************************************" ;
+ BOOST_PTHREAD_OPTS += <build>no ;
+ }
+}
+else
+{
+ AVAILABLE_THREAD_APIS = pthread ;
+ if [ os.name ] = CYGWIN
+ {
+ AVAILABLE_THREAD_APIS += win32 ;
+ }
+}
+feature.feature thrd-api : $(AVAILABLE_THREAD_APIS) : symmetric propagated composite ;
+feature.compose <thrd-api>pthread : $(BOOST_PTHREAD_OPTS) ;
+
+lib boost_thread
+ : ## sources ##
+ win32/thread.cpp
+ win32/exceptions.cpp
+ win32/xtime.cpp
+ win32/tss.cpp
+ win32/tss_hooks.cpp
+ win32/tss_dll.cpp
+ win32/tss_pe.cpp
+ : ## requirements ##
+ <thrd-api>win32
+ ;
+
+# build the pthread based variant
lib boost_thread
- : $(CPP_SOURCES).cpp
- : <link>shared:<define>BOOST_THREAD_BUILD_DLL=1
- <link>static:<define>BOOST_THREAD_BUILD_LIB=1
- : # default build
- : <link>shared:<define>BOOST_THREAD_BUILD_DLL=1
- <link>static:<define>BOOST_THREAD_BUILD_LIB=1
- ;
+ : ## sources ##
+ pthread/thread.cpp
+ pthread/exceptions.cpp
+ pthread/xtime.cpp
+ pthread/tss.cpp
+ : ## requirements ##
+ <thrd-api>pthread
+ $(BOOST_PTHREAD_OPTS)
+ ;
+
Deleted: trunk/libs/thread/src/exceptions.cpp
==============================================================================
--- trunk/libs/thread/src/exceptions.cpp 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
+++ (empty file)
@@ -1,124 +0,0 @@
-// Copyright (C) 2001-2003
-// William E. Kempf
-//
-// 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)
-
-#include <boost/thread/detail/config.hpp>
-
-#include <boost/thread/exceptions.hpp>
-#include <cstring>
-#include <string>
-
-namespace boost {
-
-thread_exception::thread_exception()
- : m_sys_err(0)
-{
-}
-
-thread_exception::thread_exception(int sys_err_code)
- : m_sys_err(sys_err_code)
-{
-}
-
-thread_exception::~thread_exception() throw()
-{
-}
-
-int thread_exception::native_error() const
-{
- return m_sys_err;
-}
-
-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
Copied: trunk/libs/thread/src/pthread/thread.cpp (from r40277, /trunk/libs/thread/src/thread.cpp)
==============================================================================
--- /trunk/libs/thread/src/thread.cpp (original)
+++ trunk/libs/thread/src/pthread/thread.cpp 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
@@ -13,58 +13,10 @@
#include <boost/thread/locks.hpp>
#include <cassert>
-#if defined(BOOST_HAS_WINTHREADS)
-# include <windows.h>
-# if !defined(BOOST_NO_THREADEX)
-# include <process.h>
-# endif
-#elif defined(BOOST_HAS_MPTASKS)
-# include <DriverServices.h>
-
-# include "init.hpp"
-# include "safe.hpp"
-# include <boost/thread/tss.hpp>
-#endif
-
#include "timeconv.inl"
-#if defined(BOOST_HAS_WINTHREADS)
-# include "boost/thread/detail/tss_hooks.hpp"
-#endif
-
namespace {
-#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_NO_THREADEX)
-// Windows CE doesn't define _beginthreadex
-
-struct ThreadProxyData
-{
- typedef unsigned (__stdcall* func)(void*);
- func start_address_;
- void* arglist_;
- ThreadProxyData(func start_address,void* arglist) : start_address_(start_address), arglist_(arglist) {}
-};
-
-DWORD WINAPI ThreadProxy(LPVOID args)
-{
- ThreadProxyData* data=reinterpret_cast<ThreadProxyData*>(args);
- DWORD ret=data->start_address_(data->arglist_);
- delete data;
- return ret;
-}
-
-inline unsigned _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*),
-void* arglist, unsigned initflag,unsigned* thrdaddr)
-{
- DWORD threadID;
- HANDLE hthread=CreateThread(static_cast<LPSECURITY_ATTRIBUTES>(security),stack_size,ThreadProxy,
- new ThreadProxyData(start_address,arglist),initflag,&threadID);
- if (hthread!=0)
- *thrdaddr=threadID;
- return reinterpret_cast<unsigned>(hthread);
-}
-#endif
-
class thread_param
{
public:
@@ -94,24 +46,12 @@
} // unnamed namespace
extern "C" {
-#if defined(BOOST_HAS_WINTHREADS)
- unsigned __stdcall thread_proxy(void* param)
-#elif defined(BOOST_HAS_PTHREADS)
static void* thread_proxy(void* param)
-#elif defined(BOOST_HAS_MPTASKS)
- static OSStatus thread_proxy(void* param)
-#endif
{
thread_param* p = static_cast<thread_param*>(param);
boost::function0<void> threadfunc = p->m_threadfunc;
p->started();
threadfunc();
-#if defined(BOOST_HAS_WINTHREADS)
- on_thread_exit();
-#endif
-#if defined(BOOST_HAS_MPTASKS)
- ::boost::detail::thread_cleanup();
-#endif
return 0;
}
@@ -119,56 +59,20 @@
namespace boost {
-thread::thread()
- : m_joinable(false)
-{
-#if defined(BOOST_HAS_WINTHREADS)
- m_thread = reinterpret_cast<void*>(GetCurrentThread());
- m_id = GetCurrentThreadId();
-#elif defined(BOOST_HAS_PTHREADS)
- m_thread = pthread_self();
-#elif defined(BOOST_HAS_MPTASKS)
- threads::mac::detail::thread_init();
- threads::mac::detail::create_singletons();
- m_pTaskID = MPCurrentTaskID();
- m_pJoinQueueID = kInvalidID;
-#endif
-}
+thread::thread():
+ m_joinable(false)
+{}
thread::thread(const function0<void>& threadfunc)
: m_joinable(true)
{
thread_param param(threadfunc);
-#if defined(BOOST_HAS_WINTHREADS)
- m_thread = reinterpret_cast<void*>(_beginthreadex(0, 0, &thread_proxy,
- ¶m, 0, &m_id));
- if (!m_thread)
- throw thread_resource_error();
-#elif defined(BOOST_HAS_PTHREADS)
int res = 0;
+ pthread_t m_thread;
res = pthread_create(&m_thread, 0, &thread_proxy, ¶m);
if (res != 0)
throw thread_resource_error();
-#elif defined(BOOST_HAS_MPTASKS)
- threads::mac::detail::thread_init();
- threads::mac::detail::create_singletons();
- OSStatus lStatus = noErr;
-
- m_pJoinQueueID = kInvalidID;
- m_pTaskID = kInvalidID;
-
- lStatus = MPCreateQueue(&m_pJoinQueueID);
- if (lStatus != noErr) throw thread_resource_error();
-
- lStatus = MPCreateTask(&thread_proxy, ¶m, 0UL, m_pJoinQueueID, NULL,
- NULL, 0UL, &m_pTaskID);
- if (lStatus != noErr)
- {
- lStatus = MPDeleteQueue(m_pJoinQueueID);
- assert(lStatus == noErr);
- throw thread_resource_error();
- }
-#endif
+ m_id=m_thread;
param.wait();
}
@@ -176,29 +80,13 @@
{
if (m_joinable)
{
-#if defined(BOOST_HAS_WINTHREADS)
- int res = 0;
- res = CloseHandle(reinterpret_cast<HANDLE>(m_thread));
- assert(res);
-#elif defined(BOOST_HAS_PTHREADS)
- pthread_detach(m_thread);
-#elif defined(BOOST_HAS_MPTASKS)
- assert(m_pJoinQueueID != kInvalidID);
- OSStatus lStatus = MPDeleteQueue(m_pJoinQueueID);
- assert(lStatus == noErr);
-#endif
+ pthread_detach(*m_id.id);
}
}
bool thread::operator==(const thread& other) const
{
-#if defined(BOOST_HAS_WINTHREADS)
- return other.m_id == m_id;
-#elif defined(BOOST_HAS_PTHREADS)
- return pthread_equal(m_thread, other.m_thread) != 0;
-#elif defined(BOOST_HAS_MPTASKS)
- return other.m_pTaskID == m_pTaskID;
-#endif
+ return m_id==other.m_id;
}
bool thread::operator!=(const thread& other) const
@@ -210,19 +98,8 @@
{
assert(m_joinable); //See race condition comment below
int res = 0;
-#if defined(BOOST_HAS_WINTHREADS)
- res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_thread), INFINITE);
- assert(res == WAIT_OBJECT_0);
- res = CloseHandle(reinterpret_cast<HANDLE>(m_thread));
- assert(res);
-#elif defined(BOOST_HAS_PTHREADS)
- res = pthread_join(m_thread, 0);
+ res = pthread_join(*m_id.id, 0);
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);
-#endif
// This isn't a race condition since any race that could occur would
// have us in undefined behavior territory any way.
m_joinable = false;
@@ -232,11 +109,6 @@
{
for (int foo=0; foo < 5; ++foo)
{
-#if defined(BOOST_HAS_WINTHREADS)
- int milliseconds;
- to_duration(xt, milliseconds);
- Sleep(milliseconds);
-#elif defined(BOOST_HAS_PTHREADS)
# if defined(BOOST_HAS_PTHREAD_DELAY_NP)
timespec ts;
to_timespec_duration(xt, ts);
@@ -256,13 +128,6 @@
condition cond;
cond.timed_wait(lock, xt);
# endif
-#elif defined(BOOST_HAS_MPTASKS)
- int microseconds;
- to_microduration(xt, microseconds);
- Duration lMicroseconds(kDurationMicrosecond * microseconds);
- AbsoluteTime sWakeTime(DurationToAbsolute(lMicroseconds));
- threads::mac::detail::safe_delay_until(&sWakeTime);
-#endif
xtime cur;
xtime_get(&cur, TIME_UTC);
if (xtime_cmp(xt, cur) <= 0)
@@ -272,9 +137,6 @@
void thread::yield()
{
-#if defined(BOOST_HAS_WINTHREADS)
- Sleep(0);
-#elif defined(BOOST_HAS_PTHREADS)
# if defined(BOOST_HAS_SCHED_YIELD)
int res = 0;
res = sched_yield();
@@ -288,9 +150,6 @@
xtime_get(&xt, TIME_UTC);
sleep(xt);
# endif
-#elif defined(BOOST_HAS_MPTASKS)
- MPYield();
-#endif
}
thread_group::thread_group()
Deleted: trunk/libs/thread/src/thread.cpp
==============================================================================
--- trunk/libs/thread/src/thread.cpp 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
+++ (empty file)
@@ -1,364 +0,0 @@
-// Copyright (C) 2001-2003
-// William E. Kempf
-// Copyright (C) 2007 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)
-
-#include <boost/thread/detail/config.hpp>
-
-#include <boost/thread/thread.hpp>
-#include <boost/thread/xtime.hpp>
-#include <boost/thread/condition.hpp>
-#include <boost/thread/locks.hpp>
-#include <cassert>
-
-#if defined(BOOST_HAS_WINTHREADS)
-# include <windows.h>
-# if !defined(BOOST_NO_THREADEX)
-# include <process.h>
-# endif
-#elif defined(BOOST_HAS_MPTASKS)
-# include <DriverServices.h>
-
-# include "init.hpp"
-# include "safe.hpp"
-# include <boost/thread/tss.hpp>
-#endif
-
-#include "timeconv.inl"
-
-#if defined(BOOST_HAS_WINTHREADS)
-# include "boost/thread/detail/tss_hooks.hpp"
-#endif
-
-namespace {
-
-#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_NO_THREADEX)
-// Windows CE doesn't define _beginthreadex
-
-struct ThreadProxyData
-{
- typedef unsigned (__stdcall* func)(void*);
- func start_address_;
- void* arglist_;
- ThreadProxyData(func start_address,void* arglist) : start_address_(start_address), arglist_(arglist) {}
-};
-
-DWORD WINAPI ThreadProxy(LPVOID args)
-{
- ThreadProxyData* data=reinterpret_cast<ThreadProxyData*>(args);
- DWORD ret=data->start_address_(data->arglist_);
- delete data;
- return ret;
-}
-
-inline unsigned _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*),
-void* arglist, unsigned initflag,unsigned* thrdaddr)
-{
- DWORD threadID;
- HANDLE hthread=CreateThread(static_cast<LPSECURITY_ATTRIBUTES>(security),stack_size,ThreadProxy,
- new ThreadProxyData(start_address,arglist),initflag,&threadID);
- if (hthread!=0)
- *thrdaddr=threadID;
- return reinterpret_cast<unsigned>(hthread);
-}
-#endif
-
-class thread_param
-{
-public:
- thread_param(const boost::function0<void>& threadfunc)
- : m_threadfunc(threadfunc), m_started(false)
- {
- }
- void wait()
- {
- boost::mutex::scoped_lock scoped_lock(m_mutex);
- while (!m_started)
- m_condition.wait(scoped_lock);
- }
- void started()
- {
- boost::mutex::scoped_lock scoped_lock(m_mutex);
- m_started = true;
- m_condition.notify_one();
- }
-
- boost::mutex m_mutex;
- boost::condition m_condition;
- const boost::function0<void>& m_threadfunc;
- bool m_started;
-};
-
-} // unnamed namespace
-
-extern "C" {
-#if defined(BOOST_HAS_WINTHREADS)
- unsigned __stdcall thread_proxy(void* param)
-#elif defined(BOOST_HAS_PTHREADS)
- static void* thread_proxy(void* param)
-#elif defined(BOOST_HAS_MPTASKS)
- static OSStatus thread_proxy(void* param)
-#endif
- {
- thread_param* p = static_cast<thread_param*>(param);
- boost::function0<void> threadfunc = p->m_threadfunc;
- p->started();
- threadfunc();
-#if defined(BOOST_HAS_WINTHREADS)
- on_thread_exit();
-#endif
-#if defined(BOOST_HAS_MPTASKS)
- ::boost::detail::thread_cleanup();
-#endif
- return 0;
- }
-
-}
-
-namespace boost {
-
-thread::thread()
- : m_joinable(false)
-{
-#if defined(BOOST_HAS_WINTHREADS)
- m_thread = reinterpret_cast<void*>(GetCurrentThread());
- m_id = GetCurrentThreadId();
-#elif defined(BOOST_HAS_PTHREADS)
- m_thread = pthread_self();
-#elif defined(BOOST_HAS_MPTASKS)
- threads::mac::detail::thread_init();
- threads::mac::detail::create_singletons();
- m_pTaskID = MPCurrentTaskID();
- m_pJoinQueueID = kInvalidID;
-#endif
-}
-
-thread::thread(const function0<void>& threadfunc)
- : m_joinable(true)
-{
- thread_param param(threadfunc);
-#if defined(BOOST_HAS_WINTHREADS)
- m_thread = reinterpret_cast<void*>(_beginthreadex(0, 0, &thread_proxy,
- ¶m, 0, &m_id));
- if (!m_thread)
- throw thread_resource_error();
-#elif defined(BOOST_HAS_PTHREADS)
- int res = 0;
- res = pthread_create(&m_thread, 0, &thread_proxy, ¶m);
- if (res != 0)
- throw thread_resource_error();
-#elif defined(BOOST_HAS_MPTASKS)
- threads::mac::detail::thread_init();
- threads::mac::detail::create_singletons();
- OSStatus lStatus = noErr;
-
- m_pJoinQueueID = kInvalidID;
- m_pTaskID = kInvalidID;
-
- lStatus = MPCreateQueue(&m_pJoinQueueID);
- if (lStatus != noErr) throw thread_resource_error();
-
- lStatus = MPCreateTask(&thread_proxy, ¶m, 0UL, m_pJoinQueueID, NULL,
- NULL, 0UL, &m_pTaskID);
- if (lStatus != noErr)
- {
- lStatus = MPDeleteQueue(m_pJoinQueueID);
- assert(lStatus == noErr);
- throw thread_resource_error();
- }
-#endif
- param.wait();
-}
-
-thread::~thread()
-{
- if (m_joinable)
- {
-#if defined(BOOST_HAS_WINTHREADS)
- int res = 0;
- res = CloseHandle(reinterpret_cast<HANDLE>(m_thread));
- assert(res);
-#elif defined(BOOST_HAS_PTHREADS)
- pthread_detach(m_thread);
-#elif defined(BOOST_HAS_MPTASKS)
- assert(m_pJoinQueueID != kInvalidID);
- OSStatus lStatus = MPDeleteQueue(m_pJoinQueueID);
- assert(lStatus == noErr);
-#endif
- }
-}
-
-bool thread::operator==(const thread& other) const
-{
-#if defined(BOOST_HAS_WINTHREADS)
- return other.m_id == m_id;
-#elif defined(BOOST_HAS_PTHREADS)
- return pthread_equal(m_thread, other.m_thread) != 0;
-#elif defined(BOOST_HAS_MPTASKS)
- return other.m_pTaskID == m_pTaskID;
-#endif
-}
-
-bool thread::operator!=(const thread& other) const
-{
- return !operator==(other);
-}
-
-void thread::join()
-{
- assert(m_joinable); //See race condition comment below
- int res = 0;
-#if defined(BOOST_HAS_WINTHREADS)
- res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_thread), INFINITE);
- assert(res == WAIT_OBJECT_0);
- res = CloseHandle(reinterpret_cast<HANDLE>(m_thread));
- assert(res);
-#elif defined(BOOST_HAS_PTHREADS)
- res = pthread_join(m_thread, 0);
- 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);
-#endif
- // 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::sleep(const xtime& xt)
-{
- for (int foo=0; foo < 5; ++foo)
- {
-#if defined(BOOST_HAS_WINTHREADS)
- int milliseconds;
- to_duration(xt, milliseconds);
- Sleep(milliseconds);
-#elif defined(BOOST_HAS_PTHREADS)
-# 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);
-# elif defined(BOOST_HAS_NANOSLEEP)
- timespec ts;
- to_timespec_duration(xt, ts);
-
- // 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);
-# endif
-#elif defined(BOOST_HAS_MPTASKS)
- int microseconds;
- to_microduration(xt, microseconds);
- Duration lMicroseconds(kDurationMicrosecond * microseconds);
- AbsoluteTime sWakeTime(DurationToAbsolute(lMicroseconds));
- threads::mac::detail::safe_delay_until(&sWakeTime);
-#endif
- xtime cur;
- xtime_get(&cur, TIME_UTC);
- if (xtime_cmp(xt, cur) <= 0)
- return;
- }
-}
-
-void thread::yield()
-{
-#if defined(BOOST_HAS_WINTHREADS)
- Sleep(0);
-#elif defined(BOOST_HAS_PTHREADS)
-# if defined(BOOST_HAS_SCHED_YIELD)
- int res = 0;
- res = sched_yield();
- assert(res == 0);
-# elif defined(BOOST_HAS_PTHREAD_YIELD)
- int res = 0;
- res = pthread_yield();
- assert(res == 0);
-# else
- xtime xt;
- xtime_get(&xt, TIME_UTC);
- sleep(xt);
-# endif
-#elif defined(BOOST_HAS_MPTASKS)
- MPYield();
-#endif
-}
-
-thread_group::thread_group()
-{
-}
-
-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);
- }
-}
-
-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::add_thread(thread* thrd)
-{
- mutex::scoped_lock scoped_lock(m_mutex);
-
- // 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);
-}
-
-void thread_group::remove_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);
-}
-
-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
Deleted: trunk/libs/thread/src/timeconv.inl
==============================================================================
--- trunk/libs/thread/src/timeconv.inl 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
+++ (empty file)
@@ -1,130 +0,0 @@
-// Copyright (C) 2001-2003
-// William E. Kempf
-//
-// 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
-
-namespace {
-const int MILLISECONDS_PER_SECOND = 1000;
-const int NANOSECONDS_PER_SECOND = 1000000000;
-const int NANOSECONDS_PER_MILLISECOND = 1000000;
-
-const int MICROSECONDS_PER_SECOND = 1000000;
-const int NANOSECONDS_PER_MICROSECOND = 1000;
-
-inline void to_time(int milliseconds, boost::xtime& xt)
-{
- int res = 0;
- res = boost::xtime_get(&xt, boost::TIME_UTC);
- assert(res == boost::TIME_UTC);
-
- xt.sec += (milliseconds / MILLISECONDS_PER_SECOND);
- xt.nsec += ((milliseconds % MILLISECONDS_PER_SECOND) *
- NANOSECONDS_PER_MILLISECOND);
-
- if (xt.nsec >= NANOSECONDS_PER_SECOND)
- {
- ++xt.sec;
- xt.nsec -= NANOSECONDS_PER_SECOND;
- }
-}
-
-#if defined(BOOST_HAS_PTHREADS)
-inline void to_timespec(const boost::xtime& xt, timespec& ts)
-{
- ts.tv_sec = static_cast<int>(xt.sec);
- ts.tv_nsec = static_cast<int>(xt.nsec);
- if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
- {
- ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
- ts.tv_nsec %= NANOSECONDS_PER_SECOND;
- }
-}
-
-inline void to_time(int milliseconds, timespec& ts)
-{
- boost::xtime xt;
- to_time(milliseconds, xt);
- to_timespec(xt, ts);
-}
-
-inline void to_timespec_duration(const boost::xtime& xt, timespec& ts)
-{
- boost::xtime cur;
- int res = 0;
- res = boost::xtime_get(&cur, boost::TIME_UTC);
- assert(res == boost::TIME_UTC);
-
- if (boost::xtime_cmp(xt, cur) <= 0)
- {
- ts.tv_sec = 0;
- ts.tv_nsec = 0;
- }
- else
- {
- ts.tv_sec = xt.sec - cur.sec;
- ts.tv_nsec = xt.nsec - cur.nsec;
-
- if( ts.tv_nsec < 0 )
- {
- ts.tv_sec -= 1;
- ts.tv_nsec += NANOSECONDS_PER_SECOND;
- }
- if(ts.tv_nsec >= NANOSECONDS_PER_SECOND)
- {
- ts.tv_sec += ts.tv_nsec / NANOSECONDS_PER_SECOND;
- ts.tv_nsec %= NANOSECONDS_PER_SECOND;
- }
- }
-}
-#endif
-
-inline void to_duration(boost::xtime xt, int& milliseconds)
-{
- boost::xtime cur;
- int res = 0;
- res = boost::xtime_get(&cur, boost::TIME_UTC);
- assert(res == boost::TIME_UTC);
-
- if (boost::xtime_cmp(xt, cur) <= 0)
- milliseconds = 0;
- else
- {
- if (cur.nsec > xt.nsec)
- {
- xt.nsec += NANOSECONDS_PER_SECOND;
- --xt.sec;
- }
- milliseconds = (int)((xt.sec - cur.sec) * MILLISECONDS_PER_SECOND) +
- (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MILLISECOND/2)) /
- NANOSECONDS_PER_MILLISECOND);
- }
-}
-
-inline void to_microduration(boost::xtime xt, int& microseconds)
-{
- boost::xtime cur;
- int res = 0;
- res = boost::xtime_get(&cur, boost::TIME_UTC);
- assert(res == boost::TIME_UTC);
-
- if (boost::xtime_cmp(xt, cur) <= 0)
- microseconds = 0;
- else
- {
- if (cur.nsec > xt.nsec)
- {
- xt.nsec += NANOSECONDS_PER_SECOND;
- --xt.sec;
- }
- microseconds = (int)((xt.sec - cur.sec) * MICROSECONDS_PER_SECOND) +
- (((xt.nsec - cur.nsec) + (NANOSECONDS_PER_MICROSECOND/2)) /
- NANOSECONDS_PER_MICROSECOND);
- }
-}
-}
-
-// Change Log:
-// 1 Jun 01 Initial creation.
Deleted: trunk/libs/thread/src/tss.cpp
==============================================================================
--- trunk/libs/thread/src/tss.cpp 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
+++ (empty file)
@@ -1,251 +0,0 @@
-// Copyright (C) 2001-2003 William E. Kempf
-// Copyright (C) 2006 Roland Schwarz
-//
-// 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)
-
-#include <boost/thread/detail/config.hpp>
-
-#include <boost/thread/tss.hpp>
-#ifndef BOOST_THREAD_NO_TSS_CLEANUP
-
-#include <boost/thread/once.hpp>
-#include <boost/thread/mutex.hpp>
-#include <boost/thread/exceptions.hpp>
-#include <vector>
-#include <string>
-#include <stdexcept>
-#include <cassert>
-
-#if defined(BOOST_HAS_WINTHREADS)
-# include <windows.h>
-# include <boost/thread/detail/tss_hooks.hpp>
-#endif
-
-namespace {
-
-typedef std::vector<void*> tss_slots;
-typedef std::vector<boost::function1<void, void*>*> tss_data_cleanup_handlers_type;
-
-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)
-{
- ++tss_data_use;
-}
-
-void tss_data_dec_use(boost::mutex::scoped_lock& lk)
-{
- if (0 == --tss_data_use)
- {
- tss_data_cleanup_handlers_type::size_type i;
- for (i = 0; i < tss_data_cleanup_handlers->size(); ++i)
- {
- delete (*tss_data_cleanup_handlers)[i];
- }
- delete tss_data_cleanup_handlers;
- tss_data_cleanup_handlers = 0;
- 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
- }
-}
-
-extern "C" void cleanup_slots(void* p)
-{
- tss_slots* slots = static_cast<tss_slots*>(p);
- boost::mutex::scoped_lock lock(*tss_data_mutex);
- for (tss_slots::size_type i = 0; i < slots->size(); ++i)
- {
- (*(*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;
-}
-
-void init_tss_data()
-{
- std::auto_ptr<tss_data_cleanup_handlers_type>
- temp(new tss_data_cleanup_handlers_type);
-
- std::auto_ptr<boost::mutex> temp_mutex(new boost::mutex);
- 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.
- // This avoids a memory leak by releasing the global data
- // after last use only, since the execution order of cleanup
- // handlers is unspecified on any platform with regards to
- // C++ destructor ordering rules.
- tss_data_cleanup_handlers = temp.release();
- 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);
- }
- slots = temp.release();
- }
-
- return slots;
-}
-
-} // namespace
-
-namespace boost {
-
-namespace detail {
-void tss::init(boost::function1<void, void*>* pcleanup)
-{
- boost::call_once(tss_data_once, &init_tss_data);
- if (tss_data_cleanup_handlers == 0)
- throw thread_resource_error();
- boost::mutex::scoped_lock lock(*tss_data_mutex);
- try
- {
- tss_data_cleanup_handlers->push_back(pcleanup);
- m_slot = tss_data_cleanup_handlers->size() - 1;
- tss_data_inc_use(lock);
- }
- catch (...)
- {
- throw thread_resource_error();
- }
-}
-
-tss::~tss()
-{
- boost::mutex::scoped_lock lock(*tss_data_mutex);
- tss_data_dec_use(lock);
-}
-
-void* tss::get() const
-{
- tss_slots* slots = get_slots(false);
-
- if (!slots)
- return 0;
-
- if (m_slot >= slots->size())
- return 0;
-
- return (*slots)[m_slot];
-}
-
-void tss::set(void* value)
-{
- tss_slots* slots = get_slots(true);
-
- if (!slots)
- throw boost::thread_resource_error();
-
- if (m_slot >= slots->size())
- {
- try
- {
- slots->resize(m_slot + 1);
- }
- catch (...)
- {
- throw boost::thread_resource_error();
- }
- }
-
- (*slots)[m_slot] = value;
-}
-
-void tss::cleanup(void* value)
-{
- boost::mutex::scoped_lock lock(*tss_data_mutex);
- (*(*tss_data_cleanup_handlers)[m_slot])(value);
-}
-
-} // namespace detail
-} // namespace boost
-
-#endif //BOOST_THREAD_NO_TSS_CLEANUP
Deleted: trunk/libs/thread/src/tss_dll.cpp
==============================================================================
--- trunk/libs/thread/src/tss_dll.cpp 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
+++ (empty file)
@@ -1,72 +0,0 @@
-// (C) Copyright Michael Glassford 2004.
-// Use, modification and distribution are subject to 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)
-
-#include <boost/thread/detail/config.hpp>
-
-#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL)
-
- #include <boost/thread/detail/tss_hooks.hpp>
-
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
-
- #if defined(__BORLANDC__)
- extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/)
- #elif defined(_WIN32_WCE)
- extern "C" BOOL WINAPI DllMain(HANDLE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/)
- #else
- extern "C" BOOL WINAPI DllMain(HINSTANCE /*hInstance*/, DWORD dwReason, LPVOID /*lpReserved*/)
- #endif
- {
- switch(dwReason)
- {
- case DLL_PROCESS_ATTACH:
- {
- on_process_enter();
- on_thread_enter();
- break;
- }
-
- case DLL_THREAD_ATTACH:
- {
- on_thread_enter();
- break;
- }
-
- case DLL_THREAD_DETACH:
- {
- on_thread_exit();
- break;
- }
-
- case DLL_PROCESS_DETACH:
- {
- on_thread_exit();
- on_process_exit();
- break;
- }
- }
-
- return TRUE;
- }
-
- extern "C" void tss_cleanup_implemented(void)
- {
- /*
- This function's sole purpose is to cause a link error in cases where
- automatic tss cleanup is not implemented by Boost.Threads as a
- reminder that user code is responsible for calling the necessary
- functions at the appropriate times (and for implementing an a
- tss_cleanup_implemented() function to eliminate the linker's
- missing symbol error).
-
- If Boost.Threads later implements automatic tss cleanup in cases
- where it currently doesn't (which is the plan), the duplicate
- symbol error will warn the user that their custom solution is no
- longer needed and can be removed.
- */
- }
-
-#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_DLL)
Deleted: trunk/libs/thread/src/tss_hooks.cpp
==============================================================================
--- trunk/libs/thread/src/tss_hooks.cpp 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
+++ (empty file)
@@ -1,212 +0,0 @@
-// Copyright (C) 2004 Michael Glassford
-// Copyright (C) 2006 Roland Schwarz
-// Use, modification and distribution are subject to 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)
-
-#include <boost/thread/detail/config.hpp>
-
-#if defined(BOOST_HAS_WINTHREADS)
-
- #include <boost/thread/detail/tss_hooks.hpp>
-
- #include <boost/assert.hpp>
-// #include <boost/thread/mutex.hpp>
- #include <boost/thread/once.hpp>
-
- #include <list>
-
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
-
- namespace
- {
- class CScopedCSLock
- {
- public:
- CScopedCSLock(LPCRITICAL_SECTION cs) : cs(cs), lk(true) {
- ::EnterCriticalSection(cs);
- }
- ~CScopedCSLock() {
- if (lk) ::LeaveCriticalSection(cs);
- }
- void Unlock() {
- lk = false;
- ::LeaveCriticalSection(cs);
- }
- private:
- bool lk;
- LPCRITICAL_SECTION cs;
- };
-
- typedef std::list<thread_exit_handler> thread_exit_handlers;
-
- boost::once_flag once_init_threadmon_mutex = BOOST_ONCE_INIT;
- //boost::mutex* threadmon_mutex;
- // We don't use boost::mutex here, to avoid a memory leak report,
- // because we cannot delete it again easily.
- CRITICAL_SECTION threadmon_mutex;
- void init_threadmon_mutex(void)
- {
- //threadmon_mutex = new boost::mutex;
- //if (!threadmon_mutex)
- // throw boost::thread_resource_error();
- ::InitializeCriticalSection(&threadmon_mutex);
- }
-
- const DWORD invalid_tls_key = TLS_OUT_OF_INDEXES;
- DWORD tls_key = invalid_tls_key;
-
- unsigned long attached_thread_count = 0;
- }
-
- /*
- Calls to DllMain() and tls_callback() are serialized by the OS;
- however, calls to at_thread_exit are not, so it must be protected
- by a mutex. Since we already need a mutex for at_thread_exit(),
- and since there is no guarantee that on_process_enter(),
- on_process_exit(), on_thread_enter(), and on_thread_exit()
- will be called only from DllMain() or tls_callback(), it makes
- sense to protect those, too.
- */
-
- extern "C" BOOST_THREAD_DECL int at_thread_exit(
- thread_exit_handler exit_handler
- )
- {
- boost::call_once(once_init_threadmon_mutex, init_threadmon_mutex);
- //boost::mutex::scoped_lock lock(*threadmon_mutex);
- CScopedCSLock lock(&threadmon_mutex);
-
- //Allocate a tls slot if necessary.
-
- if (tls_key == invalid_tls_key)
- tls_key = TlsAlloc();
-
- if (tls_key == invalid_tls_key)
- return -1;
-
- //Get the exit handlers list for the current thread from tls.
-
- thread_exit_handlers* exit_handlers =
- static_cast<thread_exit_handlers*>(TlsGetValue(tls_key));
-
- if (!exit_handlers)
- {
- //No exit handlers list was created yet.
-
- try
- {
- //Attempt to create a new exit handlers list.
-
- exit_handlers = new thread_exit_handlers;
- if (!exit_handlers)
- return -1;
-
- //Attempt to store the list pointer in tls.
-
- if (TlsSetValue(tls_key, exit_handlers))
- ++attached_thread_count;
- else
- {
- delete exit_handlers;
- return -1;
- }
- }
- catch (...)
- {
- return -1;
- }
- }
-
- //Like the C runtime library atexit() function,
- //functions should be called in the reverse of
- //the order they are added, so push them on the
- //front of the list.
-
- try
- {
- exit_handlers->push_front(exit_handler);
- }
- catch (...)
- {
- return -1;
- }
-
- //Like the atexit() function, a result of zero
- //indicates success.
-
- return 0;
- }
-
- extern "C" BOOST_THREAD_DECL void on_process_enter(void)
- {
- boost::call_once(once_init_threadmon_mutex, init_threadmon_mutex);
-// boost::mutex::scoped_lock lock(*threadmon_mutex);
- CScopedCSLock lock(&threadmon_mutex);
-
- BOOST_ASSERT(attached_thread_count == 0);
- }
-
- extern "C" BOOST_THREAD_DECL void on_process_exit(void)
- {
- boost::call_once(once_init_threadmon_mutex, init_threadmon_mutex);
-// boost::mutex::scoped_lock lock(*threadmon_mutex);
- CScopedCSLock lock(&threadmon_mutex);
-
- BOOST_ASSERT(attached_thread_count == 0);
-
- //Free the tls slot if one was allocated.
-
- if (tls_key != invalid_tls_key)
- {
- TlsFree(tls_key);
- tls_key = invalid_tls_key;
- }
- }
-
- extern "C" BOOST_THREAD_DECL void on_thread_enter(void)
- {
- //boost::call_once(init_threadmon_mutex, once_init_threadmon_mutex);
- //boost::mutex::scoped_lock lock(*threadmon_mutex);
- }
-
- extern "C" BOOST_THREAD_DECL void on_thread_exit(void)
- {
- boost::call_once(once_init_threadmon_mutex, init_threadmon_mutex);
-// boost::mutex::scoped_lock lock(*threadmon_mutex);
- CScopedCSLock lock(&threadmon_mutex);
-
- //Get the exit handlers list for the current thread from tls.
-
- if (tls_key == invalid_tls_key)
- return;
-
- thread_exit_handlers* exit_handlers =
- static_cast<thread_exit_handlers*>(TlsGetValue(tls_key));
-
- //If a handlers list was found, use it.
-
- if (exit_handlers && TlsSetValue(tls_key, 0))
- {
- BOOST_ASSERT(attached_thread_count > 0);
- --attached_thread_count;
-
- //lock.unlock();
- lock.Unlock();
-
- //Call each handler and remove it from the list
-
- while (!exit_handlers->empty())
- {
- if (thread_exit_handler exit_handler = *exit_handlers->begin())
- (*exit_handler)();
- exit_handlers->pop_front();
- }
-
- delete exit_handlers;
- exit_handlers = 0;
- }
- }
-
-#endif //defined(BOOST_HAS_WINTHREADS)
Deleted: trunk/libs/thread/src/tss_pe.cpp
==============================================================================
--- trunk/libs/thread/src/tss_pe.cpp 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
+++ (empty file)
@@ -1,179 +0,0 @@
-// (C) Copyright Aaron W. LaFramboise, Roland Schwarz, Michael Glassford 2004.
-// Use, modification and distribution are subject to 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)
-
-#include <boost/thread/detail/config.hpp>
-
-#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB) && defined(_MSC_VER)
-
- #include <boost/thread/detail/tss_hooks.hpp>
-
- #include <stdlib.h>
-
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
-
- //Definitions required by implementation
-
- #if (_MSC_VER < 1300) // 1300 == VC++ 7.0
- typedef void (__cdecl *_PVFV)(void);
- #define INIRETSUCCESS
- #define PVAPI void
- #else
- typedef int (__cdecl *_PVFV)(void);
- #define INIRETSUCCESS 0
- #define PVAPI int
- #endif
-
- typedef void (NTAPI* _TLSCB)(HINSTANCE, DWORD, PVOID);
-
- //Symbols for connection to the runtime environment
-
- extern "C"
- {
- extern DWORD _tls_used; //the tls directory (located in .rdata segment)
- extern _TLSCB __xl_a[], __xl_z[]; //tls initializers */
- }
-
- namespace
- {
- //Forward declarations
-
- static PVAPI on_tls_prepare(void);
- static PVAPI on_process_init(void);
- static PVAPI on_process_term(void);
- static void NTAPI on_tls_callback(HINSTANCE, DWORD, PVOID);
-
- //The .CRT$Xxx information is taken from Codeguru:
- //http://www.codeguru.com/Cpp/misc/misc/threadsprocesses/article.php/c6945__2/
-
- #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
- # pragma data_seg(push, old_seg)
- #endif
- //Callback to run tls glue code first.
- //I don't think it is necessary to run it
- //at .CRT$XIB level, since we are only
- //interested in thread detachement. But
- //this could be changed easily if required.
-
- #pragma data_seg(".CRT$XIU")
- static _PVFV p_tls_prepare = on_tls_prepare;
- #pragma data_seg()
-
- //Callback after all global ctors.
-
- #pragma data_seg(".CRT$XCU")
- static _PVFV p_process_init = on_process_init;
- #pragma data_seg()
-
- //Callback for tls notifications.
-
- #pragma data_seg(".CRT$XLB")
- _TLSCB p_thread_callback = on_tls_callback;
- #pragma data_seg()
-
- //Callback for termination.
-
- #pragma data_seg(".CRT$XTU")
- static _PVFV p_process_term = on_process_term;
- #pragma data_seg()
- #if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
- # pragma data_seg(pop, old_seg)
- #endif
-
- PVAPI on_tls_prepare(void)
- {
- //The following line has an important side effect:
- //if the TLS directory is not already there, it will
- //be created by the linker. In other words, it forces a tls
- //directory to be generated by the linker even when static tls
- //(i.e. __declspec(thread)) is not used.
- //The volatile should prevent the optimizer
- //from removing the reference.
-
- DWORD volatile dw = _tls_used;
-
- #if (_MSC_VER < 1300) // 1300 == VC++ 7.0
- _TLSCB* pfbegin = __xl_a;
- _TLSCB* pfend = __xl_z;
- _TLSCB* pfdst = pfbegin;
- //pfdst = (_TLSCB*)_tls_used.AddressOfCallBacks;
-
- //The following loop will merge the address pointers
- //into a contiguous area, since the tlssup code seems
- //to require this (at least on MSVC 6)
-
- while (pfbegin < pfend)
- {
- if (*pfbegin != 0)
- {
- *pfdst = *pfbegin;
- ++pfdst;
- }
- ++pfbegin;
- }
-
- *pfdst = 0;
- #endif
-
- return INIRETSUCCESS;
- }
-
- PVAPI on_process_init(void)
- {
- //Schedule on_thread_exit() to be called for the main
- //thread before destructors of global objects have been
- //called.
-
- //It will not be run when 'quick' exiting the
- //library; however, this is the standard behaviour
- //for destructors of global objects, so that
- //shouldn't be a problem.
-
- atexit(on_thread_exit);
-
- //Call Boost process entry callback here
-
- on_process_enter();
-
- return INIRETSUCCESS;
- }
-
- PVAPI on_process_term(void)
- {
- on_process_exit();
- return INIRETSUCCESS;
- }
-
- void NTAPI on_tls_callback(HINSTANCE h, DWORD dwReason, PVOID pv)
- {
- switch (dwReason)
- {
- case DLL_THREAD_DETACH:
- {
- on_thread_exit();
- break;
- }
- }
- }
- } //namespace
-
- extern "C" void tss_cleanup_implemented(void)
- {
- /*
- This function's sole purpose is to cause a link error in cases where
- automatic tss cleanup is not implemented by Boost.Threads as a
- reminder that user code is responsible for calling the necessary
- functions at the appropriate times (and for implementing an a
- tss_cleanup_implemented() function to eliminate the linker's
- missing symbol error).
-
- If Boost.Threads later implements automatic tss cleanup in cases
- where it currently doesn't (which is the plan), the duplicate
- symbol error will warn the user that their custom solution is no
- longer needed and can be removed.
- */
- }
-
-#endif //defined(BOOST_HAS_WINTHREADS) && defined(BOOST_THREAD_BUILD_LIB)
Copied: trunk/libs/thread/src/win32/thread.cpp (from r40277, /trunk/libs/thread/src/thread.cpp)
==============================================================================
--- /trunk/libs/thread/src/thread.cpp (original)
+++ trunk/libs/thread/src/win32/thread.cpp 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
@@ -1,364 +1,443 @@
-// Copyright (C) 2001-2003
-// William E. Kempf
-// Copyright (C) 2007 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)
-
-#include <boost/thread/detail/config.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)
+// (C) Copyright 2007 Anthony Williams
#include <boost/thread/thread.hpp>
-#include <boost/thread/xtime.hpp>
-#include <boost/thread/condition.hpp>
-#include <boost/thread/locks.hpp>
-#include <cassert>
-
-#if defined(BOOST_HAS_WINTHREADS)
-# include <windows.h>
-# if !defined(BOOST_NO_THREADEX)
-# include <process.h>
-# endif
-#elif defined(BOOST_HAS_MPTASKS)
-# include <DriverServices.h>
-
-# include "init.hpp"
-# include "safe.hpp"
-# include <boost/thread/tss.hpp>
-#endif
-
-#include "timeconv.inl"
-
-#if defined(BOOST_HAS_WINTHREADS)
-# include "boost/thread/detail/tss_hooks.hpp"
-#endif
-
-namespace {
-
-#if defined(BOOST_HAS_WINTHREADS) && defined(BOOST_NO_THREADEX)
-// Windows CE doesn't define _beginthreadex
-
-struct ThreadProxyData
-{
- typedef unsigned (__stdcall* func)(void*);
- func start_address_;
- void* arglist_;
- ThreadProxyData(func start_address,void* arglist) : start_address_(start_address), arglist_(arglist) {}
-};
-
-DWORD WINAPI ThreadProxy(LPVOID args)
-{
- ThreadProxyData* data=reinterpret_cast<ThreadProxyData*>(args);
- DWORD ret=data->start_address_(data->arglist_);
- delete data;
- return ret;
-}
-
-inline unsigned _beginthreadex(void* security, unsigned stack_size, unsigned (__stdcall* start_address)(void*),
-void* arglist, unsigned initflag,unsigned* thrdaddr)
-{
- DWORD threadID;
- HANDLE hthread=CreateThread(static_cast<LPSECURITY_ATTRIBUTES>(security),stack_size,ThreadProxy,
- new ThreadProxyData(start_address,arglist),initflag,&threadID);
- if (hthread!=0)
- *thrdaddr=threadID;
- return reinterpret_cast<unsigned>(hthread);
-}
-#endif
+#include <algorithm>
+#include <windows.h>
+#include <process.h>
+#include <stdio.h>
+#include <boost/thread/once.hpp>
+#include <boost/assert.hpp>
-class thread_param
+namespace boost
{
-public:
- thread_param(const boost::function0<void>& threadfunc)
- : m_threadfunc(threadfunc), m_started(false)
+ namespace
{
+#ifdef _MSC_VER
+ __declspec(thread) detail::thread_data_base* current_thread_data=0;
+ detail::thread_data_base* get_current_thread_data()
+ {
+ return current_thread_data;
+ }
+ void set_current_thread_data(detail::thread_data_base* new_data)
+ {
+ current_thread_data=new_data;
+ }
+#elif defined(__BORLANDC__)
+ detail::thread_data_base* __thread current_thread_data=0;
+ detail::thread_data_base* get_current_thread_data()
+ {
+ return current_thread_data;
+ }
+ void set_current_thread_data(detail::thread_data_base* new_data)
+ {
+ current_thread_data=new_data;
+ }
+#else
+
+ boost::once_flag current_thread_tls_init_flag=BOOST_ONCE_INIT;
+ DWORD current_thread_tls_key=0;
+
+ void create_current_thread_tls_key()
+ {
+ current_thread_tls_key=TlsAlloc();
+ BOOST_ASSERT(current_thread_tls_key!=TLS_OUT_OF_INDEXES);
+ }
+
+ detail::thread_data_base* get_current_thread_data()
+ {
+ boost::call_once(current_thread_tls_init_flag,create_current_thread_tls_key);
+ return (detail::thread_data_base*)TlsGetValue(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);
+ BOOL const res=TlsSetValue(current_thread_tls_key,new_data);
+ BOOST_ASSERT(res);
+ }
+#endif
}
- void wait()
+
+ void thread::yield()
{
- boost::mutex::scoped_lock scoped_lock(m_mutex);
- while (!m_started)
- m_condition.wait(scoped_lock);
+ this_thread::yield();
}
- void started()
+
+ void thread::sleep(const system_time& target)
{
- boost::mutex::scoped_lock scoped_lock(m_mutex);
- m_started = true;
- m_condition.notify_one();
+ system_time const now(get_system_time());
+
+ if(target<=now)
+ {
+ this_thread::yield();
+ }
+ else
+ {
+ this_thread::sleep(target-now);
+ }
}
- boost::mutex m_mutex;
- boost::condition m_condition;
- const boost::function0<void>& m_threadfunc;
- bool m_started;
-};
-
-} // unnamed namespace
-
-extern "C" {
-#if defined(BOOST_HAS_WINTHREADS)
- unsigned __stdcall thread_proxy(void* param)
-#elif defined(BOOST_HAS_PTHREADS)
- static void* thread_proxy(void* param)
-#elif defined(BOOST_HAS_MPTASKS)
- static OSStatus thread_proxy(void* param)
-#endif
+ unsigned __stdcall thread::thread_start_function(void* param)
{
- thread_param* p = static_cast<thread_param*>(param);
- boost::function0<void> threadfunc = p->m_threadfunc;
- p->started();
- threadfunc();
-#if defined(BOOST_HAS_WINTHREADS)
- on_thread_exit();
-#endif
-#if defined(BOOST_HAS_MPTASKS)
- ::boost::detail::thread_cleanup();
-#endif
+ boost::intrusive_ptr<detail::thread_data_base> thread_info(reinterpret_cast<detail::thread_data_base*>(param),false);
+ set_current_thread_data(thread_info.get());
+ try
+ {
+ thread_info->run();
+ }
+ catch(thread_canceled const&)
+ {
+ }
+ catch(...)
+ {
+ std::terminate();
+ }
return 0;
}
-}
+ thread::thread()
+ {}
-namespace boost {
+ void thread::start_thread()
+ {
+ 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();
+ }
+ intrusive_ptr_add_ref(thread_info.get());
+ thread_info->thread_handle=(detail::win32::handle)(new_thread);
+ ResumeThread(thread_info->thread_handle);
+ }
-thread::thread()
- : m_joinable(false)
-{
-#if defined(BOOST_HAS_WINTHREADS)
- m_thread = reinterpret_cast<void*>(GetCurrentThread());
- m_id = GetCurrentThreadId();
-#elif defined(BOOST_HAS_PTHREADS)
- m_thread = pthread_self();
-#elif defined(BOOST_HAS_MPTASKS)
- threads::mac::detail::thread_init();
- threads::mac::detail::create_singletons();
- m_pTaskID = MPCurrentTaskID();
- m_pJoinQueueID = kInvalidID;
-#endif
-}
+ thread::thread(boost::intrusive_ptr<detail::thread_data_base> data):
+ thread_info(data)
+ {}
-thread::thread(const function0<void>& threadfunc)
- : m_joinable(true)
-{
- thread_param param(threadfunc);
-#if defined(BOOST_HAS_WINTHREADS)
- m_thread = reinterpret_cast<void*>(_beginthreadex(0, 0, &thread_proxy,
- ¶m, 0, &m_id));
- if (!m_thread)
- throw thread_resource_error();
-#elif defined(BOOST_HAS_PTHREADS)
- int res = 0;
- res = pthread_create(&m_thread, 0, &thread_proxy, ¶m);
- if (res != 0)
- throw thread_resource_error();
-#elif defined(BOOST_HAS_MPTASKS)
- threads::mac::detail::thread_init();
- threads::mac::detail::create_singletons();
- OSStatus lStatus = noErr;
-
- m_pJoinQueueID = kInvalidID;
- m_pTaskID = kInvalidID;
-
- lStatus = MPCreateQueue(&m_pJoinQueueID);
- if (lStatus != noErr) throw thread_resource_error();
-
- lStatus = MPCreateTask(&thread_proxy, ¶m, 0UL, m_pJoinQueueID, NULL,
- NULL, 0UL, &m_pTaskID);
- if (lStatus != noErr)
- {
- lStatus = MPDeleteQueue(m_pJoinQueueID);
- assert(lStatus == noErr);
- throw thread_resource_error();
+ namespace
+ {
+ struct externally_launched_thread:
+ detail::thread_data_base
+ {
+ externally_launched_thread()
+ {
+ ++count;
+ thread_handle=detail::win32::duplicate_handle(detail::win32::GetCurrentThread());
+ }
+
+ void run()
+ {}
+ };
+
+ struct externally_launched_thread_deleter
+ {
+ externally_launched_thread* thread_data;
+
+ externally_launched_thread_deleter(externally_launched_thread* thread_data_):
+ thread_data(thread_data_)
+ {}
+
+ void operator()() const
+ {
+ intrusive_ptr_release(thread_data);
+ }
+ };
+
}
-#endif
- param.wait();
-}
+
-thread::~thread()
-{
- if (m_joinable)
+ thread thread::self()
{
-#if defined(BOOST_HAS_WINTHREADS)
- int res = 0;
- res = CloseHandle(reinterpret_cast<HANDLE>(m_thread));
- assert(res);
-#elif defined(BOOST_HAS_PTHREADS)
- pthread_detach(m_thread);
-#elif defined(BOOST_HAS_MPTASKS)
- assert(m_pJoinQueueID != kInvalidID);
- OSStatus lStatus = MPDeleteQueue(m_pJoinQueueID);
- assert(lStatus == noErr);
-#endif
+ if(!get_current_thread_data())
+ {
+ externally_launched_thread* me=detail::heap_new<externally_launched_thread>();
+ set_current_thread_data(me);
+ this_thread::at_thread_exit(externally_launched_thread_deleter(me));
+ }
+ return thread(boost::intrusive_ptr<detail::thread_data_base>(get_current_thread_data()));
+ }
+
+ thread::~thread()
+ {
+ cancel();
+ detach();
+ }
+
+ thread::thread(boost::move_t<thread> x)
+ {
+ {
+ boost::mutex::scoped_lock l(x->thread_info_mutex);
+ thread_info=x->thread_info;
+ }
+ x->release_handle();
+ }
+
+ thread& thread::operator=(boost::move_t<thread> x)
+ {
+ thread new_thread(x);
+ swap(new_thread);
+ return *this;
+ }
+
+ thread::operator boost::move_t<thread>()
+ {
+ return boost::move_t<thread>(*this);
}
-}
-
-bool thread::operator==(const thread& other) const
-{
-#if defined(BOOST_HAS_WINTHREADS)
- return other.m_id == m_id;
-#elif defined(BOOST_HAS_PTHREADS)
- return pthread_equal(m_thread, other.m_thread) != 0;
-#elif defined(BOOST_HAS_MPTASKS)
- return other.m_pTaskID == m_pTaskID;
-#endif
-}
-
-bool thread::operator!=(const thread& other) const
-{
- return !operator==(other);
-}
-void thread::join()
-{
- assert(m_joinable); //See race condition comment below
- int res = 0;
-#if defined(BOOST_HAS_WINTHREADS)
- res = WaitForSingleObject(reinterpret_cast<HANDLE>(m_thread), INFINITE);
- assert(res == WAIT_OBJECT_0);
- res = CloseHandle(reinterpret_cast<HANDLE>(m_thread));
- assert(res);
-#elif defined(BOOST_HAS_PTHREADS)
- res = pthread_join(m_thread, 0);
- 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);
-#endif
- // This isn't a race condition since any race that could occur would
- // have us in undefined behavior territory any way.
- m_joinable = false;
-}
+ boost::move_t<thread> thread::move()
+ {
+ return boost::move_t<thread>(*this);
+ }
-void thread::sleep(const xtime& xt)
-{
- for (int foo=0; foo < 5; ++foo)
+ void thread::swap(thread& x)
{
-#if defined(BOOST_HAS_WINTHREADS)
- int milliseconds;
- to_duration(xt, milliseconds);
- Sleep(milliseconds);
-#elif defined(BOOST_HAS_PTHREADS)
-# 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);
-# elif defined(BOOST_HAS_NANOSLEEP)
- timespec ts;
- to_timespec_duration(xt, ts);
-
- // 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);
-# endif
-#elif defined(BOOST_HAS_MPTASKS)
- int microseconds;
- to_microduration(xt, microseconds);
- Duration lMicroseconds(kDurationMicrosecond * microseconds);
- AbsoluteTime sWakeTime(DurationToAbsolute(lMicroseconds));
- threads::mac::detail::safe_delay_until(&sWakeTime);
-#endif
- xtime cur;
- xtime_get(&cur, TIME_UTC);
- if (xtime_cmp(xt, cur) <= 0)
- return;
+ thread_info.swap(x.thread_info);
}
-}
-void thread::yield()
-{
-#if defined(BOOST_HAS_WINTHREADS)
- Sleep(0);
-#elif defined(BOOST_HAS_PTHREADS)
-# if defined(BOOST_HAS_SCHED_YIELD)
- int res = 0;
- res = sched_yield();
- assert(res == 0);
-# elif defined(BOOST_HAS_PTHREAD_YIELD)
- int res = 0;
- res = pthread_yield();
- assert(res == 0);
-# else
- xtime xt;
- xtime_get(&xt, TIME_UTC);
- sleep(xt);
-# endif
-#elif defined(BOOST_HAS_MPTASKS)
- MPYield();
-#endif
-}
+ thread::id thread::get_id() const
+ {
+ boost::intrusive_ptr<detail::thread_data_base> local_thread_info=get_thread_info();
+ return local_thread_info?thread::id(local_thread_info->id):thread::id();
+ }
-thread_group::thread_group()
-{
-}
+ thread::cancel_handle thread::get_cancel_handle() const
+ {
+ boost::intrusive_ptr<detail::thread_data_base> local_thread_info=get_thread_info();
+ return local_thread_info?thread::cancel_handle(local_thread_info->cancel_handle.duplicate()):thread::cancel_handle();
+ }
+
+ bool thread::joinable() const
+ {
+ return get_thread_info();
+ }
-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)
+ void thread::join()
{
- delete (*it);
+ boost::intrusive_ptr<detail::thread_data_base> local_thread_info=get_thread_info();
+ if(local_thread_info)
+ {
+ this_thread::cancellable_wait(local_thread_info->thread_handle,detail::win32::infinite);
+ release_handle();
+ }
+ }
+
+ void thread::detach()
+ {
+ release_handle();
}
-}
-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::release_handle()
+ {
+ boost::mutex::scoped_lock l1(thread_info_mutex);
+ thread_info=0;
+ }
+
+ void thread::cancel()
+ {
+ boost::intrusive_ptr<detail::thread_data_base> local_thread_info=get_thread_info();
+ if(local_thread_info)
+ {
+ detail::win32::SetEvent(local_thread_info->cancel_handle);
+ }
+ }
+
+ bool thread::cancellation_requested() const
+ {
+ boost::intrusive_ptr<detail::thread_data_base> local_thread_info=get_thread_info();
+ return local_thread_info.get() && (detail::win32::WaitForSingleObject(local_thread_info->cancel_handle,0)==0);
+ }
+
+ unsigned thread::hardware_concurrency()
+ {
+ SYSTEM_INFO info={0};
+ GetSystemInfo(&info);
+ return info.dwNumberOfProcessors;
+ }
+
+ thread::native_handle_type thread::native_handle()
+ {
+ boost::intrusive_ptr<detail::thread_data_base> local_thread_info=get_thread_info();
+ return local_thread_info?(detail::win32::handle)local_thread_info->thread_handle:detail::win32::invalid_handle_value;
+ }
-void thread_group::add_thread(thread* thrd)
-{
- mutex::scoped_lock scoped_lock(m_mutex);
+ boost::intrusive_ptr<detail::thread_data_base> thread::get_thread_info() const
+ {
+ boost::mutex::scoped_lock l(thread_info_mutex);
+ return thread_info;
+ }
- // 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);
-}
+ namespace this_thread
+ {
+ thread::cancel_handle get_cancel_handle()
+ {
+ return get_current_thread_data()?thread::cancel_handle(get_current_thread_data()->cancel_handle.duplicate()):thread::cancel_handle();
+ }
+
+ bool cancellable_wait(detail::win32::handle handle_to_wait_for,unsigned long milliseconds)
+ {
+ detail::win32::handle handles[2]={0};
+ unsigned handle_count=0;
+ unsigned cancel_index=~0U;
+ if(handle_to_wait_for!=detail::win32::invalid_handle_value)
+ {
+ handles[handle_count++]=handle_to_wait_for;
+ }
+ if(get_current_thread_data() && get_current_thread_data()->cancel_enabled)
+ {
+ cancel_index=handle_count;
+ handles[handle_count++]=get_current_thread_data()->cancel_handle;
+ }
+
+ if(handle_count)
+ {
+ unsigned long const notified_index=detail::win32::WaitForMultipleObjects(handle_count,handles,false,milliseconds);
+ if((handle_to_wait_for!=detail::win32::invalid_handle_value) && !notified_index)
+ {
+ return true;
+ }
+ else if(notified_index==cancel_index)
+ {
+ detail::win32::ResetEvent(get_current_thread_data()->cancel_handle);
+ throw thread_canceled();
+ }
+ }
+ else
+ {
+ detail::win32::Sleep(milliseconds);
+ }
+ return false;
+ }
+
+ thread::id get_id()
+ {
+ return thread::id(detail::win32::GetCurrentThreadId());
+ }
+
+ void cancellation_point()
+ {
+ if(cancellation_enabled() && cancellation_requested())
+ {
+ detail::win32::ResetEvent(get_current_thread_data()->cancel_handle);
+ throw thread_canceled();
+ }
+ }
+
+ bool cancellation_enabled()
+ {
+ return get_current_thread_data() && get_current_thread_data()->cancel_enabled;
+ }
+
+ bool cancellation_requested()
+ {
+ return get_current_thread_data() && (detail::win32::WaitForSingleObject(get_current_thread_data()->cancel_handle,0)==0);
+ }
+
+ void yield()
+ {
+ detail::win32::Sleep(0);
+ }
+
+ disable_cancellation::disable_cancellation():
+ cancel_was_enabled(cancellation_enabled())
+ {
+ if(cancel_was_enabled)
+ {
+ get_current_thread_data()->cancel_enabled=false;
+ }
+ }
+
+ disable_cancellation::~disable_cancellation()
+ {
+ if(get_current_thread_data())
+ {
+ get_current_thread_data()->cancel_enabled=cancel_was_enabled;
+ }
+ }
+
+ enable_cancellation::enable_cancellation(disable_cancellation& d)
+ {
+ if(d.cancel_was_enabled)
+ {
+ get_current_thread_data()->cancel_enabled=true;
+ }
+ }
+
+ enable_cancellation::~enable_cancellation()
+ {
+ if(get_current_thread_data())
+ {
+ get_current_thread_data()->cancel_enabled=false;
+ }
+ }
+ }
-void thread_group::remove_thread(thread* thrd)
-{
- mutex::scoped_lock scoped_lock(m_mutex);
+ namespace detail
+ {
+ struct thread_exit_callback_node
+ {
+ boost::detail::thread_exit_function_base* func;
+ thread_exit_callback_node* next;
+ };
+ }
+ namespace
+ {
+ void NTAPI thread_exit_func_callback(HINSTANCE, DWORD, PVOID);
+ typedef void (NTAPI* tls_callback)(HINSTANCE, DWORD, PVOID);
+
+#ifdef _MSC_VER
+ extern "C"
+ {
+ extern DWORD _tls_used; //the tls directory (located in .rdata segment)
+ extern tls_callback __xl_a[], __xl_z[]; //tls initializers */
+ }
+
+#if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
+# pragma data_seg(push, old_seg)
+#endif
+
+#pragma data_seg(".CRT$XLB")
+ tls_callback p_thread_callback = thread_exit_func_callback;
+#pragma data_seg()
+
+#if (_MSC_VER >= 1300) // 1300 == VC++ 7.0
+# pragma data_seg(pop, old_seg)
+#endif
+#endif
- // 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);
-}
+ void NTAPI thread_exit_func_callback(HINSTANCE h, DWORD dwReason, PVOID pv)
+ {
+ if((dwReason==DLL_THREAD_DETACH) || (dwReason==DLL_PROCESS_DETACH))
+ {
+ if(boost::detail::thread_data_base* const current_thread_data=get_current_thread_data())
+ {
+ while(current_thread_data->thread_exit_callbacks)
+ {
+ detail::thread_exit_callback_node* const current_node=current_thread_data->thread_exit_callbacks;
+ current_thread_data->thread_exit_callbacks=current_node->next;
+ if(current_node->func)
+ {
+ (*current_node->func)();
+ boost::detail::heap_delete(current_node->func);
+ }
+ boost::detail::heap_delete(current_node);
+ }
+ }
+ }
+ }
+ }
-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)
+ namespace detail
{
- (*it)->join();
+ void add_thread_exit_function(thread_exit_function_base* func)
+ {
+ thread_exit_callback_node* const new_node=heap_new<thread_exit_callback_node>();
+ new_node->func=func;
+ new_node->next=get_current_thread_data()->thread_exit_callbacks;
+ get_current_thread_data()->thread_exit_callbacks=new_node;
+ }
}
}
-int thread_group::size() const
-{
- return m_threads.size();
-}
-
-} // namespace boost
Deleted: trunk/libs/thread/src/xtime.cpp
==============================================================================
--- trunk/libs/thread/src/xtime.cpp 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
+++ (empty file)
@@ -1,158 +0,0 @@
-// Copyright (C) 2001-2003
-// William E. Kempf
-//
-// 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)
-
-#include <boost/thread/detail/config.hpp>
-
-#if defined(BOOST_HAS_FTIME)
-# define __STDC_CONSTANT_MACROS
-#endif
-
-#include <boost/thread/xtime.hpp>
-
-#if defined(BOOST_HAS_FTIME)
-# include <windows.h>
-# include <boost/cstdint.hpp>
-#elif defined(BOOST_HAS_GETTIMEOFDAY)
-# include <sys/time.h>
-#elif defined(BOOST_HAS_MPTASKS)
-# include <DriverServices.h>
-# include <boost/thread/detail/force_cast.hpp>
-#endif
-
-#include <cassert>
-
-namespace boost {
-
-#ifdef BOOST_HAS_MPTASKS
-
-namespace detail
-{
-
-using thread::force_cast;
-
-struct startup_time_info
-{
- startup_time_info()
- {
- // 1970 Jan 1 at 00:00:00
- static const DateTimeRec k_sUNIXBase = {1970, 1, 1, 0, 0, 0, 0};
- static unsigned long s_ulUNIXBaseSeconds = 0UL;
-
- if(s_ulUNIXBaseSeconds == 0UL)
- {
- // calculate the number of seconds between the Mac OS base and the
- // UNIX base the first time we enter this constructor.
- DateToSeconds(&k_sUNIXBase, &s_ulUNIXBaseSeconds);
- }
-
- unsigned long ulSeconds;
-
- // get the time in UpTime units twice, with the time in seconds in the
- // middle.
- uint64_t ullFirstUpTime = force_cast<uint64_t>(UpTime());
- GetDateTime(&ulSeconds);
- uint64_t ullSecondUpTime = force_cast<uint64_t>(UpTime());
-
- // calculate the midpoint of the two UpTimes, and save that.
- uint64_t ullAverageUpTime = (ullFirstUpTime + ullSecondUpTime) / 2ULL;
- m_sStartupAbsoluteTime = force_cast<AbsoluteTime>(ullAverageUpTime);
-
- // save the number of seconds, recentered at the UNIX base.
- m_ulStartupSeconds = ulSeconds - s_ulUNIXBaseSeconds;
- }
-
- AbsoluteTime m_sStartupAbsoluteTime;
- UInt32 m_ulStartupSeconds;
-};
-
-static startup_time_info g_sStartupTimeInfo;
-
-} // namespace detail
-
-#endif
-
-
-int xtime_get(struct xtime* xtp, int clock_type)
-{
- if (clock_type == TIME_UTC)
- {
-#if defined(BOOST_HAS_FTIME)
- FILETIME ft;
-# if defined(BOOST_NO_GETSYSTEMTIMEASFILETIME)
- {
- SYSTEMTIME st;
- GetSystemTime(&st);
- SystemTimeToFileTime(&st,&ft);
- }
-# else
- GetSystemTimeAsFileTime(&ft);
-# endif
- static const boost::uint64_t TIMESPEC_TO_FILETIME_OFFSET =
- UINT64_C(116444736000000000);
-
- const boost::uint64_t ft64 =
- (static_cast<boost::uint64_t>(ft.dwHighDateTime) << 32)
- + ft.dwLowDateTime;
-
- xtp->sec = static_cast<xtime::xtime_sec_t>(
- (ft64 - TIMESPEC_TO_FILETIME_OFFSET) / 10000000
- );
-
- xtp->nsec = static_cast<xtime::xtime_nsec_t>(
- ((ft64 - TIMESPEC_TO_FILETIME_OFFSET) % 10000000) * 100
- );
-
- return clock_type;
-#elif defined(BOOST_HAS_GETTIMEOFDAY)
- struct timeval tv;
-# ifndef NDEBUG
- int res =
-#endif
- gettimeofday(&tv, 0);
- assert(0 == res);
- assert(tv.tv_sec >= 0);
- assert(tv.tv_usec >= 0);
- xtp->sec = tv.tv_sec;
- xtp->nsec = tv.tv_usec * 1000;
- return clock_type;
-#elif defined(BOOST_HAS_CLOCK_GETTIME)
- timespec ts;
-# ifndef NDEBUG
- int res =
-# endif
- clock_gettime(CLOCK_REALTIME, &ts);
- assert(0 == res);
- xtp->sec = ts.tv_sec;
- xtp->nsec = ts.tv_nsec;
- return clock_type;
-#elif defined(BOOST_HAS_MPTASKS)
- using detail::thread::force_cast;
- // the Mac OS does not have an MP-safe way of getting the date/time,
- // so we use a delta from the startup time. We _could_ defer this
- // and use something that is interrupt-safe, but this would be _SLOW_,
- // and we need speed here.
- const uint64_t k_ullNanosecondsPerSecond(1000ULL * 1000ULL * 1000ULL);
- AbsoluteTime sUpTime(UpTime());
- uint64_t ullNanoseconds(
- force_cast<uint64_t>(
- AbsoluteDeltaToNanoseconds(sUpTime,
- detail::g_sStartupTimeInfo.m_sStartupAbsoluteTime)));
- uint64_t ullSeconds = (ullNanoseconds / k_ullNanosecondsPerSecond);
- ullNanoseconds -= (ullSeconds * k_ullNanosecondsPerSecond);
- xtp->sec = detail::g_sStartupTimeInfo.m_ulStartupSeconds + ullSeconds;
- xtp->nsec = ullNanoseconds;
- return clock_type;
-#else
-# error "xtime_get implementation undefined"
-#endif
- }
- return 0;
-}
-
-} // namespace boost
-
-// Change Log:
-// 8 Feb 01 WEKEMPF Initial version.
Modified: trunk/libs/thread/test/test_shared_mutex.cpp
==============================================================================
--- trunk/libs/thread/test/test_shared_mutex.cpp (original)
+++ trunk/libs/thread/test/test_shared_mutex.cpp 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
@@ -9,6 +9,8 @@
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/xtime.hpp>
#include "util.inl"
+#include <iostream>
+#include <boost/date_time/posix_time/posix_time_io.hpp>
#define CHECK_LOCKED_VALUE_EQUAL(mutex_name,value,expected_value) \
{ \
@@ -37,10 +39,10 @@
unsigned& max_simultaneous_running_):
rw_mutex(rw_mutex_),
unblocked_count(unblocked_count_),
- unblocked_count_mutex(unblocked_count_mutex_),
- finish_mutex(finish_mutex_),
simultaneous_running_count(simultaneous_running_count_),
- max_simultaneous_running(max_simultaneous_running_)
+ max_simultaneous_running(max_simultaneous_running_),
+ unblocked_count_mutex(unblocked_count_mutex_),
+ finish_mutex(finish_mutex_)
{}
void operator()()
@@ -129,7 +131,7 @@
pool.join_all();
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads);
- CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1);
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u);
}
void test_reader_blocks_writer()
@@ -156,7 +158,7 @@
pool.join_all();
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,2U);
- CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1);
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u);
}
void test_unlocking_writer_unblocks_all_readers()
@@ -218,19 +220,19 @@
{
pool.create_thread(locking_thread<boost::unique_lock<boost::shared_mutex> >(rw_mutex,unblocked_count,unblocked_count_mutex,finish_writing_mutex,simultaneous_running_writers,max_simultaneous_writers));
}
- boost::thread::sleep(delay(1));
+ boost::thread::sleep(delay(2));
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count);
finish_reading_lock.unlock();
- boost::thread::sleep(delay(1));
+ boost::thread::sleep(delay(2));
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+1);
finish_writing_lock.unlock();
pool.join_all();
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,reader_count+writer_count);
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_readers,reader_count);
- CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_writers,1);
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_writers,1u);
}
void test_only_one_upgrade_lock_permitted()
@@ -261,7 +263,7 @@
pool.join_all();
CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,unblocked_count,number_of_threads);
- CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1);
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_count_mutex,max_simultaneous_running,1u);
}
void test_can_lock_upgrade_if_currently_locked_shared()
@@ -334,7 +336,7 @@
boost::mutex::scoped_lock finish_lock(finish_mutex);
boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
boost::thread::sleep(delay(1));
- CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1);
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
bool const try_succeeded=rw_mutex.try_lock_shared();
BOOST_CHECK(!try_succeeded);
@@ -400,7 +402,7 @@
boost::mutex::scoped_lock finish_lock(finish_mutex);
boost::thread writer(simple_reading_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
boost::thread::sleep(delay(1));
- CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1);
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
bool const try_succeeded=rw_mutex.try_lock_shared();
BOOST_CHECK(try_succeeded);
@@ -422,12 +424,18 @@
boost::mutex::scoped_lock finish_lock(finish_mutex);
boost::thread writer(simple_writing_thread(rw_mutex,finish_mutex,unblocked_mutex,unblocked_count));
boost::thread::sleep(delay(1));
- CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1);
+ CHECK_LOCKED_VALUE_EQUAL(unblocked_mutex,unblocked_count,1u);
boost::system_time const start=boost::get_system_time();
boost::system_time const timeout=start+boost::posix_time::milliseconds(100);
bool const timed_lock_succeeded=rw_mutex.timed_lock_shared(timeout);
- BOOST_CHECK(timeout<=boost::get_system_time());
+ boost::system_time const wakeup=boost::get_system_time();
+ BOOST_CHECK(timeout<=(wakeup+boost::posix_time::milliseconds(1)));
+ if(timeout>wakeup)
+ {
+ std::cout<<"timeout="<<timeout<<", wakeup="<<wakeup<<std::endl;
+ }
+
BOOST_CHECK(!timed_lock_succeeded);
if(timed_lock_succeeded)
{
Modified: trunk/libs/thread/test/test_thread.cpp
==============================================================================
--- trunk/libs/thread/test/test_thread.cpp (original)
+++ trunk/libs/thread/test/test_thread.cpp 2007-10-23 04:57:17 EDT (Tue, 23 Oct 2007)
@@ -21,12 +21,16 @@
test_value = 999;
}
-void comparison_thread(boost::thread* parent)
+void comparison_thread(boost::thread::id parent)
{
- boost::thread thrd;
- BOOST_CHECK(thrd != *parent);
- boost::thread thrd2;
- BOOST_CHECK(thrd == thrd2);
+ boost::thread::id const my_id=boost::this_thread::get_id();
+
+ BOOST_CHECK(my_id != parent);
+ boost::thread::id const my_id2=boost::this_thread::get_id();
+ BOOST_CHECK(my_id == my_id2);
+
+ boost::thread::id const no_thread_id=boost::thread::id();
+ BOOST_CHECK(my_id != no_thread_id);
}
void test_sleep()
@@ -52,16 +56,16 @@
timed_test(&do_test_creation, 1);
}
-void do_test_comparison()
+void do_test_id_comparison()
{
- boost::thread self;
- boost::thread thrd(bind(&comparison_thread, &self));
+ boost::thread::id const self=boost::this_thread::get_id();
+ boost::thread thrd(bind(&comparison_thread, self));
thrd.join();
}
-void test_comparison()
+void test_id_comparison()
{
- timed_test(&do_test_comparison, 1);
+ timed_test(&do_test_id_comparison, 1);
}
boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[])
@@ -71,7 +75,7 @@
test->add(BOOST_TEST_CASE(test_sleep));
test->add(BOOST_TEST_CASE(test_creation));
- test->add(BOOST_TEST_CASE(test_comparison));
+ test->add(BOOST_TEST_CASE(test_id_comparison));
return test;
}
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