2
0
mirror of https://github.com/boostorg/thread.git synced 2026-02-11 12:12:12 +00:00

Patches for Codegear C++ Builder 2009

[SVN r48981]
This commit is contained in:
Nicola Musatti
2008-09-27 08:59:20 +00:00
96 changed files with 14151 additions and 1367 deletions

View File

@@ -1,19 +1,25 @@
// Copyright (C) 2001-2003
// William E. Kempf
// (C) Copyright 2008 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)
// See www.boost.org/libs/thread for documentation.
#if !defined(BOOST_THREAD_WEK01082003_HPP)
#define BOOST_THREAD_WEK01082003_HPP
#include <boost/thread/thread.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/once.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/tss.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/barrier.hpp>
#endif

View File

@@ -1,5 +1,6 @@
// Copyright (C) 2002-2003
// David Moore, William E. Kempf
// Copyright (C) 2007-8 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)
@@ -10,35 +11,53 @@
#include <boost/thread/detail/config.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/condition_variable.hpp>
#include <string>
#include <stdexcept>
namespace boost {
#include <boost/config/abi_prefix.hpp>
class BOOST_THREAD_DECL barrier
namespace boost
{
public:
barrier(unsigned int count);
~barrier();
bool wait();
class barrier
{
public:
barrier(unsigned int count)
: m_threshold(count), m_count(count), m_generation(0)
{
if (count == 0)
throw std::invalid_argument("count cannot be zero.");
}
bool wait()
{
boost::mutex::scoped_lock lock(m_mutex);
unsigned int gen = m_generation;
if (--m_count == 0)
{
m_generation++;
m_count = m_threshold;
m_cond.notify_all();
return true;
}
private:
mutex m_mutex;
// 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
condition m_cond;
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
unsigned int m_threshold;
unsigned int m_count;
unsigned int m_generation;
};
while (gen == m_generation)
m_cond.wait(lock);
return false;
}
private:
mutex m_mutex;
condition_variable m_cond;
unsigned int m_threshold;
unsigned int m_count;
unsigned int m_generation;
};
} // namespace boost
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,197 +1,16 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright (C) 2007 Anthony Williams
#ifndef BOOST_THREAD_CONDITION_HPP
#define BOOST_THREAD_CONDITION_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)
// 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_CONDITION_WEK070601_HPP
#define BOOST_CONDITION_WEK070601_HPP
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/detail/config.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/utility.hpp>
#include <boost/thread/detail/lock.hpp>
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
#elif defined(BOOST_HAS_MPTASKS)
# include "scoped_critical_region.hpp"
#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
namespace detail {
class BOOST_THREAD_DECL condition_impl : private noncopyable
namespace boost
{
friend class condition;
typedef condition_variable_any condition;
}
public:
condition_impl();
~condition_impl();
void notify_one();
void notify_all();
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
void enter_wait();
void do_wait();
bool do_timed_wait(const xtime& xt);
#elif defined(BOOST_HAS_PTHREADS)
void do_wait(pthread_mutex_t* pmutex);
bool do_timed_wait(const xtime& xt, pthread_mutex_t* pmutex);
#endif
#if defined(BOOST_HAS_WINTHREADS)
void* m_gate;
void* m_queue;
void* m_mutex;
unsigned m_gone; // # threads that timed out and never made it to m_queue
unsigned long m_blocked; // # threads blocked on the condition
unsigned m_waiting; // # threads no longer waiting for the condition but
// still waiting to be removed from m_queue
#elif defined(BOOST_HAS_PTHREADS)
pthread_cond_t m_condition;
pthread_mutex_t m_mutex;
#elif defined(BOOST_HAS_MPTASKS)
MPSemaphoreID m_gate;
MPSemaphoreID m_queue;
threads::mac::detail::scoped_critical_region m_mutex;
threads::mac::detail::scoped_critical_region m_mutex_mutex;
unsigned m_gone; // # threads that timed out and never made it to m_queue
unsigned long m_blocked; // # threads blocked on the condition
unsigned m_waiting; // # threads no longer waiting for the condition but
// still waiting to be removed from m_queue
#endif
};
} // namespace detail
class condition : private noncopyable
{
public:
condition() { }
~condition() { }
void notify_one() { m_impl.notify_one(); }
void notify_all() { m_impl.notify_all(); }
template <typename L>
void wait(L& lock)
{
if (!lock)
throw lock_error();
do_wait(*lock.mutex());
}
template <typename L, typename Pr>
void wait(L& lock, Pr pred)
{
if (!lock)
throw lock_error();
while (!pred())
do_wait(*lock.mutex());
}
template <typename L>
bool timed_wait(L& lock, const xtime& xt)
{
if (!lock)
throw lock_error();
return do_timed_wait(*lock.mutex(), xt);
}
template <typename L, typename Pr>
bool timed_wait(L& lock, const xtime& xt, Pr pred)
{
if (!lock)
throw lock_error();
while (!pred())
{
if (!do_timed_wait(*lock.mutex(), xt))
return false;
}
return true;
}
private:
detail::condition_impl m_impl;
template <typename M>
void do_wait(M& mutex)
{
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
m_impl.enter_wait();
#else
pthread_mutex_lock(&m_impl.m_mutex);
#endif
mutex.unlock();
#if defined(BOOST_HAS_PTHREADS)
m_impl.do_wait(&m_impl.m_mutex);
#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
m_impl.do_wait();
#endif
#if defined(BOOST_HAS_PTHREADS)
pthread_mutex_unlock(&m_impl.m_mutex);
#endif
mutex.lock();
}
template <typename M>
bool do_timed_wait(M& mutex, const xtime& xt)
{
#if (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
m_impl.enter_wait();
#else
pthread_mutex_lock(&m_impl.m_mutex);
#endif
mutex.unlock();
bool ret = false;
#if defined(BOOST_HAS_PTHREADS)
ret = m_impl.do_timed_wait(xt, &m_impl.m_mutex);
#elif (defined(BOOST_HAS_WINTHREADS) || defined(BOOST_HAS_MPTASKS))
ret = m_impl.do_timed_wait(xt);
#endif
#if defined(BOOST_HAS_PTHREADS)
pthread_mutex_unlock(&m_impl.m_mutex);
#endif
mutex.lock();
return ret;
}
};
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
} // namespace boost
// Change Log:
// 8 Feb 01 WEKEMPF Initial version.
// 22 May 01 WEKEMPF Modified to use xtime for time outs.
// 23 May 01 WEKEMPF Removed "duration" timed_waits, as they are too
// difficult to use with spurious wakeups.
// 3 Jan 03 WEKEMPF Modified for DLL implementation.
#endif // BOOST_CONDITION_WEK070601_HPP

View File

@@ -0,0 +1,21 @@
#ifndef BOOST_THREAD_CONDITION_VARIABLE_HPP
#define BOOST_THREAD_CONDITION_VARIABLE_HPP
// condition_variable.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)
#include <boost/thread/detail/platform.hpp>
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#include <boost/thread/win32/condition_variable.hpp>
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
#include <boost/thread/pthread/condition_variable.hpp>
#else
#error "Boost threads unavailable on this platform"
#endif
#endif

View File

@@ -17,8 +17,7 @@
# pragma warn -8066 // Unreachable code
#endif
// insist on threading support being available:
#include <boost/config/requires_threads.hpp>
#include "platform.hpp"
// compatibility with the rest of Boost's auto-linking code:
#if defined(BOOST_THREAD_DYN_DLL) || defined(BOOST_ALL_DYN_LINK)
@@ -31,7 +30,7 @@
#elif defined(BOOST_THREAD_USE_DLL) //Use dll
#elif defined(BOOST_THREAD_USE_LIB) //Use lib
#else //Use default
# if defined(BOOST_HAS_WINTHREADS)
# if defined(BOOST_THREAD_PLATFORM_WIN32)
# if defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)
//For compilers supporting auto-tss cleanup
//with Boost.Threads lib, use Boost.Threads lib

View File

