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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
21
include/boost/thread/condition_variable.hpp
Normal file
21
include/boost/thread/condition_variable.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
575
include/boost/thread/detail/thread.hpp
Normal file
575
include/boost/thread/detail/thread.hpp
Normal 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
|
||||
23
include/boost/thread/detail/thread_heap_alloc.hpp
Normal file
23
include/boost/thread/detail/thread_heap_alloc.hpp
Normal 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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
176
include/boost/thread/pthread/condition_variable.hpp
Normal file
176
include/boost/thread/pthread/condition_variable.hpp
Normal 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
|
||||
97
include/boost/thread/pthread/condition_variable_fwd.hpp
Normal file
97
include/boost/thread/pthread/condition_variable_fwd.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
54
include/boost/thread/pthread/pthread_mutex_scoped_lock.hpp
Normal file
54
include/boost/thread/pthread/pthread_mutex_scoped_lock.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
118
include/boost/thread/pthread/thread_data.hpp
Normal file
118
include/boost/thread/pthread/thread_data.hpp
Normal 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
|
||||
242
include/boost/thread/pthread/thread_heap_alloc.hpp
Normal file
242
include/boost/thread/pthread/thread_heap_alloc.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
418
include/boost/thread/win32/condition_variable.hpp
Normal file
418
include/boost/thread/win32/condition_variable.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
178
include/boost/thread/win32/thread_data.hpp
Normal file
178
include/boost/thread/win32/thread_data.hpp
Normal 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
|
||||
397
include/boost/thread/win32/thread_heap_alloc.hpp
Normal file
397
include/boost/thread/win32/thread_heap_alloc.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user