#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) | |
{} | |
}; | |
inline unsigned long pin_to_zero(long value) | |
{ | |
return (value<0)?0u:(unsigned long)value; | |
} | |
} | |
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(detail::pin_to_zero(rel_time.total_milliseconds())); | |
} | |
inline void sleep(system_time const& abs_time) | |
{ | |
interruptible_wait(abs_time); | |
} | |
} | |
} | |
#include <boost/config/abi_suffix.hpp> | |
#endif |