@@ -1,33 +1,60 @@
// 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
// (C) Copyright 2007-8 Anthony Williams
#ifndef BOOST_THREAD_MOVE_HPP
#define BOOST_THREAD_MOVE_HPP
#ifndef BOOST_NO_SFINAE
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_convertible.hpp>
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
template<typename T>
struct move_t
namespace detail
{
T& t;
move_t(T& t_):
t(t_)
{}
T* operator->() const
template<typename T>
struct thread_move_t
{
return &t;
}
};
T& t;
explicit thread_move_t(T& t_):
t(t_)
{}
template<typename T>
move_t<T> move(T& t)
{
return move_t<T>(t);
T& operator*() const
{
return t;
}
T* operator->() const
{
return &t;
}
private:
void operator=(thread_move_t&);
};
}
#ifndef BOOST_NO_SFINAE
template<typename T>
typename enable_if<boost::is_convertible<T&,detail::thread_move_t<T> >, detail::thread_move_t<T> >::type move(T& t)
{
return t;
}
#endif
template<typename T>
detail::thread_move_t<T> move(detail::thread_move_t<T> t)
{
return t;
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,4 +1,5 @@
// Copyright 2006 Roland Schwarz.
// (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)
@@ -41,9 +42,9 @@
#elif defined(__QNXNTO__)
# define BOOST_THREAD_QNXNTO
#elif defined(unix) || defined(__unix) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE)
# if defined(BOOST_HAS_PTHREADS) && !defined(BOOST_THREAD_POSIX)
# define BOOST_THREAD_POSIX
# endif
# if defined(BOOST_HAS_PTHREADS) && !defined(BOOST_THREAD_POSIX)
# define BOOST_THREAD_POSIX
# endif
#endif
// For every supported platform add a new entry into the dispatch table below.
@@ -56,17 +57,15 @@
// available the preprocessor will fail with a diagnostic message.
#if defined(BOOST_THREAD_POSIX)
# define BOOST_THREAD_PPFX pthread
# define BOOST_THREAD_PLATFORM_PTHREAD
#else
# if defined(BOOST_THREAD_WIN32)
# define BOOST_THREAD_PPFX win32
# define BOOST_THREAD_PLATFORM_WIN32
# elif defined(BOOST_HAS_PTHREADS)
# define BOOST_THREAD_PPFX pthread
# define BOOST_THREAD_PLATFORM_PTHREAD
# else
# error "Sorry, no boost threads are available for this platform."
# endif
#endif
#define BOOST_THREAD_PLATFORM(header) <boost/thread/BOOST_THREAD_PPFX/header>
#endif // BOOST_THREAD_RS06040501_HPP

View File

@@ -0,0 +1,575 @@
#ifndef BOOST_THREAD_THREAD_COMMON_HPP
#define BOOST_THREAD_THREAD_COMMON_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-8 Anthony Williams
#include <boost/thread/exceptions.hpp>
#include <ostream>
#include <boost/thread/detail/move.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/thread/detail/thread_heap_alloc.hpp>
#include <boost/utility.hpp>
#include <boost/assert.hpp>
#include <list>
#include <algorithm>
#include <boost/ref.hpp>
#include <boost/cstdint.hpp>
#include <boost/bind.hpp>
#include <stdlib.h>
#include <memory>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/config/abi_prefix.hpp>
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4251)
#endif
namespace boost
{
namespace detail
{
template<typename F>
class thread_data:
public detail::thread_data_base
{
public:
#ifdef BOOST_HAS_RVALUE_REFS
thread_data(F&& f_):
f(static_cast<F&&>(f_))
{}
#else
thread_data(F f_):
f(f_)
{}
thread_data(detail::thread_move_t<F> f_):
f(f_)
{}
#endif
void run()
{
f();
}
private:
F f;
void operator=(thread_data&);
thread_data(thread_data&);
};
template<typename F>
class thread_data<boost::reference_wrapper<F> >:
public detail::thread_data_base
{
private:
F& f;
void operator=(thread_data&);
thread_data(thread_data&);
public:
thread_data(boost::reference_wrapper<F> f_):
f(f_)
{}
void run()
{
f();
}
};
template<typename F>
class thread_data<const boost::reference_wrapper<F> >:
public detail::thread_data_base
{
private:
F& f;
void operator=(thread_data&);
thread_data(thread_data&);
public:
thread_data(const boost::reference_wrapper<F> f_):
f(f_)
{}
void run()
{
f();
}
};
}
class BOOST_THREAD_DECL thread
{
private:
thread(thread&);
thread& operator=(thread&);
void release_handle();
mutable boost::mutex thread_info_mutex;
detail::thread_data_ptr thread_info;
void start_thread();
explicit thread(detail::thread_data_ptr data);
detail::thread_data_ptr get_thread_info() const;
#ifdef BOOST_HAS_RVALUE_REFS
template<typename F>
static inline detail::thread_data_ptr make_thread_info(F&& f)
{
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<typename boost::remove_reference<F>::type> >(static_cast<F&&>(f)));
}
static inline detail::thread_data_ptr make_thread_info(void (*f)())
{
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<void(*)()> >(f));
}
#else
template<typename F>
static inline detail::thread_data_ptr make_thread_info(F f)
{
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
}
template<typename F>
static inline detail::thread_data_ptr make_thread_info(boost::detail::thread_move_t<F> f)
{
return detail::thread_data_ptr(detail::heap_new<detail::thread_data<F> >(f));
}
struct dummy;
#endif
public:
thread();
~thread();
#ifdef BOOST_HAS_RVALUE_REFS
template <class F>
thread(F&& f):
thread_info(make_thread_info(static_cast<F&&>(f)))
{
start_thread();
}
thread(thread&& other)
{
thread_info.swap(other.thread_info);
}
thread& operator=(thread&& other)
{
thread_info=other.thread_info;
other.thread_info.reset();
return *this;
}
thread&& move()
{
return static_cast<thread&&>(*this);
}
#else
#ifdef BOOST_NO_SFINAE
template <class F>
explicit thread(F f):
thread_info(make_thread_info(f))
{
start_thread();
}
#else
template <class F>
explicit thread(F f,typename disable_if<boost::is_convertible<F&,detail::thread_move_t<F> >, dummy* >::type=0):
thread_info(make_thread_info(f))
{
start_thread();
}
#endif
template <class F>
explicit thread(detail::thread_move_t<F> f):
thread_info(make_thread_info(f))
{
start_thread();
}
thread(detail::thread_move_t<thread> x)
{
thread_info=x->thread_info;
x->thread_info.reset();
}
thread& operator=(detail::thread_move_t<thread> x)
{
thread new_thread(x);
swap(new_thread);
return *this;
}
operator detail::thread_move_t<thread>()
{
return move();
}
detail::thread_move_t<thread> move()
{
detail::thread_move_t<thread> x(*this);
return x;
}
#endif
template <class F,class A1>
thread(F f,A1 a1):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1)))
{
start_thread();
}
template <class F,class A1,class A2>
thread(F f,A1 a1,A2 a2):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2)))
{
start_thread();
}
template <class F,class A1,class A2,class A3>
thread(F f,A1 a1,A2 a2,A3 a3):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3)))
{
start_thread();
}
template <class F,class A1,class A2,class A3,class A4>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4)))
{
start_thread();
}
template <class F,class A1,class A2,class A3,class A4,class A5>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5)))
{
start_thread();
}
template <class F,class A1,class A2,class A3,class A4,class A5,class A6>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6)))
{
start_thread();
}
template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7)))
{
start_thread();
}
template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8)))
{
start_thread();
}
template <class F,class A1,class A2,class A3,class A4,class A5,class A6,class A7,class A8,class A9>
thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9):
thread_info(make_thread_info(boost::bind(boost::type<void>(),f,a1,a2,a3,a4,a5,a6,a7,a8,a9)))
{
start_thread();
}
void swap(thread& x)
{
thread_info.swap(x.thread_info);
}
class id;
id get_id() const;
bool joinable() const;
void join();
bool timed_join(const system_time& wait_until);
template<typename TimeDuration>
inline bool timed_join(TimeDuration const& rel_time)
{
return timed_join(get_system_time()+rel_time);
}
void detach();
static unsigned hardware_concurrency();
typedef detail::thread_data_base::native_handle_type native_handle_type;
native_handle_type native_handle();
// backwards compatibility
bool operator==(const thread& other) const;
bool operator!=(const thread& other) const;
static inline void yield()
{
this_thread::yield();
}
static inline void sleep(const system_time& xt)
{
this_thread::sleep(xt);
}
// extensions
void interrupt();
bool interruption_requested() const;
};
inline void swap(thread& lhs,thread& rhs)
{
return lhs.swap(rhs);
}
#ifdef BOOST_HAS_RVALUE_REFS
inline thread&& move(thread&& t)
{
return t;
}
#else
inline detail::thread_move_t<thread> move(detail::thread_move_t<thread> t)
{
return t;
}
#endif
namespace this_thread
{
class BOOST_THREAD_DECL disable_interruption
{
disable_interruption(const disable_interruption&);
disable_interruption& operator=(const disable_interruption&);
bool interruption_was_enabled;
friend class restore_interruption;
public:
disable_interruption();
~disable_interruption();
};
class BOOST_THREAD_DECL restore_interruption
{
restore_interruption(const restore_interruption&);
restore_interruption& operator=(const restore_interruption&);
public:
explicit restore_interruption(disable_interruption& d);
~restore_interruption();
};
thread::id BOOST_THREAD_DECL get_id();
void BOOST_THREAD_DECL interruption_point();
bool BOOST_THREAD_DECL interruption_enabled();
bool BOOST_THREAD_DECL interruption_requested();
inline void sleep(xtime const& abs_time)
{
sleep(system_time(abs_time));
}
}
class thread::id
{
private:
detail::thread_data_ptr thread_data;
id(detail::thread_data_ptr thread_data_):
thread_data(thread_data_)
{}
friend class thread;
friend id this_thread::get_id();
public:
id():
thread_data()
{}
bool operator==(const id& y) const
{
return thread_data==y.thread_data;
}
bool operator!=(const id& y) const
{
return thread_data!=y.thread_data;
}
bool operator<(const id& y) const
{
return thread_data<y.thread_data;
}
bool operator>(const id& y) const
{
return y.thread_data<thread_data;
}
bool operator<=(const id& y) const
{
return !(y.thread_data<thread_data);
}
bool operator>=(const id& y) const
{
return !(thread_data<y.thread_data);
}
template<class charT, class traits>
friend std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const id& x)
{
if(x.thread_data)
{
return os<<x.thread_data;
}
else
{
return os<<"{Not-any-thread}";
}
}
};
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();
}
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);
std::auto_ptr<thread> new_thread(new thread(threadfunc));
threads.push_back(new_thread.get());
return new_thread.release();
}
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();
}
}
void interrupt_all()
{
boost::lock_guard<mutex> guard(m);
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
it!=end;
++it)
{
(*it)->interrupt();
}
}
size_t size() const
{
boost::lock_guard<mutex> guard(m);
return threads.size();
}
private:
std::list<thread*> threads;
mutable mutex m;
};
}
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,23 @@
#ifndef BOOST_THREAD_THREAD_HEAP_ALLOC_HPP
#define BOOST_THREAD_THREAD_HEAP_ALLOC_HPP
// thread_heap_alloc.hpp
//
// (C) Copyright 2008 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/platform.hpp>
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#include <boost/thread/win32/thread_heap_alloc.hpp>
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
#include <boost/thread/pthread/thread_heap_alloc.hpp>
#else
#error "Boost threads unavailable on this platform"
#endif
#endif

View File

@@ -8,6 +8,8 @@
#include <boost/thread/detail/config.hpp>
#include <boost/config/abi_prefix.hpp>
#if defined(BOOST_HAS_WINTHREADS)
typedef void (__cdecl *thread_exit_handler)(void);
@@ -59,7 +61,7 @@
//a method for doing so has been discovered.
//May be omitted; may be called multiple times.
extern "C" BOOST_THREAD_DECL void on_thread_exit(void);
extern "C" BOOST_THREAD_DECL void __cdecl on_thread_exit(void);
//Function to be called just be fore a thread ends
//in an exe or dll that uses Boost.Threads.
//Must be called in the context of the thread
@@ -67,7 +69,7 @@
//Called automatically by Boost.Threads when
//a method for doing so has been discovered.
//Must not be omitted; may be called multiple times.
extern "C" void tss_cleanup_implemented(void);
//Dummy function used both to detect whether tss cleanup
//cleanup has been implemented and to force
@@ -75,4 +77,6 @@
#endif //defined(BOOST_HAS_WINTHREADS)
#include <boost/config/abi_suffix.hpp>
#endif //!defined(BOOST_TLS_HOOKS_HPP)

View File

