2
0
mirror of https://github.com/boostorg/thread.git synced 2026-02-08 23:22:13 +00:00
Files
thread/include/boost/thread/win32/thread.hpp
Anthony Williams 31e1566e1d renamed cancellation to interruption
[SVN r40685]
2007-11-02 14:58:48 +00:00

443 lines
11 KiB
C++

#ifndef BOOST_THREAD_THREAD_WIN32_HPP
#define BOOST_THREAD_THREAD_WIN32_HPP
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007 Anthony Williams
#include <exception>
#include <boost/thread/exceptions.hpp>
#include <ostream>
#include <boost/thread/detail/move.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread_time.hpp>
#include "thread_primitives.hpp"
#include "thread_heap_alloc.hpp"
#include <boost/utility.hpp>
#include <list>
#include <algorithm>
#include <boost/ref.hpp>
namespace boost
{
class thread_interrupted
{};
namespace detail
{
struct thread_exit_callback_node;
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;
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),
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);
}
}
virtual void run()=0;
};
}
class BOOST_THREAD_DECL thread
{
private:
thread(thread&);
thread& operator=(thread&);
void release_handle();
template<typename F>
struct thread_data:
detail::thread_data_base
{
F f;
thread_data(F f_):
f(f_)
{}
thread_data(boost::move_t<F> f_):
f(f_)
{}
void run()
{
f();
}
};
mutable boost::mutex thread_info_mutex;
boost::intrusive_ptr<detail::thread_data_base> thread_info;
static unsigned __stdcall thread_start_function(void* param);
void start_thread();
explicit thread(boost::intrusive_ptr<detail::thread_data_base> data);
boost::intrusive_ptr<detail::thread_data_base> get_thread_info() const;
public:
thread();
~thread();
template <class F>
explicit thread(F f):
thread_info(detail::heap_new<thread_data<F> >(f))
{
start_thread();
}
template <class F>
explicit thread(boost::move_t<F> f):
thread_info(detail::heap_new<thread_data<F> >(f))
{
start_thread();
}
thread(boost::move_t<thread> x);
thread& operator=(boost::move_t<thread> x);
operator boost::move_t<thread>();
boost::move_t<thread> move();
void swap(thread& x);
class id;
id get_id() const;
bool joinable() const;
void join();
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::win32::handle native_handle_type;
native_handle_type native_handle();
// backwards compatibility
bool operator==(const thread& other) const;
bool operator!=(const thread& other) const;
static void yield();
static void sleep(const system_time& xt);
// extensions
class interruption_handle;
interruption_handle get_interruption_handle() const;
void interrupt();
bool interruption_requested() const;
static thread self();
};
template<typename F>
struct thread::thread_data<boost::reference_wrapper<F> >:
detail::thread_data_base
{
F& f;
thread_data(boost::reference_wrapper<F> f_):
f(f_)
{}
void run()
{
f();
}
};
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();
bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,unsigned long milliseconds);
inline bool interruptible_wait(unsigned long milliseconds)
{
return interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
}
void BOOST_THREAD_DECL interruption_point();
bool BOOST_THREAD_DECL interruption_enabled();
bool BOOST_THREAD_DECL interruption_requested();
thread::interruption_handle BOOST_THREAD_DECL get_interruption_handle();
void BOOST_THREAD_DECL yield();
template<typename TimeDuration>
void sleep(TimeDuration const& rel_time)
{
interruptible_wait(static_cast<unsigned long>(rel_time.total_milliseconds()));
}
}
class thread::id
{
private:
unsigned thread_id;
id(unsigned thread_id_):
thread_id(thread_id_)
{}
friend class thread;
friend id this_thread::get_id();
public:
id():
thread_id(0)
{}
bool operator==(const id& y) const
{
return thread_id==y.thread_id;
}
bool operator!=(const id& y) const
{
return thread_id!=y.thread_id;
}
bool operator<(const id& y) const
{
return thread_id<y.thread_id;
}
bool operator>(const id& y) const
{
return thread_id>y.thread_id;
}
bool operator<=(const id& y) const
{
return thread_id<=y.thread_id;
}
bool operator>=(const id& y) const
{
return thread_id>=y.thread_id;
}
template<class charT, class traits>
friend std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const id& x)
{
return os<<x.thread_id;
}
};
inline bool thread::operator==(const thread& other) const
{
return get_id()==other.get_id();
}
inline bool thread::operator!=(const thread& other) const
{
return get_id()!=other.get_id();
}
class thread::interruption_handle
{
private:
boost::detail::win32::handle_manager handle;
friend class thread;
friend interruption_handle this_thread::get_interruption_handle();
interruption_handle(detail::win32::handle h_):
handle(h_)
{}
public:
interruption_handle(interruption_handle const& other):
handle(other.handle.duplicate())
{}
interruption_handle():
handle(0)
{}
void swap(interruption_handle& other)
{
handle.swap(other.handle);
}
interruption_handle& operator=(interruption_handle const& other)
{
interruption_handle temp(other);
swap(temp);
return *this;
}
void reset()
{
handle=0;
}
void interrupt()
{
if(handle)
{
detail::win32::SetEvent(handle);
}
}
typedef void(interruption_handle::*bool_type)();
operator bool_type() const
{
return handle?&interruption_handle::interrupt:0;
}
};
namespace detail
{
struct thread_exit_function_base
{
virtual ~thread_exit_function_base()
{}
virtual void operator()() const=0;
};
template<typename F>
struct thread_exit_function:
thread_exit_function_base
{
F f;
thread_exit_function(F f_):
f(f_)
{}
void operator()() const
{
f();
}
};
void add_thread_exit_function(thread_exit_function_base*);
}
namespace this_thread
{
template<typename F>
void at_thread_exit(F f)
{
detail::thread_exit_function_base* const thread_exit_func=detail::heap_new<detail::thread_exit_function<F> >(f);
detail::add_thread_exit_function(thread_exit_func);
}
}
class thread_group:
private noncopyable
{
public:
~thread_group()
{
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
it!=end;
++it)
{
delete *it;
}
}
template<typename F>
thread* create_thread(F threadfunc)
{
boost::lock_guard<mutex> guard(m);
thread* const new_thread=new thread(threadfunc);
threads.push_back(new_thread);
return new_thread;
}
void add_thread(thread* thrd)
{
if(thrd)
{
boost::lock_guard<mutex> guard(m);
threads.push_back(thrd);
}
}
void remove_thread(thread* thrd)
{
boost::lock_guard<mutex> guard(m);
std::list<thread*>::iterator const it=std::find(threads.begin(),threads.end(),thrd);
if(it!=threads.end())
{
threads.erase(it);
}
}
void join_all()
{
boost::lock_guard<mutex> guard(m);
for(std::list<thread*>::iterator it=threads.begin(),end=threads.end();
it!=end;
++it)
{
(*it)->join();
}
}
int size() const
{
boost::lock_guard<mutex> guard(m);
return threads.size();
}
private:
std::list<thread*> threads;
mutable mutex m;
};
}
#endif