@@ -1,5 +1,6 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright (C) 2007-8 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)
@@ -18,7 +19,13 @@
#include <string>
#include <stdexcept>
namespace boost {
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class BOOST_THREAD_DECL thread_interrupted
{};
class BOOST_THREAD_DECL thread_exception : public std::exception
{
@@ -35,6 +42,17 @@ private:
int m_sys_err;
};
class condition_error:
public std::exception
{
public:
const char* what() const throw()
{
return "Condition error";
}
};
class BOOST_THREAD_DECL lock_error : public thread_exception
{
public:
@@ -87,6 +105,8 @@ public:
} // namespace boost
#include <boost/config/abi_suffix.hpp>
#endif // BOOST_THREAD_CONFIG_PDM070801_H
// Change log:

File diff suppressed because it is too large Load Diff

View File

@@ -10,6 +10,12 @@
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/platform.hpp>
#include BOOST_THREAD_PLATFORM(mutex.hpp)
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#include <boost/thread/win32/mutex.hpp>
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
#include <boost/thread/pthread/mutex.hpp>
#else
#error "Boost threads unavailable on this platform"
#endif
#endif

View File

@@ -10,7 +10,15 @@
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/platform.hpp>
#include BOOST_THREAD_PLATFORM(once.hpp)
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#include <boost/thread/win32/once.hpp>
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
#include <boost/thread/pthread/once.hpp>
#else
#error "Boost threads unavailable on this platform"
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
@@ -20,4 +28,6 @@ namespace boost
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,176 @@
#ifndef BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP
#define BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007-8 Anthony Williams
#include "timespec.hpp"
#include "pthread_mutex_scoped_lock.hpp"
#include "thread_data.hpp"
#include "condition_variable_fwd.hpp"
#include <boost/config/abi_prefix.hpp>
namespace boost
{
inline void condition_variable::wait(unique_lock<mutex>& m)
{
detail::interruption_checker check_for_interruption(&cond);
BOOST_VERIFY(!pthread_cond_wait(&cond,m.mutex()->native_handle()));
}
inline bool condition_variable::timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until)
{
detail::interruption_checker check_for_interruption(&cond);
struct timespec const timeout=detail::get_timespec(wait_until);
int const cond_res=pthread_cond_timedwait(&cond,m.mutex()->native_handle(),&timeout);
if(cond_res==ETIMEDOUT)
{
return false;
}
BOOST_ASSERT(!cond_res);
return true;
}
inline void condition_variable::notify_one()
{
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
inline void condition_variable::notify_all()
{
BOOST_VERIFY(!pthread_cond_broadcast(&cond));
}
class condition_variable_any
{
pthread_mutex_t internal_mutex;
pthread_cond_t cond;
condition_variable_any(condition_variable&);
condition_variable_any& operator=(condition_variable&);
public:
condition_variable_any()
{
int const res=pthread_mutex_init(&internal_mutex,NULL);
if(res)
{
throw thread_resource_error();
}
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
throw thread_resource_error();
}
}
~condition_variable_any()
{
BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex));
BOOST_VERIFY(!pthread_cond_destroy(&cond));
}
template<typename lock_type>
void wait(lock_type& m)
{
int res=0;
{
detail::interruption_checker check_for_interruption(&cond);
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
m.unlock();
res=pthread_cond_wait(&cond,&internal_mutex);
}
m.lock();
}
if(res)
{
throw condition_error();
}
}
template<typename lock_type,typename predicate_type>
void wait(lock_type& m,predicate_type pred)
{
while(!pred()) wait(m);
}
template<typename lock_type>
bool timed_wait(lock_type& m,boost::system_time const& wait_until)
{
struct timespec const timeout=detail::get_timespec(wait_until);
int res=0;
{
detail::interruption_checker check_for_interruption(&cond);
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
m.unlock();
res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout);
}
m.lock();
}
if(res==ETIMEDOUT)
{
return false;
}
if(res)
{
throw condition_error();
}
return true;
}
template<typename lock_type>
bool timed_wait(lock_type& m,xtime const& wait_until)
{
return timed_wait(m,system_time(wait_until));
}
template<typename lock_type,typename duration_type>
bool timed_wait(lock_type& m,duration_type const& wait_duration)
{
return timed_wait(m,get_system_time()+wait_duration);
}
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred)
{
while (!pred())
{
if(!timed_wait(m, wait_until))
return pred();
}
return true;
}
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,xtime const& wait_until,predicate_type pred)
{
return timed_wait(m,system_time(wait_until),pred);
}
template<typename lock_type,typename duration_type,typename predicate_type>
bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
{
return timed_wait(m,get_system_time()+wait_duration,pred);
}
void notify_one()
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
void notify_all()
{
boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex);
BOOST_VERIFY(!pthread_cond_broadcast(&cond));
}
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,97 @@
#ifndef BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_HPP
#define BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_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-8 Anthony Williams
#include <boost/assert.hpp>
#include <pthread.h>
#include <boost/thread/mutex.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class condition_variable
{
private:
pthread_cond_t cond;
condition_variable(condition_variable&);
condition_variable& operator=(condition_variable&);
public:
condition_variable()
{
int const res=pthread_cond_init(&cond,NULL);
if(res)
{
throw thread_resource_error();
}
}
~condition_variable()
{
BOOST_VERIFY(!pthread_cond_destroy(&cond));
}
void wait(unique_lock<mutex>& m);
template<typename predicate_type>
void wait(unique_lock<mutex>& m,predicate_type pred)
{
while(!pred()) wait(m);
}
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until);
bool timed_wait(unique_lock<mutex>& m,xtime const& wait_until)
{
return timed_wait(m,system_time(wait_until));
}
template<typename duration_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration)
{
return timed_wait(m,get_system_time()+wait_duration);
}
template<typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until,predicate_type pred)
{
while (!pred())
{
if(!timed_wait(m, wait_until))
return pred();
}
return true;
}
template<typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,xtime const& wait_until,predicate_type pred)
{
return timed_wait(m,system_time(wait_until),pred);
}
template<typename duration_type,typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
{
return timed_wait(m,get_system_time()+wait_duration,pred);
}
typedef pthread_cond_t* native_handle_type;
native_handle_type native_handle()
{
return &cond;
}
void notify_one();
void notify_all();
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,6 +1,6 @@
#ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_MUTEX_HPP
// (C) Copyright 2007 Anthony Williams
// (C) Copyright 2007-8 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)
@@ -10,10 +10,11 @@
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/assert.hpp>
#include <unistd.h>
#include <errno.h>
#include "timespec.hpp"
#include "pthread_mutex_scoped_lock.hpp"
#ifdef _POSIX_TIMEOUTS
#if _POSIX_TIMEOUTS >= 0
@@ -21,6 +22,8 @@
#endif
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class mutex:
@@ -39,20 +42,17 @@ namespace boost
}
~mutex()
{
int const res=pthread_mutex_destroy(&m);
BOOST_ASSERT(!res);
BOOST_VERIFY(!pthread_mutex_destroy(&m));
}
void lock()
{
int const res=pthread_mutex_lock(&m);
BOOST_ASSERT(!res);
BOOST_VERIFY(!pthread_mutex_lock(&m));
}
void unlock()
{
int const res=pthread_mutex_unlock(&m);
BOOST_ASSERT(!res);
BOOST_VERIFY(!pthread_mutex_unlock(&m));
}
bool try_lock()
@@ -61,8 +61,15 @@ namespace boost
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
return &m;
}
typedef unique_lock<mutex> scoped_lock;
typedef scoped_lock scoped_try_lock;
typedef detail::try_lock_wrapper<mutex> scoped_try_lock;
};
typedef mutex try_mutex;
@@ -75,25 +82,6 @@ namespace boost
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
pthread_cond_t cond;
bool is_locked;
struct pthread_mutex_scoped_lock
{
pthread_mutex_t* m;
explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_):
m(m_)
{
int const res=pthread_mutex_lock(m);
BOOST_ASSERT(!res);
}
~pthread_mutex_scoped_lock()
{
int const res=pthread_mutex_unlock(m);
BOOST_ASSERT(!res);
}
};
#endif
public:
timed_mutex()
@@ -107,8 +95,7 @@ namespace boost
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
int const destroy_res=pthread_mutex_destroy(&m);
BOOST_ASSERT(!destroy_res);
BOOST_VERIFY(!pthread_mutex_destroy(&m));
throw thread_resource_error();
}
is_locked=false;
@@ -116,11 +103,9 @@ namespace boost
}
~timed_mutex()
{
int const res=pthread_mutex_destroy(&m);
BOOST_ASSERT(!res);
BOOST_VERIFY(!pthread_mutex_destroy(&m));
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
int const res2=pthread_cond_destroy(&cond);
BOOST_ASSERT(!res2);
BOOST_VERIFY(!pthread_cond_destroy(&cond));
#endif
}
@@ -129,18 +114,20 @@ namespace boost
{
return timed_lock(get_system_time()+relative_time);
}
bool timed_lock(boost::xtime const & absolute_time)
{
return timed_lock(system_time(absolute_time));
}
#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
void lock()
{
int const res=pthread_mutex_lock(&m);
BOOST_ASSERT(!res);
BOOST_VERIFY(!pthread_mutex_lock(&m));
}
void unlock()
{
int const res=pthread_mutex_unlock(&m);
BOOST_ASSERT(!res);
BOOST_VERIFY(!pthread_mutex_unlock(&m));
}
bool try_lock()
@@ -153,32 +140,37 @@ namespace boost
{
struct timespec const timeout=detail::get_timespec(abs_time);
int const res=pthread_mutex_timedlock(&m,&timeout);
BOOST_ASSERT(!res || res==EBUSY);
BOOST_ASSERT(!res || res==ETIMEDOUT);
return !res;
}
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
return &m;
}
#else
void lock()
{
pthread_mutex_scoped_lock const _(&m);
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
while(is_locked)
{
int const cond_res=pthread_cond_wait(&cond,&m);
BOOST_ASSERT(!cond_res);
BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
}
is_locked=true;
}
void unlock()
{
pthread_mutex_scoped_lock const _(&m);
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
is_locked=false;
int const res=pthread_cond_signal(&cond);
BOOST_ASSERT(!res);
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
bool try_lock()
{
pthread_mutex_scoped_lock const _(&m);
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(is_locked)
{
return false;
@@ -190,7 +182,7 @@ namespace boost
bool timed_lock(system_time const & abs_time)
{
struct timespec const timeout=detail::get_timespec(abs_time);
pthread_mutex_scoped_lock const _(&m);
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
while(is_locked)
{
int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout);
@@ -206,11 +198,13 @@ namespace boost
#endif
typedef unique_lock<timed_mutex> scoped_timed_lock;
typedef scoped_timed_lock scoped_try_lock;
typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -3,7 +3,7 @@
// once.hpp
//
// (C) Copyright 2007 Anthony Williams
// (C) Copyright 2007-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -13,62 +13,78 @@
#include <pthread.h>
#include <boost/assert.hpp>
#include "pthread_mutex_scoped_lock.hpp"
#include <boost/thread/pthread/pthread_mutex_scoped_lock.hpp>
#include <boost/cstdint.hpp>
namespace boost {
#include <boost/config/abi_prefix.hpp>
namespace boost
{
struct once_flag
{
pthread_mutex_t mutex;
unsigned flag;
boost::uintmax_t epoch;
};
#define BOOST_ONCE_INIT {PTHREAD_MUTEX_INITIALIZER,0}
namespace detail
{
struct pthread_mutex_scoped_lock
{
pthread_mutex_t * mutex;
explicit pthread_mutex_scoped_lock(pthread_mutex_t* mutex_):
mutex(mutex_)
{
int const res=pthread_mutex_lock(mutex);
BOOST_ASSERT(!res);
}
~pthread_mutex_scoped_lock()
{
int const res=pthread_mutex_unlock(mutex);
BOOST_ASSERT(!res);
}
};
BOOST_THREAD_DECL boost::uintmax_t& get_once_per_thread_epoch();
BOOST_THREAD_DECL extern boost::uintmax_t once_global_epoch;
BOOST_THREAD_DECL extern pthread_mutex_t once_epoch_mutex;
BOOST_THREAD_DECL extern pthread_cond_t once_epoch_cv;
}
#define BOOST_ONCE_INITIAL_FLAG_VALUE 0
#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE}
// Based on Mike Burrows fast_pthread_once algorithm as described in
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html
template<typename Function>
void call_once(once_flag& flag,Function f)
{
long const function_complete_flag_value=0xc15730e2;
#ifdef BOOST_PTHREAD_HAS_ATOMICS
if(::boost::detail::interlocked_read_acquire(&flag.flag)!=function_complete_flag_value)
static boost::uintmax_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE;
static boost::uintmax_t const being_initialized=uninitialized_flag+1;
boost::uintmax_t const epoch=flag.epoch;
boost::uintmax_t& this_thread_epoch=detail::get_once_per_thread_epoch();
if(epoch<this_thread_epoch)
{
#endif
detail::pthread_mutex_scoped_lock const lock(&flag.mutex);
if(flag.flag!=function_complete_flag_value)
{
f();
#ifdef BOOST_PTHREAD_HAS_ATOMICS
::boost::detail::interlocked_write_release(&flag.flag,function_complete_flag_value);
#else
flag.flag=function_complete_flag_value;
#endif
}
#ifdef BOOST_PTHREAD_HAS_ATOMICS
}
#endif
}
pthread::pthread_mutex_scoped_lock lk(&detail::once_epoch_mutex);
while(flag.epoch<=being_initialized)
{
if(flag.epoch==uninitialized_flag)
{
flag.epoch=being_initialized;
try
{
pthread::pthread_mutex_scoped_unlock relocker(&detail::once_epoch_mutex);
f();
}
catch(...)
{
flag.epoch=uninitialized_flag;
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
throw;
}
flag.epoch=--detail::once_global_epoch;
BOOST_VERIFY(!pthread_cond_broadcast(&detail::once_epoch_cv));
}
else
{
while(flag.epoch==being_initialized)
{
BOOST_VERIFY(!pthread_cond_wait(&detail::once_epoch_cv,&detail::once_epoch_mutex));
}
}
}
this_thread_epoch=detail::once_global_epoch;
}
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,54 @@
#ifndef BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP
#define BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP
// (C) Copyright 2007-8 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 <pthread.h>
#include <boost/assert.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace pthread
{
class pthread_mutex_scoped_lock
{
pthread_mutex_t* m;
public:
explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_):
m(m_)
{
BOOST_VERIFY(!pthread_mutex_lock(m));
}
~pthread_mutex_scoped_lock()
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
}
};
class pthread_mutex_scoped_unlock
{
pthread_mutex_t* m;
public:
explicit pthread_mutex_scoped_unlock(pthread_mutex_t* m_):
m(m_)
{
BOOST_VERIFY(!pthread_mutex_unlock(m));
}
~pthread_mutex_scoped_unlock()
{
BOOST_VERIFY(!pthread_mutex_lock(m));
}
};
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,6 +1,6 @@
#ifndef BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP
// (C) Copyright 2007 Anthony Williams
// (C) Copyright 2007-8 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)
@@ -11,10 +11,13 @@
#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"
#include "pthread_mutex_scoped_lock.hpp"
#ifdef _POSIX_TIMEOUTS
#if _POSIX_TIMEOUTS >= 0
@@ -22,6 +25,8 @@
#endif
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class recursive_mutex:
@@ -50,25 +55,21 @@ namespace boost
{
throw thread_resource_error();
}
int const destroy_attr_res=pthread_mutexattr_destroy(&attr);
BOOST_ASSERT(!destroy_attr_res);
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
}
~recursive_mutex()
{
int const res=pthread_mutex_destroy(&m);
BOOST_ASSERT(!res);
BOOST_VERIFY(!pthread_mutex_destroy(&m));
}
void lock()
{
int const res=pthread_mutex_lock(&m);
BOOST_ASSERT(!res);
BOOST_VERIFY(!pthread_mutex_lock(&m));
}
void unlock()
{
int const res=pthread_mutex_unlock(&m);
BOOST_ASSERT(!res);
BOOST_VERIFY(!pthread_mutex_unlock(&m));
}
bool try_lock()
@@ -77,8 +78,15 @@ namespace boost
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
return &m;
}
typedef unique_lock<recursive_mutex> scoped_lock;
typedef scoped_lock scoped_try_lock;
typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
};
typedef recursive_mutex recursive_try_mutex;
@@ -93,25 +101,6 @@ namespace boost
bool is_locked;
pthread_t owner;
unsigned count;
struct pthread_mutex_scoped_lock
{
pthread_mutex_t* m;
explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_):
m(m_)
{
int const res=pthread_mutex_lock(m);
BOOST_ASSERT(!res);
}
~pthread_mutex_scoped_lock()
{
int const res=pthread_mutex_unlock(m);
BOOST_ASSERT(!res);
}
};
#endif
public:
recursive_timed_mutex()
@@ -133,12 +122,10 @@ namespace boost
int const res=pthread_mutex_init(&m,&attr);
if(res)
{
int const destroy_attr_res=pthread_mutexattr_destroy(&attr);
BOOST_ASSERT(!destroy_attr_res);
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
throw thread_resource_error();
}
int const destroy_attr_res=pthread_mutexattr_destroy(&attr);
BOOST_ASSERT(!destroy_attr_res);
BOOST_VERIFY(!pthread_mutexattr_destroy(&attr));
#else
int const res=pthread_mutex_init(&m,NULL);
if(res)
@@ -148,8 +135,7 @@ namespace boost
int const res2=pthread_cond_init(&cond,NULL);
if(res2)
{
int const destroy_res=pthread_mutex_destroy(&m);
BOOST_ASSERT(!destroy_res);
BOOST_VERIFY(!pthread_mutex_destroy(&m));
throw thread_resource_error();
}
is_locked=false;
@@ -158,11 +144,9 @@ namespace boost
}
~recursive_timed_mutex()
{
int const res=pthread_mutex_destroy(&m);
BOOST_ASSERT(!res);
BOOST_VERIFY(!pthread_mutex_destroy(&m));
#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK
int const res2=pthread_cond_destroy(&cond);
BOOST_ASSERT(!res2);
BOOST_VERIFY(!pthread_cond_destroy(&cond));
#endif
}
@@ -175,14 +159,12 @@ namespace boost
#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK
void lock()
{
int const res=pthread_mutex_lock(&m);
BOOST_ASSERT(!res);
BOOST_VERIFY(!pthread_mutex_lock(&m));
}
void unlock()
{
int const res=pthread_mutex_unlock(&m);
BOOST_ASSERT(!res);
BOOST_VERIFY(!pthread_mutex_unlock(&m));
}
bool try_lock()
@@ -198,11 +180,18 @@ namespace boost
BOOST_ASSERT(!res || res==EBUSY);
return !res;
}
typedef pthread_mutex_t* native_handle_type;
native_handle_type native_handle()
{
return &m;
}
#else
void lock()
{
pthread_mutex_scoped_lock const _(&m);
if(is_locked && owner==pthread_self())
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(is_locked && pthread_equal(owner,pthread_self()))
{
++count;
return;
@@ -210,8 +199,7 @@ namespace boost
while(is_locked)
{
int const cond_res=pthread_cond_wait(&cond,&m);
BOOST_ASSERT(!cond_res);
BOOST_VERIFY(!pthread_cond_wait(&cond,&m));
}
is_locked=true;
++count;
@@ -220,19 +208,18 @@ namespace boost
void unlock()
{
pthread_mutex_scoped_lock const _(&m);
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(!--count)
{
is_locked=false;
}
int const res=pthread_cond_signal(&cond);
BOOST_ASSERT(!res);
BOOST_VERIFY(!pthread_cond_signal(&cond));
}
bool try_lock()
{
pthread_mutex_scoped_lock const _(&m);
if(is_locked && owner!=pthread_self())
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(is_locked && !pthread_equal(owner,pthread_self()))
{
return false;
}
@@ -245,8 +232,8 @@ namespace boost
bool timed_lock(system_time const & abs_time)
{
struct timespec const timeout=detail::get_timespec(abs_time);
pthread_mutex_scoped_lock const _(&m);
if(is_locked && owner==pthread_self())
boost::pthread::pthread_mutex_scoped_lock const local_lock(&m);
if(is_locked && pthread_equal(owner,pthread_self()))
{
++count;
return true;
@@ -268,11 +255,12 @@ namespace boost
#endif
typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
typedef scoped_timed_lock scoped_try_lock;
typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,7 +1,7 @@
#ifndef BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
#define BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP
// (C) Copyright 2006-7 Anthony Williams
// (C) Copyright 2006-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -10,8 +10,10 @@
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
@@ -30,9 +32,9 @@ namespace boost
state_data state;
boost::mutex state_change;
boost::condition shared_cond;
boost::condition exclusive_cond;
boost::condition upgrade_cond;
boost::condition_variable shared_cond;
boost::condition_variable exclusive_cond;
boost::condition_variable upgrade_cond;
void release_waiters()
{
@@ -44,7 +46,7 @@ namespace boost
public:
shared_mutex()
{
state_data state_={0};
state_data state_={0,0,0,0};
state=state_;
}
@@ -54,18 +56,14 @@ namespace boost
void lock_shared()
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lock(state_change);
while(true)
while(state.exclusive || state.exclusive_waiting_blocked)
{
if(!state.exclusive && !state.exclusive_waiting_blocked)
{
++state.shared_count;
return;
}
shared_cond.wait(lock);
}
++state.shared_count;
}
bool try_lock_shared()
@@ -85,21 +83,24 @@ namespace boost
bool timed_lock_shared(system_time const& timeout)
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lock(state_change);
while(true)
while(state.exclusive || state.exclusive_waiting_blocked)
{
if(!state.exclusive && !state.exclusive_waiting_blocked)
{
++state.shared_count;
return true;
}
if(!shared_cond.timed_wait(lock,get_xtime(timeout)))
if(!shared_cond.timed_wait(lock,timeout))
{
return false;
}
}
++state.shared_count;
return true;
}
template<typename TimeDuration>
bool timed_lock_shared(TimeDuration const & relative_time)
{
return timed_lock_shared(get_system_time()+relative_time);
}
void unlock_shared()
@@ -125,43 +126,44 @@ namespace boost
void lock()
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lock(state_change);
while(true)
while(state.shared_count || state.exclusive)
{
if(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=true;
}
else
{
state.exclusive=true;
return;
}
state.exclusive_waiting_blocked=true;
exclusive_cond.wait(lock);
}
state.exclusive=true;
}
bool timed_lock(system_time const& timeout)
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lock(state_change);
while(true)
while(state.shared_count || state.exclusive)
{
if(state.shared_count || state.exclusive)
state.exclusive_waiting_blocked=true;
if(!exclusive_cond.timed_wait(lock,timeout))
{
state.exclusive_waiting_blocked=true;
}
else
{
state.exclusive=true;
return true;
}
if(!exclusive_cond.timed_wait(lock,get_xtime(timeout)))
{
return false;
if(state.shared_count || state.exclusive)
{
state.exclusive_waiting_blocked=false;
exclusive_cond.notify_one();
return false;
}
break;
}
}
state.exclusive=true;
return true;
}
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time)
{
return timed_lock(get_system_time()+relative_time);
}
bool try_lock()
@@ -190,37 +192,40 @@ namespace boost
void lock_upgrade()
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lock(state_change);
while(true)
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
if(!state.exclusive && !state.exclusive_waiting_blocked && !state.upgrade)
{
++state.shared_count;
state.upgrade=true;
return;
}
shared_cond.wait(lock);
}
++state.shared_count;
state.upgrade=true;
}
bool timed_lock_upgrade(system_time const& timeout)
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lock(state_change);
while(true)
while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
if(!state.exclusive && !state.exclusive_waiting_blocked && !state.upgrade)
if(!shared_cond.timed_wait(lock,timeout))
{
++state.shared_count;
state.upgrade=true;
return true;
}
if(!shared_cond.timed_wait(lock,get_xtime(timeout)))
{
return false;
if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade)
{
return false;
}
break;
}
}
++state.shared_count;
state.upgrade=true;
return true;
}
template<typename TimeDuration>
bool timed_lock_upgrade(TimeDuration const & relative_time)
{
return timed_lock(get_system_time()+relative_time);
}
bool try_lock_upgrade()
@@ -253,18 +258,15 @@ namespace boost
void unlock_upgrade_and_lock()
{
boost::this_thread::disable_interruption do_not_disturb;
boost::mutex::scoped_lock lock(state_change);
--state.shared_count;
while(true)
while(state.shared_count)
{
if(!state.shared_count)
{
state.upgrade=false;
state.exclusive=true;
break;
}
upgrade_cond.wait(lock);
}
state.upgrade=false;
state.exclusive=true;
}
void unlock_and_lock_upgrade()
@@ -296,5 +298,6 @@ namespace boost
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,118 @@
#ifndef BOOST_THREAD_PTHREAD_THREAD_DATA_HPP
#define BOOST_THREAD_PTHREAD_THREAD_DATA_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/detail/config.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/optional.hpp>
#include <pthread.h>
#include "condition_variable_fwd.hpp"
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class thread;
namespace detail
{
struct thread_exit_callback_node;
struct tss_data_node;
struct thread_data_base;
typedef boost::shared_ptr<thread_data_base> thread_data_ptr;
struct BOOST_THREAD_DECL thread_data_base:
enable_shared_from_this<thread_data_base>
{
thread_data_ptr self;
pthread_t thread_handle;
boost::mutex data_mutex;
boost::condition_variable done_condition;
boost::mutex sleep_mutex;
boost::condition_variable sleep_condition;
bool done;
bool join_started;
bool joined;
boost::detail::thread_exit_callback_node* thread_exit_callbacks;
boost::detail::tss_data_node* tss_data;
bool interrupt_enabled;
bool interrupt_requested;
pthread_cond_t* current_cond;
thread_data_base():
done(false),join_started(false),joined(false),
thread_exit_callbacks(0),tss_data(0),
interrupt_enabled(true),
interrupt_requested(false),
current_cond(0)
{}
virtual ~thread_data_base();
typedef pthread_t native_handle_type;
virtual void run()=0;
};
BOOST_THREAD_DECL thread_data_base* get_current_thread_data();
class interruption_checker
{
thread_data_base* const thread_info;
void check_for_interruption()
{
if(thread_info->interrupt_requested)
{
thread_info->interrupt_requested=false;
throw thread_interrupted();
}
}
void operator=(interruption_checker&);
public:
explicit interruption_checker(pthread_cond_t* cond):
thread_info(detail::get_current_thread_data())
{
if(thread_info && thread_info->interrupt_enabled)
{
lock_guard<mutex> guard(thread_info->data_mutex);
check_for_interruption();
thread_info->current_cond=cond;
}
}
~interruption_checker()
{
if(thread_info && thread_info->interrupt_enabled)
{
lock_guard<mutex> guard(thread_info->data_mutex);
thread_info->current_cond=NULL;
check_for_interruption();
}
}
};
}
namespace this_thread
{
void BOOST_THREAD_DECL yield();
void BOOST_THREAD_DECL sleep(system_time const& abs_time);
template<typename TimeDuration>
inline void sleep(TimeDuration const& rel_time)
{
this_thread::sleep(get_system_time()+rel_time);
}
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,242 @@
// 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 2008 Anthony Williams
#ifndef THREAD_HEAP_ALLOC_PTHREAD_HPP
#define THREAD_HEAP_ALLOC_PTHREAD_HPP
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
template<typename T>
inline T* heap_new()
{
return new T();
}
#ifdef BOOST_HAS_RVALUE_REFS
template<typename T,typename A1>
inline T* heap_new(A1&& a1)
{
return new T(static_cast<A1&&>(a1));
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1&& a1,A2&& a2)
{
return new T(static_cast<A1&&>(a1),static_cast<A2&&>(a2));
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1&& a1,A2&& a2,A3&& a3)
{
return new T(static_cast<A1&&>(a1),static_cast<A2&&>(a2),
static_cast<A3&&>(a3));
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1&& a1,A2&& a2,A3&& a3,A4&& a4)
{
return new T(static_cast<A1&&>(a1),static_cast<A2&&>(a2),
static_cast<A3&&>(a3),static_cast<A4&&>(a4));
}
#else
template<typename T,typename A1>
inline T* heap_new_impl(A1 a1)
{
return new T(a1);
}
template<typename T,typename A1,typename A2>
inline T* heap_new_impl(A1 a1,A2 a2)
{
return new T(a1,a2);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3)
{
return new T(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4)
{
return new T(a1,a2,a3,a4);
}
template<typename T,typename A1>
inline T* heap_new(A1 const& a1)
{
return heap_new_impl<T,A1 const&>(a1);
}
template<typename T,typename A1>
inline T* heap_new(A1& a1)
{
return heap_new_impl<T,A1&>(a1);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1 const& a1,A2 const& a2)
{
return heap_new_impl<T,A1 const&,A2 const&>(a1,a2);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1& a1,A2 const& a2)
{
return heap_new_impl<T,A1&,A2 const&>(a1,a2);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1 const& a1,A2& a2)
{
return heap_new_impl<T,A1 const&,A2&>(a1,a2);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1& a1,A2& a2)
{
return heap_new_impl<T,A1&,A2&>(a1,a2);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3)
{
return heap_new_impl<T,A1 const&,A2 const&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3)
{
return heap_new_impl<T,A1&,A2 const&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3)
{
return heap_new_impl<T,A1 const&,A2&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2& a2,A3 const& a3)
{
return heap_new_impl<T,A1&,A2&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3)
{
return heap_new_impl<T,A1 const&,A2 const&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2 const& a2,A3& a3)
{
return heap_new_impl<T,A1&,A2 const&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2& a2,A3& a3)
{
return heap_new_impl<T,A1 const&,A2&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2& a2,A3& a3)
{
return heap_new_impl<T,A1&,A2&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4);
}
#endif
template<typename T>
inline void heap_delete(T* data)
{
delete data;
}
template<typename T>
struct do_heap_delete
{
void operator()(T* data) const
{
detail::heap_delete(data);
}
};
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,8 +1,19 @@
#ifndef BOOST_THREAD_PTHREAD_TIMESPEC_HPP
#define BOOST_THREAD_PTHREAD_TIMESPEC_HPP
// (C) Copyright 2007-8 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/thread_time.hpp>
#include <boost/date_time/posix_time/conversion.hpp>
#include <pthread.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
@@ -10,14 +21,16 @@ namespace boost
{
inline struct timespec get_timespec(boost::system_time const& abs_time)
{
struct timespec timeout={0};
struct timespec timeout={0,0};
boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0);
timeout.tv_sec=time_since_epoch.total_seconds();
timeout.tv_nsec=time_since_epoch.fractional_seconds()*(1000000000/time_since_epoch.ticks_per_second());
timeout.tv_nsec=(long)(time_since_epoch.fractional_seconds()*(1000000000l/time_since_epoch.ticks_per_second()));
return timeout;
}
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -10,6 +10,12 @@
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/platform.hpp>
#include BOOST_THREAD_PLATFORM(recursive_mutex.hpp)
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#include <boost/thread/win32/recursive_mutex.hpp>
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
#include <boost/thread/pthread/recursive_mutex.hpp>
#else
#error "Boost threads unavailable on this platform"
#endif
#endif

View File

@@ -10,6 +10,12 @@
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/thread/detail/platform.hpp>
#include BOOST_THREAD_PLATFORM(shared_mutex.hpp)
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#include <boost/thread/win32/shared_mutex.hpp>
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
#include <boost/thread/pthread/shared_mutex.hpp>
#else
#error "Boost threads unavailable on this platform"
#endif
#endif

View File

@@ -1,89 +1,25 @@
// Copyright (C) 2001-2003
// William E. Kempf
#ifndef BOOST_THREAD_THREAD_HPP
#define BOOST_THREAD_THREAD_HPP
// thread.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-8 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/platform.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>
# include <boost/thread/condition.hpp>
#elif defined(BOOST_HAS_MPTASKS)
# include <Multiprocessing.h>
#if defined(BOOST_THREAD_PLATFORM_WIN32)
#include <boost/thread/win32/thread_data.hpp>
#elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
#include <boost/thread/pthread/thread_data.hpp>
#else
#error "Boost threads unavailable on this platform"
#endif
namespace boost {
#include <boost/thread/detail/thread.hpp>
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();
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* 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;
};
#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

View File

@@ -1,8 +1,16 @@
#ifndef BOOST_THREAD_TIME_HPP
#define BOOST_THREAD_TIME_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)
#include <boost/date_time/microsec_time_clock.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
typedef boost::posix_time::ptime system_time;
@@ -19,22 +27,24 @@ namespace boost
return system_time(boost::posix_time::pos_infin);
}
inline unsigned get_milliseconds_until(system_time const& target_time)
inline unsigned long get_milliseconds_until(system_time const& target_time)
{
if(target_time.is_pos_infinity())
{
return ~0u;
return ~(unsigned long)0;
}
system_time const now=get_system_time();
if(target_time<=now)
{
return 0;
}
return (target_time-now).total_milliseconds()+1;
return static_cast<unsigned long>((target_time-now).total_milliseconds()+1);
}
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,128 +1,111 @@
// 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)
#ifndef BOOST_TSS_WEK070601_HPP
#define BOOST_TSS_WEK070601_HPP
#include <boost/thread/detail/config.hpp>
#include <boost/utility.hpp>
#include <boost/function.hpp>
#include <boost/thread/exceptions.hpp>
#if defined(BOOST_HAS_PTHREADS)
# include <pthread.h>
#elif defined(BOOST_HAS_MPTASKS)
# include <Multiprocessing.h>
#endif
namespace boost {
// 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
namespace detail {
class BOOST_THREAD_DECL tss : private noncopyable
{
public:
tss(boost::function1<void, void*>* pcleanup) {
if (pcleanup == 0) throw boost::thread_resource_error();
try
{
init(pcleanup);
}
catch (...)
{
delete pcleanup;
throw boost::thread_resource_error();
}
}
~tss();
void* get() const;
void set(void* value);
void cleanup(void* p);
private:
unsigned int m_slot; //This is a "pseudo-slot", not a native slot
void init(boost::function1<void, void*>* pcleanup);
};
#if defined(BOOST_HAS_MPTASKS)
void thread_cleanup();
#endif
template <typename T>
struct tss_adapter
{
template <typename F>
tss_adapter(const F& cleanup) : m_cleanup(cleanup) { }
void operator()(void* p) { m_cleanup(static_cast<T*>(p)); }
boost::function1<void, T*> m_cleanup;
};
} // namespace detail
template <typename T>
class thread_specific_ptr : private noncopyable
{
public:
thread_specific_ptr()
: m_tss(new boost::function1<void, void*>(
boost::detail::tss_adapter<T>(
&thread_specific_ptr<T>::cleanup)))
{
}
thread_specific_ptr(void (*clean)(T*))
: m_tss(new boost::function1<void, void*>(
boost::detail::tss_adapter<T>(clean)))
{
}
~thread_specific_ptr() { reset(); }
T* get() const { return static_cast<T*>(m_tss.get()); }
T* operator->() const { return get(); }
T& operator*() const { return *get(); }
T* release() { T* temp = get(); if (temp) m_tss.set(0); return temp; }
void reset(T* p=0)
{
T* cur = get();
if (cur == p) return;
m_tss.set(p);
if (cur) m_tss.cleanup(cur);
}
private:
static void cleanup(T* p) { delete p; }
detail::tss m_tss;
};
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
} // namespace boost
#endif //BOOST_TSS_WEK070601_HPP
// Change Log:
// 6 Jun 01
// WEKEMPF Initial version.
// 30 May 02 WEKEMPF
// Added interface to set specific cleanup handlers.
// Removed TLS slot limits from most implementations.
// 22 Mar 04 GlassfordM for WEKEMPF
// Fixed: thread_specific_ptr::reset() doesn't check error returned
// by tss::set(); tss::set() now throws if it fails.
// Fixed: calling thread_specific_ptr::reset() or
// thread_specific_ptr::release() causes double-delete: once on
// reset()/release() and once on ~thread_specific_ptr().
#ifndef BOOST_THREAD_TSS_HPP
#define BOOST_THREAD_TSS_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-8 Anthony Williams
#include <boost/thread/detail/config.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread/detail/thread_heap_alloc.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
struct tss_cleanup_function
{
virtual ~tss_cleanup_function()
{}
virtual void operator()(void* data)=0;
};
BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr<tss_cleanup_function> func,void* tss_data,bool cleanup_existing);
BOOST_THREAD_DECL void* get_tss_data(void const* key);
}
template <typename T>
class thread_specific_ptr
{
private:
thread_specific_ptr(thread_specific_ptr&);
thread_specific_ptr& operator=(thread_specific_ptr&);
struct delete_data:
detail::tss_cleanup_function
{
void operator()(void* data)
{
delete static_cast<T*>(data);
}
};
struct run_custom_cleanup_function:
detail::tss_cleanup_function
{
void (*cleanup_function)(T*);
explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)):
cleanup_function(cleanup_function_)
{}
void operator()(void* data)
{
cleanup_function(static_cast<T*>(data));
}
};
boost::shared_ptr<detail::tss_cleanup_function> cleanup;
public:
thread_specific_ptr():
cleanup(detail::heap_new<delete_data>(),detail::do_heap_delete<delete_data>())
{}
explicit thread_specific_ptr(void (*func_)(T*))
{
if(func_)
{
cleanup.reset(detail::heap_new<run_custom_cleanup_function>(func_),detail::do_heap_delete<run_custom_cleanup_function>());
}
}
~thread_specific_ptr()
{
reset();
}
T* get() const
{
return static_cast<T*>(detail::get_tss_data(this));
}
T* operator->() const
{
return get();
}
T& operator*() const
{
return *get();
}
T* release()
{
T* const temp=get();
detail::set_tss_data(this,boost::shared_ptr<detail::tss_cleanup_function>(),0,false);
return temp;
}
void reset(T* new_value=0)
{
T* const current_value=get();
if(current_value!=new_value)
{
detail::set_tss_data(this,cleanup,new_value,true);
}
}
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -3,7 +3,7 @@
// basic_recursive_mutex.hpp
//
// (C) Copyright 2006-7 Anthony Williams
// (C) Copyright 2006-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -12,6 +12,8 @@
#include "thread_primitives.hpp"
#include "basic_timed_mutex.hpp"
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
@@ -56,9 +58,10 @@ namespace boost
long const current_thread_id=win32::GetCurrentThreadId();
return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target);
}
long get_active_count()
template<typename Duration>
bool timed_lock(Duration const& timeout)
{
return mutex.get_active_count();
return timed_lock(get_system_time()+timeout);
}
void unlock()
@@ -70,11 +73,6 @@ namespace boost
}
}
bool locked()
{
return mutex.locked();
}
private:
bool try_recursive_lock(long current_thread_id)
{
@@ -117,4 +115,6 @@ namespace boost
#define BOOST_BASIC_RECURSIVE_MUTEX_INITIALIZER {0}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -3,7 +3,7 @@
// basic_timed_mutex_win32.hpp
//
// (C) Copyright 2006 Anthony Williams
// (C) Copyright 2006-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -13,6 +13,10 @@
#include "thread_primitives.hpp"
#include "interlocked_read.hpp"
#include <boost/thread/thread_time.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/detail/interlocked.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
@@ -20,7 +24,10 @@ namespace boost
{
struct basic_timed_mutex
{
BOOST_STATIC_CONSTANT(long,lock_flag_value=0x80000000);
BOOST_STATIC_CONSTANT(unsigned char,lock_flag_bit=31);
BOOST_STATIC_CONSTANT(unsigned char,event_set_flag_bit=30);
BOOST_STATIC_CONSTANT(long,lock_flag_value=1<<lock_flag_bit);
BOOST_STATIC_CONSTANT(long,event_set_flag_value=1<<event_set_flag_bit);
long active_count;
void* event;
@@ -32,7 +39,14 @@ namespace boost
void destroy()
{
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4312)
#endif
void* const old_event=BOOST_INTERLOCKED_EXCHANGE_POINTER(&event,0);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
if(old_event)
{
win32::CloseHandle(old_event);
@@ -42,61 +56,55 @@ namespace boost
bool try_lock()
{
long old_count=active_count&~lock_flag_value;
do
{
long const current_count=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,(old_count+1)|lock_flag_value,old_count);
if(current_count==old_count)
{
return true;
}
old_count=current_count;
}
while(!(old_count&lock_flag_value));
return false;
return !win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit);
}
void lock()
{
bool const success=timed_lock(::boost::detail::get_system_time_sentinel());
BOOST_ASSERT(success);
BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
}
bool timed_lock(::boost::system_time const& wait_until)
{
long old_count=active_count;
while(true)
if(!win32::interlocked_bit_test_and_set(&active_count,lock_flag_bit))
{
long const current_count=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,(old_count+1)|lock_flag_value,old_count);
if(current_count==old_count)
return true;
}
long old_count=active_count;
for(;;)
{
long const new_count=(old_count&lock_flag_value)?(old_count+1):(old_count|lock_flag_value);
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
if(current==old_count)
{
break;
}
old_count=current_count;
old_count=current;
}
if(old_count&lock_flag_value)
{
bool lock_acquired=false;
void* const sem=get_event();
++old_count; // we're waiting, too
do
{
old_count-=(lock_flag_value+1); // there will be one less active thread on this mutex when it gets unlocked
if(win32::WaitForSingleObject(sem,::boost::detail::get_milliseconds_until(wait_until))!=0)
{
BOOST_INTERLOCKED_DECREMENT(&active_count);
return false;
}
do
old_count&=~lock_flag_value;
old_count|=event_set_flag_value;
for(;;)
{
long const current_count=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,old_count|lock_flag_value,old_count);
if(current_count==old_count)
long const new_count=((old_count&lock_flag_value)?old_count:((old_count-1)|lock_flag_value))&~event_set_flag_value;
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&active_count,new_count,old_count);
if(current==old_count)
{
break;
}
old_count=current_count;
old_count=current;
}
while(!(old_count&lock_flag_value));
lock_acquired=!(old_count&lock_flag_value);
}
while(!lock_acquired);
@@ -104,27 +112,30 @@ namespace boost
return true;
}
long get_active_count()
template<typename Duration>
bool timed_lock(Duration const& timeout)
{
return ::boost::detail::interlocked_read_acquire(&active_count);
return timed_lock(get_system_time()+timeout);
}
bool timed_lock(boost::xtime const& timeout)
{
return timed_lock(system_time(timeout));
}
void unlock()
{
long const offset=lock_flag_value+1;
long old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,-offset);
if(old_count>offset)
long const offset=lock_flag_value;
long const old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,lock_flag_value);
if(!(old_count&event_set_flag_value) && (old_count>offset))
{
win32::SetEvent(get_event());
if(!win32::interlocked_bit_test_and_set(&active_count,event_set_flag_bit))
{
win32::SetEvent(get_event());
}
}
}
bool locked()
{
return get_active_count()>=lock_flag_value;
}
private:
void* get_event()
{
@@ -133,7 +144,15 @@ namespace boost
if(!current_event)
{
void* const new_event=win32::create_anonymous_event(win32::auto_reset_event,win32::event_initially_reset);
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4311)
#pragma warning(disable:4312)
#endif
void* const old_event=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&event,new_event,0);
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
if(old_event!=0)
{
win32::CloseHandle(new_event);
@@ -154,4 +173,6 @@ namespace boost
#define BOOST_BASIC_TIMED_MUTEX_INITIALIZER {0}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,418 @@
#ifndef BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP
#define BOOST_THREAD_CONDITION_VARIABLE_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-8 Anthony Williams
#include <boost/thread/mutex.hpp>
#include "thread_primitives.hpp"
#include <limits.h>
#include <boost/assert.hpp>
#include <algorithm>
#include <boost/thread/thread.hpp>
#include <boost/thread/thread_time.hpp>
#include "interlocked_read.hpp"
#include <boost/thread/xtime.hpp>
#include <vector>
#include <boost/intrusive_ptr.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
class basic_cv_list_entry;
void intrusive_ptr_add_ref(basic_cv_list_entry * p);
void intrusive_ptr_release(basic_cv_list_entry * p);
class basic_cv_list_entry
{
private:
detail::win32::handle_manager semaphore;
detail::win32::handle_manager wake_sem;
long waiters;
bool notified;
long references;
basic_cv_list_entry(basic_cv_list_entry&);
void operator=(basic_cv_list_entry&);
public:
explicit basic_cv_list_entry(detail::win32::handle_manager const& wake_sem_):
semaphore(detail::win32::create_anonymous_semaphore(0,LONG_MAX)),
wake_sem(wake_sem_.duplicate()),
waiters(1),notified(false),references(0)
{}
static bool no_waiters(boost::intrusive_ptr<basic_cv_list_entry> const& entry)
{
return !detail::interlocked_read_acquire(&entry->waiters);
}
void add_waiter()
{
BOOST_INTERLOCKED_INCREMENT(&waiters);
}
void remove_waiter()
{
BOOST_INTERLOCKED_DECREMENT(&waiters);
}
void release(unsigned count_to_release)
{
notified=true;
detail::win32::ReleaseSemaphore(semaphore,count_to_release,0);
}
void release_waiters()
{
release(detail::interlocked_read_acquire(&waiters));
}
bool is_notified() const
{
return notified;
}
bool wait(timeout wait_until)
{
return this_thread::interruptible_wait(semaphore,wait_until);
}
bool woken()
{
unsigned long const woken_result=detail::win32::WaitForSingleObject(wake_sem,0);
BOOST_ASSERT((woken_result==detail::win32::timeout) || (woken_result==0));
return woken_result==0;
}
friend void intrusive_ptr_add_ref(basic_cv_list_entry * p);
friend void intrusive_ptr_release(basic_cv_list_entry * p);
};
inline void intrusive_ptr_add_ref(basic_cv_list_entry * p)
{
BOOST_INTERLOCKED_INCREMENT(&p->references);
}
inline void intrusive_ptr_release(basic_cv_list_entry * p)
{
if(!BOOST_INTERLOCKED_DECREMENT(&p->references))
{
delete p;
}
}
class basic_condition_variable
{
boost::mutex internal_mutex;
long total_count;
unsigned active_generation_count;
typedef basic_cv_list_entry list_entry;
typedef boost::intrusive_ptr<list_entry> entry_ptr;
typedef std::vector<entry_ptr> generation_list;
generation_list generations;
detail::win32::handle_manager wake_sem;
void wake_waiters(long count_to_wake)
{
detail::interlocked_write_release(&total_count,total_count-count_to_wake);
detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0);
}
template<typename lock_type>
struct relocker
{
lock_type& lock;
bool unlocked;
relocker(lock_type& lock_):
lock(lock_),unlocked(false)
{}
void unlock()
{
lock.unlock();
unlocked=true;
}
~relocker()
{
if(unlocked)
{
lock.lock();
}
}
private:
relocker(relocker&);
void operator=(relocker&);
};
entry_ptr get_wait_entry()
{
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
if(!wake_sem)
{
wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
BOOST_ASSERT(wake_sem);
}
detail::interlocked_write_release(&total_count,total_count+1);
if(generations.empty() || generations.back()->is_notified())
{
entry_ptr new_entry(new list_entry(wake_sem));
generations.push_back(new_entry);
return new_entry;
}
else
{
generations.back()->add_waiter();
return generations.back();
}
}
struct entry_manager
{
entry_ptr const entry;
entry_manager(entry_ptr const& entry_):
entry(entry_)
{}
~entry_manager()
{
entry->remove_waiter();
}
list_entry* operator->()
{
return entry.get();
}
private:
void operator=(entry_manager&);
entry_manager(entry_manager&);
};
protected:
template<typename lock_type>
bool do_wait(lock_type& lock,timeout wait_until)
{
relocker<lock_type> locker(lock);
entry_manager entry(get_wait_entry());
locker.unlock();
bool woken=false;
while(!woken)
{
if(!entry->wait(wait_until))
{
return false;
}
woken=entry->woken();
}
return woken;
}
template<typename lock_type,typename predicate_type>
bool do_wait(lock_type& m,timeout const& wait_until,predicate_type pred)
{
while (!pred())
{
if(!do_wait(m, wait_until))
return pred();
}
return true;
}
basic_condition_variable(const basic_condition_variable& other);
basic_condition_variable& operator=(const basic_condition_variable& other);
public:
basic_condition_variable():
total_count(0),active_generation_count(0),wake_sem(0)
{}
~basic_condition_variable()
{}
void notify_one()
{
if(detail::interlocked_read_acquire(&total_count))
{
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
if(!total_count)
{
return;
}
wake_waiters(1);
for(generation_list::iterator it=generations.begin(),
end=generations.end();
it!=end;++it)
{
(*it)->release(1);
}
generations.erase(std::remove_if(generations.begin(),generations.end(),&basic_cv_list_entry::no_waiters),generations.end());
}
}
void notify_all()
{
if(detail::interlocked_read_acquire(&total_count))
{
boost::lock_guard<boost::mutex> internal_lock(internal_mutex);
if(!total_count)
{
return;
}
wake_waiters(total_count);
for(generation_list::iterator it=generations.begin(),
end=generations.end();
it!=end;++it)
{
(*it)->release_waiters();
}
generations.clear();
wake_sem=detail::win32::handle(0);
}
}
};
}
class condition_variable:
private detail::basic_condition_variable
{
private:
condition_variable(condition_variable&);
void operator=(condition_variable&);
public:
condition_variable()
{}
using detail::basic_condition_variable::notify_one;
using detail::basic_condition_variable::notify_all;
void wait(unique_lock<mutex>& m)
{
do_wait(m,detail::timeout::sentinel());
}
template<typename predicate_type>
void wait(unique_lock<mutex>& m,predicate_type pred)
{
while(!pred()) wait(m);
}
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until)
{
return do_wait(m,wait_until);
}
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& wait_until)
{
return do_wait(m,system_time(wait_until));
}
template<typename duration_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration)
{
return do_wait(m,wait_duration.total_milliseconds());
}
template<typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,boost::system_time const& wait_until,predicate_type pred)
{
return do_wait(m,wait_until,pred);
}
template<typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,boost::xtime const& wait_until,predicate_type pred)
{
return do_wait(m,system_time(wait_until),pred);
}
template<typename duration_type,typename predicate_type>
bool timed_wait(unique_lock<mutex>& m,duration_type const& wait_duration,predicate_type pred)
{
return do_wait(m,wait_duration.total_milliseconds(),pred);
}
};
class condition_variable_any:
private detail::basic_condition_variable
{
private:
condition_variable_any(condition_variable_any&);
void operator=(condition_variable_any&);
public:
condition_variable_any()
{}
using detail::basic_condition_variable::notify_one;
using detail::basic_condition_variable::notify_all;
template<typename lock_type>
void wait(lock_type& m)
{
do_wait(m,detail::timeout::sentinel());
}
template<typename lock_type,typename predicate_type>
void wait(lock_type& m,predicate_type pred)
{
while(!pred()) wait(m);
}
template<typename lock_type>
bool timed_wait(lock_type& m,boost::system_time const& wait_until)
{
return do_wait(m,wait_until);
}
template<typename lock_type>
bool timed_wait(lock_type& m,boost::xtime const& wait_until)
{
return do_wait(m,system_time(wait_until));
}
template<typename lock_type,typename duration_type>
bool timed_wait(lock_type& m,duration_type const& wait_duration)
{
return do_wait(m,wait_duration.total_milliseconds());
}
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,boost::system_time const& wait_until,predicate_type pred)
{
return do_wait(m,wait_until,pred);
}
template<typename lock_type,typename predicate_type>
bool timed_wait(lock_type& m,boost::xtime const& wait_until,predicate_type pred)
{
return do_wait(m,system_time(wait_until),pred);
}
template<typename lock_type,typename duration_type,typename predicate_type>
bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred)
{
return do_wait(m,wait_duration.total_milliseconds(),pred);
}
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -3,12 +3,16 @@
// interlocked_read_win32.hpp
//
// (C) Copyright 2005-7 Anthony Williams
// (C) Copyright 2005-8 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/detail/interlocked.hpp>
#include <boost/config/abi_prefix.hpp>
#ifdef BOOST_MSVC
extern "C" void _ReadWriteBarrier(void);
@@ -30,13 +34,22 @@ namespace boost
_ReadWriteBarrier();
return res;
}
inline void interlocked_write_release(long volatile* x,long value)
{
_ReadWriteBarrier();
*x=value;
}
inline void interlocked_write_release(void* volatile* x,void* value)
{
_ReadWriteBarrier();
*x=value;
}
}
}
#else
#include <boost/detail/interlocked.hpp>
namespace boost
{
namespace detail
@@ -49,10 +62,19 @@ namespace boost
{
return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(x,0,0);
}
inline void interlocked_write_release(long volatile* x,long value)
{
BOOST_INTERLOCKED_EXCHANGE(x,value);
}
inline void interlocked_write_release(void* volatile* x,void* value)
{
BOOST_INTERLOCKED_EXCHANGE_POINTER(x,value);
}
}
}
#endif
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -10,6 +10,8 @@
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
@@ -18,7 +20,7 @@ namespace boost
}
class mutex:
boost::noncopyable,
boost::noncopyable,
public ::boost::detail::underlying_mutex
{
public:
@@ -32,7 +34,7 @@ namespace boost
}
typedef unique_lock<mutex> scoped_lock;
typedef scoped_lock scoped_try_lock;
typedef detail::try_lock_wrapper<mutex> scoped_try_lock;
};
typedef mutex try_mutex;
@@ -53,9 +55,11 @@ namespace boost
}
typedef unique_lock<timed_mutex> scoped_timed_lock;
typedef scoped_timed_lock scoped_try_lock;
typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -18,6 +18,8 @@
#include <boost/thread/win32/thread_primitives.hpp>
#include <boost/thread/win32/interlocked_read.hpp>
#include <boost/config/abi_prefix.hpp>
#ifdef BOOST_NO_STDC_NAMESPACE
namespace std
{
@@ -40,14 +42,14 @@ namespace boost
explicit win32_mutex_scoped_lock(void* mutex_handle_):
mutex_handle(mutex_handle_)
{
unsigned long const res=win32::WaitForSingleObject(mutex_handle,win32::infinite);
BOOST_ASSERT(!res);
BOOST_VERIFY(!win32::WaitForSingleObject(mutex_handle,win32::infinite));
}
~win32_mutex_scoped_lock()
{
bool const success=win32::ReleaseMutex(mutex_handle)!=0;
BOOST_ASSERT(success);
BOOST_VERIFY(win32::ReleaseMutex(mutex_handle)!=0);
}
private:
void operator=(win32_mutex_scoped_lock&);
};
#ifdef BOOST_NO_ANSI_APIS
@@ -96,9 +98,9 @@ namespace boost
detail::int_to_string(win32::GetCurrentProcessId(), mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2);
#ifdef BOOST_NO_ANSI_APIS
return win32::CreateMutexW(NULL, 0, mutex_name);
return win32::CreateMutexW(0, 0, mutex_name);
#else
return win32::CreateMutexA(NULL, 0, mutex_name);
return win32::CreateMutexA(0, 0, mutex_name);
#endif
}
@@ -129,4 +131,6 @@ namespace boost
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -15,6 +15,8 @@
#include <boost/thread/exceptions.hpp>
#include <boost/thread/locks.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class recursive_mutex:
@@ -32,7 +34,7 @@ namespace boost
}
typedef unique_lock<recursive_mutex> scoped_lock;
typedef scoped_lock scoped_try_lock;
typedef detail::try_lock_wrapper<recursive_mutex> scoped_try_lock;
};
typedef recursive_mutex recursive_try_mutex;
@@ -52,10 +54,11 @@ namespace boost
}
typedef unique_lock<recursive_timed_mutex> scoped_timed_lock;
typedef scoped_timed_lock scoped_try_lock;
typedef detail::try_lock_wrapper<recursive_timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,7 +1,7 @@
#ifndef BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
#define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
// (C) Copyright 2006-7 Anthony Williams
// (C) Copyright 2006-8 Anthony Williams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -15,6 +15,8 @@
#include <boost/utility.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost
{
class shared_mutex:
@@ -23,12 +25,12 @@ namespace boost
private:
struct state_data
{
unsigned shared_count:11;
unsigned shared_waiting:11;
unsigned exclusive:1;
unsigned upgrade:1;
unsigned exclusive_waiting:7;
unsigned exclusive_waiting_blocked:1;
unsigned shared_count:11,
shared_waiting:11,
exclusive:1,
upgrade:1,
exclusive_waiting:7,
exclusive_waiting_blocked:1;
friend bool operator==(state_data const& lhs,state_data const& rhs)
{
@@ -48,23 +50,21 @@ namespace boost
}
state_data state;
void* semaphores[2];
void* &unlock_sem;
void* &exclusive_sem;
void* upgrade_sem;
detail::win32::handle semaphores[2];
detail::win32::handle &unlock_sem;
detail::win32::handle &exclusive_sem;
detail::win32::handle upgrade_sem;
void release_waiters(state_data old_state)
{
if(old_state.exclusive_waiting)
{
bool const success=detail::win32::ReleaseSemaphore(exclusive_sem,1,NULL)!=0;
BOOST_ASSERT(success);
BOOST_VERIFY(detail::win32::ReleaseSemaphore(exclusive_sem,1,0)!=0);
}
if(old_state.shared_waiting || old_state.exclusive_waiting)
{
bool const success=detail::win32::ReleaseSemaphore(unlock_sem,old_state.shared_waiting + (old_state.exclusive_waiting?1:0),NULL)!=0;
BOOST_ASSERT(success);
BOOST_VERIFY(detail::win32::ReleaseSemaphore(unlock_sem,old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
}
}
@@ -91,7 +91,7 @@ namespace boost
bool try_lock_shared()
{
state_data old_state=state;
do
for(;;)
{
state_data new_state=old_state;
if(!new_state.exclusive && !new_state.exclusive_waiting_blocked)
@@ -106,22 +106,26 @@ namespace boost
}
old_state=current_state;
}
while(true);
return !(old_state.exclusive| old_state.exclusive_waiting_blocked);
}
void lock_shared()
{
bool const success=timed_lock_shared(::boost::detail::get_system_time_sentinel());
BOOST_ASSERT(success);
BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel()));
}
template<typename TimeDuration>
bool timed_lock_shared(TimeDuration const & relative_time)
{
return timed_lock_shared(get_system_time()+relative_time);
}
bool timed_lock_shared(boost::system_time const& wait_until)
{
while(true)
for(;;)
{
state_data old_state=state;
do
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
@@ -140,7 +144,6 @@ namespace boost
}
old_state=current_state;
}
while(true);
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
@@ -150,7 +153,7 @@ namespace boost
unsigned long const res=detail::win32::WaitForSingleObject(unlock_sem,::boost::detail::get_milliseconds_until(wait_until));
if(res==detail::win32::timeout)
{
do
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked)
@@ -172,7 +175,6 @@ namespace boost
}
old_state=current_state;
}
while(true);
if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
{
@@ -188,7 +190,7 @@ namespace boost
void unlock_shared()
{
state_data old_state=state;
do
for(;;)
{
state_data new_state=old_state;
bool const last_reader=!--new_state.shared_count;
@@ -218,8 +220,7 @@ namespace boost
{
if(old_state.upgrade)
{
bool const success=detail::win32::ReleaseSemaphore(upgrade_sem,1,NULL)!=0;
BOOST_ASSERT(success);
BOOST_VERIFY(detail::win32::ReleaseSemaphore(upgrade_sem,1,0)!=0);
}
else
{
@@ -230,22 +231,52 @@ namespace boost
}
old_state=current_state;
}
while(true);
}
void lock()
{
bool const success=timed_lock(::boost::detail::get_system_time_sentinel());
BOOST_ASSERT(success);
BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
}
template<typename TimeDuration>
bool timed_lock(TimeDuration const & relative_time)
{
return timed_lock(get_system_time()+relative_time);
}
bool try_lock()
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
return false;
}
else
{
new_state.exclusive=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
return true;
}
bool timed_lock(boost::system_time const& wait_until)
{
while(true)
for(;;)
{
state_data old_state=state;
do
for(;;)
{
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
@@ -265,7 +296,6 @@ namespace boost
}
old_state=current_state;
}
while(true);
if(!old_state.shared_count && !old_state.exclusive)
{
@@ -274,14 +304,17 @@ namespace boost
unsigned long const wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,true,::boost::detail::get_milliseconds_until(wait_until));
if(wait_res==detail::win32::timeout)
{
do
for(;;)
{
state_data new_state=old_state;
if(new_state.shared_count || new_state.exclusive)
{
if(new_state.exclusive_waiting)
{
--new_state.exclusive_waiting;
if(!--new_state.exclusive_waiting)
{
new_state.exclusive_waiting_blocked=false;
}
}
}
else
@@ -296,7 +329,6 @@ namespace boost
}
old_state=current_state;
}
while(true);
if(!old_state.shared_count && !old_state.exclusive)
{
return true;
@@ -310,7 +342,7 @@ namespace boost
void unlock()
{
state_data old_state=state;
do
for(;;)
{
state_data new_state=old_state;
new_state.exclusive=false;
@@ -328,16 +360,15 @@ namespace boost
}
old_state=current_state;
}
while(true);
release_waiters(old_state);
}
void lock_upgrade()
{
while(true)
for(;;)
{
state_data old_state=state;
do
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
@@ -357,22 +388,46 @@ namespace boost
}
old_state=current_state;
}
while(true);
if(!(old_state.exclusive|| old_state.exclusive_waiting_blocked|| old_state.upgrade))
{
return;
}
unsigned long const res=detail::win32::WaitForSingleObject(unlock_sem,detail::win32::infinite);
BOOST_ASSERT(res==0);
BOOST_VERIFY(!detail::win32::WaitForSingleObject(unlock_sem,detail::win32::infinite));
}
}
bool try_lock_upgrade()
{
state_data old_state=state;
for(;;)
{
state_data new_state=old_state;
if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
{
return false;
}
else
{
++new_state.shared_count;
new_state.upgrade=true;
}
state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
if(current_state==old_state)
{
break;
}
old_state=current_state;
}
return true;
}
void unlock_upgrade()
{
state_data old_state=state;
do
for(;;)
{
state_data new_state=old_state;
new_state.upgrade=false;
@@ -399,13 +454,12 @@ namespace boost
}
old_state=current_state;
}
while(true);
}
void unlock_upgrade_and_lock()
{
state_data old_state=state;
do
for(;;)
{
state_data new_state=old_state;
bool const last_reader=!--new_state.shared_count;
@@ -421,20 +475,18 @@ namespace boost
{
if(!last_reader)
{
unsigned long const res=detail::win32::WaitForSingleObject(upgrade_sem,detail::win32::infinite);
BOOST_ASSERT(res==0);
BOOST_VERIFY(!detail::win32::WaitForSingleObject(upgrade_sem,detail::win32::infinite));
}
break;
}
old_state=current_state;
}
while(true);
}
void unlock_and_lock_upgrade()
{
state_data old_state=state;
do
for(;;)
{
state_data new_state=old_state;
new_state.exclusive=false;
@@ -454,14 +506,13 @@ namespace boost
}
old_state=current_state;
}
while(true);
release_waiters(old_state);
}
void unlock_and_lock_shared()
{
state_data old_state=state;
do
for(;;)
{
state_data new_state=old_state;
new_state.exclusive=false;
@@ -480,14 +531,13 @@ namespace boost
}
old_state=current_state;
}
while(true);
release_waiters(old_state);
}
void unlock_upgrade_and_lock_shared()
{
state_data old_state=state;
do
for(;;)
{
state_data new_state=old_state;
new_state.upgrade=false;
@@ -505,12 +555,12 @@ namespace boost
}
old_state=current_state;
}
while(true);
release_waiters(old_state);
}
};
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,178 @@
#ifndef BOOST_THREAD_PTHREAD_THREAD_DATA_HPP
#define BOOST_THREAD_PTHREAD_THREAD_DATA_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 2008 Anthony Williams
#include <boost/thread/detail/config.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/thread/thread_time.hpp>
#include "thread_primitives.hpp"
#include "thread_heap_alloc.hpp"
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
struct thread_exit_callback_node;
struct tss_data_node;
struct thread_data_base;
void intrusive_ptr_add_ref(thread_data_base * p);
void intrusive_ptr_release(thread_data_base * p);
struct thread_data_base
{
long count;
detail::win32::handle_manager thread_handle;
detail::win32::handle_manager interruption_handle;
boost::detail::thread_exit_callback_node* thread_exit_callbacks;
boost::detail::tss_data_node* tss_data;
bool interruption_enabled;
unsigned id;
thread_data_base():
count(0),thread_handle(detail::win32::invalid_handle_value),
interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)),
thread_exit_callbacks(0),tss_data(0),
interruption_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);
}
}
void interrupt()
{
BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0);
}
typedef detail::win32::handle native_handle_type;
virtual void run()=0;
};
typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr;
struct timeout
{
unsigned long start;
uintmax_t milliseconds;
bool relative;
boost::system_time abs_time;
static unsigned long const max_non_infinite_wait=0xfffffffe;
timeout(uintmax_t milliseconds_):
start(win32::GetTickCount()),
milliseconds(milliseconds_),
relative(true),
abs_time(boost::get_system_time())
{}
timeout(boost::system_time const& abs_time_):
start(win32::GetTickCount()),
milliseconds(0),
relative(false),
abs_time(abs_time_)
{}
struct remaining_time
{
bool more;
unsigned long milliseconds;
remaining_time(uintmax_t remaining):
more(remaining>max_non_infinite_wait),
milliseconds(more?max_non_infinite_wait:(unsigned long)remaining)
{}
};
remaining_time remaining_milliseconds() const
{
if(is_sentinel())
{
return remaining_time(win32::infinite);
}
else if(relative)
{
unsigned long const now=win32::GetTickCount();
unsigned long const elapsed=now-start;
return remaining_time((elapsed<milliseconds)?(milliseconds-elapsed):0);
}
else
{
system_time const now=get_system_time();
if(abs_time<=now)
{
return remaining_time(0);
}
return remaining_time((abs_time-now).total_milliseconds()+1);
}
}
bool is_sentinel() const
{
return milliseconds==~uintmax_t(0);
}
static timeout sentinel()
{
return timeout(sentinel_type());
}
private:
struct sentinel_type
{};
explicit timeout(sentinel_type):
start(0),milliseconds(~uintmax_t(0)),relative(true)
{}
};
}
namespace this_thread
{
void BOOST_THREAD_DECL yield();
bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
inline void interruptible_wait(unsigned long milliseconds)
{
interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
}
inline void interruptible_wait(system_time const& abs_time)
{
interruptible_wait(detail::win32::invalid_handle_value,abs_time);
}
template<typename TimeDuration>
inline void sleep(TimeDuration const& rel_time)
{
interruptible_wait(static_cast<unsigned long>(rel_time.total_milliseconds()));
}
inline void sleep(system_time const& abs_time)
{
interruptible_wait(abs_time);
}
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,397 @@
// 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"
#include <stdexcept>
#include <boost/assert.hpp>
#if defined( BOOST_USE_WINDOWS_H )
# include <windows.h>
namespace boost
{
namespace detail
{
namespace win32
{
using ::GetProcessHeap;
using ::HeapAlloc;
using ::HeapFree;
}
}
}
#else
# ifdef HeapAlloc
# undef HeapAlloc
# endif
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
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
{
inline BOOST_THREAD_DECL void* allocate_raw_heap_memory(unsigned size)
{
void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,size);
if(!heap_memory)
{
throw std::bad_alloc();
}
return heap_memory;
}
inline BOOST_THREAD_DECL void free_raw_heap_memory(void* heap_memory)
{
BOOST_VERIFY(detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,heap_memory)!=0);
}
template<typename T>
inline T* heap_new()
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
try
{
T* const data=new (heap_memory) T();
return data;
}
catch(...)
{
free_raw_heap_memory(heap_memory);
throw;
}
}
#ifdef BOOST_HAS_RVALUE_REFS
template<typename T,typename A1>
inline T* heap_new(A1&& a1)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
try
{
T* const data=new (heap_memory) T(static_cast<A1&&>(a1));
return data;
}
catch(...)
{
free_raw_heap_memory(heap_memory);
throw;
}
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1&& a1,A2&& a2)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
try
{
T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2));
return data;
}
catch(...)
{
free_raw_heap_memory(heap_memory);
throw;
}
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1&& a1,A2&& a2,A3&& a3)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
try
{
T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2),
static_cast<A3&&>(a3));
return data;
}
catch(...)
{
free_raw_heap_memory(heap_memory);
throw;
}
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1&& a1,A2&& a2,A3&& a3,A4&& a4)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
try
{
T* const data=new (heap_memory) T(static_cast<A1&&>(a1),static_cast<A2&&>(a2),
static_cast<A3&&>(a3),static_cast<A4&&>(a4));
return data;
}
catch(...)
{
free_raw_heap_memory(heap_memory);
throw;
}
}
#else
template<typename T,typename A1>
inline T* heap_new_impl(A1 a1)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
try
{
T* const data=new (heap_memory) T(a1);
return data;
}
catch(...)
{
free_raw_heap_memory(heap_memory);
throw;
}
}
template<typename T,typename A1,typename A2>
inline T* heap_new_impl(A1 a1,A2 a2)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
try
{
T* const data=new (heap_memory) T(a1,a2);
return data;
}
catch(...)
{
free_raw_heap_memory(heap_memory);
throw;
}
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
try
{
T* const data=new (heap_memory) T(a1,a2,a3);
return data;
}
catch(...)
{
free_raw_heap_memory(heap_memory);
throw;
}
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4)
{
void* const heap_memory=allocate_raw_heap_memory(sizeof(T));
try
{
T* const data=new (heap_memory) T(a1,a2,a3,a4);
return data;
}
catch(...)
{
free_raw_heap_memory(heap_memory);
throw;
}
}
template<typename T,typename A1>
inline T* heap_new(A1 const& a1)
{
return heap_new_impl<T,A1 const&>(a1);
}
template<typename T,typename A1>
inline T* heap_new(A1& a1)
{
return heap_new_impl<T,A1&>(a1);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1 const& a1,A2 const& a2)
{
return heap_new_impl<T,A1 const&,A2 const&>(a1,a2);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1& a1,A2 const& a2)
{
return heap_new_impl<T,A1&,A2 const&>(a1,a2);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1 const& a1,A2& a2)
{
return heap_new_impl<T,A1 const&,A2&>(a1,a2);
}
template<typename T,typename A1,typename A2>
inline T* heap_new(A1& a1,A2& a2)
{
return heap_new_impl<T,A1&,A2&>(a1,a2);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3)
{
return heap_new_impl<T,A1 const&,A2 const&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3)
{
return heap_new_impl<T,A1&,A2 const&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3)
{
return heap_new_impl<T,A1 const&,A2&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2& a2,A3 const& a3)
{
return heap_new_impl<T,A1&,A2&,A3 const&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3)
{
return heap_new_impl<T,A1 const&,A2 const&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2 const& a2,A3& a3)
{
return heap_new_impl<T,A1&,A2 const&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1 const& a1,A2& a2,A3& a3)
{
return heap_new_impl<T,A1 const&,A2&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3>
inline T* heap_new(A1& a1,A2& a2,A3& a3)
{
return heap_new_impl<T,A1&,A2&,A3&>(a1,a2,a3);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2&,A3 const&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3& a3,A4 const& a4)
{
return heap_new_impl<T,A1&,A2&,A3&,A4 const&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2&,A3 const&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2 const&,A3&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2 const&,A3&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1 const&,A2&,A3&,A4&>(a1,a2,a3,a4);
}
template<typename T,typename A1,typename A2,typename A3,typename A4>
inline T* heap_new(A1& a1,A2& a2,A3& a3,A4& a4)
{
return heap_new_impl<T,A1&,A2&,A3&,A4&>(a1,a2,a3,a4);
}
#endif
template<typename T>
inline void heap_delete(T* data)
{
data->~T();
free_raw_heap_memory(data);
}
template<typename T>
struct do_heap_delete
{
void operator()(T* data) const
{
detail::heap_delete(data);
}
};
}
}
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -3,7 +3,8 @@
// win32_thread_primitives.hpp
//
// (C) Copyright 2005-6 Anthony Williams
// (C) Copyright 2005-7 Anthony Williams
// (C) Copyright 2007 David Deakins
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -12,9 +13,12 @@
#include <boost/config.hpp>
#include <boost/assert.hpp>
#include <boost/thread/exceptions.hpp>
#include <boost/detail/interlocked.hpp>
#include <algorithm>
#if defined( BOOST_USE_WINDOWS_H )
# include <windows.h>
namespace boost
{
namespace detail
@@ -25,10 +29,17 @@ namespace boost
typedef HANDLE handle;
unsigned const infinite=INFINITE;
unsigned const timeout=WAIT_TIMEOUT;
handle const invalid_handle_value=INVALID_HANDLE_VALUE;
# ifdef BOOST_NO_ANSI_APIS
using ::CreateMutexW;
using ::CreateEventW;
using ::CreateSemaphoreW;
# else
using ::CreateMutexA;
using ::CreateEventA;
using ::CreateSemaphoreA;
# endif
using ::CloseHandle;
using ::ReleaseMutex;
using ::ReleaseSemaphore;
@@ -42,11 +53,36 @@ namespace boost
using ::GetCurrentProcess;
using ::DuplicateHandle;
using ::SleepEx;
using ::Sleep;
using ::QueueUserAPC;
using ::GetTickCount;
}
}
}
#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
# ifdef UNDER_CE
# ifndef WINAPI
# ifndef _WIN32_WCE_EMULATION
# define WINAPI __cdecl // Note this doesn't match the desktop definition
# else
# define WINAPI __stdcall
# endif
# endif
# ifdef __cplusplus
extern "C" {
# endif
typedef int BOOL;
typedef unsigned long DWORD;
typedef void* HANDLE;
# include <kfuncs.h>
# ifdef __cplusplus
}
# endif
# endif
namespace boost
{
namespace detail
@@ -62,28 +98,48 @@ namespace boost
typedef void* handle;
unsigned const infinite=~0U;
unsigned const timeout=258U;
handle const invalid_handle_value=(handle)(-1);
extern "C"
{
struct _SECURITY_ATTRIBUTES;
# ifdef BOOST_NO_ANSI_APIS
__declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*);
__declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*);
__declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*);
# else
__declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*);
__declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*);
__declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*);
# endif
__declspec(dllimport) int __stdcall CloseHandle(void*);
__declspec(dllimport) int __stdcall ReleaseMutex(void*);
__declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
__declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
__declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void*,unsigned long);
__declspec(dllimport) unsigned long __stdcall WaitForMultipleObjects(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds);
__declspec(dllimport) int __stdcall ReleaseSemaphore(void*,long,long*);
__declspec(dllimport) void* __stdcall GetCurrentThread();
__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) unsigned long __stdcall GetTickCount();
# ifndef UNDER_CE
__declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
__declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
__declspec(dllimport) void* __stdcall GetCurrentThread();
__declspec(dllimport) void* __stdcall GetCurrentProcess();
__declspec(dllimport) int __stdcall SetEvent(void*);
__declspec(dllimport) int __stdcall ResetEvent(void*);
__declspec(dllimport) unsigned long __stdcall WaitForMultipleObjects(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds);
# else
using ::GetCurrentProcessId;
using ::GetCurrentThreadId;
using ::GetCurrentThread;
using ::GetCurrentProcess;
using ::SetEvent;
using ::ResetEvent;
# endif
}
}
}
@@ -92,6 +148,8 @@ namespace boost
# error "Win32 functions not available"
#endif
#include <boost/config/abi_prefix.hpp>
namespace boost
{
namespace detail
@@ -112,7 +170,11 @@ namespace boost
inline handle create_anonymous_event(event_type type,initial_event_state state)
{
#if !defined(BOOST_NO_ANSI_APIS)
handle const res=win32::CreateEventA(0,type,state,0);
#else
handle const res=win32::CreateEventW(0,type,state,0);
#endif
if(!res)
{
throw thread_resource_error();
@@ -122,7 +184,11 @@ namespace boost
inline handle create_anonymous_semaphore(long initial_count,long max_count)
{
handle const res=CreateSemaphoreA(NULL,initial_count,max_count,NULL);
#if !defined(BOOST_NO_ANSI_APIS)
handle const res=CreateSemaphoreA(0,initial_count,max_count,0);
#else
handle const res=CreateSemaphoreW(0,initial_count,max_count,0);
#endif
if(!res)
{
throw thread_resource_error();
@@ -145,8 +211,7 @@ namespace boost
inline void release_semaphore(handle semaphore,long count)
{
bool const success=ReleaseSemaphore(semaphore,count,0)!=0;
BOOST_ASSERT(success);
BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0);
}
class handle_manager
@@ -158,10 +223,9 @@ namespace boost
void cleanup()
{
if(handle_to_manage)
if(handle_to_manage && handle_to_manage!=invalid_handle_value)
{
unsigned long result=CloseHandle(handle_to_manage);
BOOST_ASSERT(result);
BOOST_VERIFY(CloseHandle(handle_to_manage));
}
}
@@ -185,6 +249,16 @@ namespace boost
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;
@@ -207,5 +281,118 @@ namespace boost
}
}
#if defined(BOOST_MSVC) && (_MSC_VER>=1400) && !defined(UNDER_CE)
namespace boost
{
namespace detail
{
namespace win32
{
#if _MSC_VER==1400
extern "C" unsigned char _interlockedbittestandset(long *a,long b);
extern "C" unsigned char _interlockedbittestandreset(long *a,long b);
#else
extern "C" unsigned char _interlockedbittestandset(volatile long *a,long b);
extern "C" unsigned char _interlockedbittestandreset(volatile long *a,long b);
#endif
#pragma intrinsic(_interlockedbittestandset)
#pragma intrinsic(_interlockedbittestandreset)
inline bool interlocked_bit_test_and_set(long* x,long bit)
{
return _interlockedbittestandset(x,bit)!=0;
}
inline bool interlocked_bit_test_and_reset(long* x,long bit)
{
return _interlockedbittestandreset(x,bit)!=0;
}
}
}
}
#define BOOST_THREAD_BTS_DEFINED
#elif (defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)) && defined(_M_IX86)
namespace boost
{
namespace detail
{
namespace win32
{
inline bool interlocked_bit_test_and_set(long* x,long bit)
{
__asm {
mov eax,bit;
mov edx,x;
lock bts [edx],eax;
setc al;
};
}
inline bool interlocked_bit_test_and_reset(long* x,long bit)
{
__asm {
mov eax,bit;
mov edx,x;
lock btr [edx],eax;
setc al;
};
}
}
}
}
#define BOOST_THREAD_BTS_DEFINED
#endif
#ifndef BOOST_THREAD_BTS_DEFINED
namespace boost
{
namespace detail
{
namespace win32
{
inline bool interlocked_bit_test_and_set(long* x,long bit)
{
long const value=1<<bit;
long old=*x;
do
{
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old|value,old);
if(current==old)
{
break;
}
old=current;
}
while(true);
return (old&value)!=0;
}
inline bool interlocked_bit_test_and_reset(long* x,long bit)
{
long const value=1<<bit;
long old=*x;
do
{
long const current=BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,old&~value,old);
if(current==old)
{
break;
}
old=current;
}
while(true);
return (old&value)!=0;
}
}
}
}
#endif
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -1,5 +1,6 @@
// Copyright (C) 2001-2003
// William E. Kempf
// Copyright (C) 2007-8 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)
@@ -13,6 +14,8 @@
#include <boost/thread/thread_time.hpp>
#include <boost/date_time/posix_time/conversion.hpp>
#include <boost/config/abi_prefix.hpp>
namespace boost {
enum xtime_clock_types
@@ -39,9 +42,40 @@ struct xtime
xtime_sec_t sec;
xtime_nsec_t nsec;
operator system_time() const
{
return boost::posix_time::from_time_t(0)+
boost::posix_time::seconds(static_cast<long>(sec))+
#ifdef BOOST_DATE_TIME_HAS_NANOSECONDS
boost::posix_time::nanoseconds(nsec);
#else
boost::posix_time::microseconds((nsec+500)/1000);
#endif
}
};
int BOOST_THREAD_DECL xtime_get(struct xtime* xtp, int clock_type);
inline xtime get_xtime(boost::system_time const& abs_time)
{
xtime res;
boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0);
res.sec=static_cast<xtime::xtime_sec_t>(time_since_epoch.total_seconds());
res.nsec=static_cast<xtime::xtime_nsec_t>(time_since_epoch.fractional_seconds()*(1000000000/time_since_epoch.ticks_per_second()));
return res;
}
inline int xtime_get(struct xtime* xtp, int clock_type)
{
if (clock_type == TIME_UTC)
{
*xtp=get_xtime(get_system_time());
return clock_type;
}
return 0;
}
inline int xtime_cmp(const xtime& xt1, const xtime& xt2)
{
@@ -51,16 +85,8 @@ inline int xtime_cmp(const xtime& xt1, const xtime& xt2)
return (xt1.sec > xt2.sec) ? 1 : -1;
}
inline xtime get_xtime(boost::system_time const& abs_time)
{
xtime res={0};
boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0);
res.sec=time_since_epoch.total_seconds();
res.nsec=time_since_epoch.fractional_seconds()*(1000000000/time_since_epoch.ticks_per_second());
return res;
}
} // namespace boost
#include <boost/config/abi_suffix.hpp>
#endif //BOOST_XTIME_WEK070601_HPP