]> git.sesse.net Git - casparcg/blob - dependencies/boost/boost/thread/win32/thread_data.hpp
Manually merged pull request #222
[casparcg] / dependencies / boost / boost / thread / win32 / thread_data.hpp
1 #ifndef BOOST_THREAD_PTHREAD_THREAD_DATA_HPP
2 #define BOOST_THREAD_PTHREAD_THREAD_DATA_HPP
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 // (C) Copyright 2008 Anthony Williams
7
8 #include <boost/thread/detail/config.hpp>
9 #include <boost/intrusive_ptr.hpp>
10 #include <boost/thread/thread_time.hpp>
11 #include "thread_primitives.hpp"
12 #include "thread_heap_alloc.hpp"
13
14 #include <boost/config/abi_prefix.hpp>
15
16 namespace boost
17 {
18     namespace detail
19     {
20         struct thread_exit_callback_node;
21         struct tss_data_node;
22
23         struct thread_data_base;
24         void intrusive_ptr_add_ref(thread_data_base * p);
25         void intrusive_ptr_release(thread_data_base * p);
26         
27         struct thread_data_base
28         {
29             long count;
30             detail::win32::handle_manager thread_handle;
31             detail::win32::handle_manager interruption_handle;
32             boost::detail::thread_exit_callback_node* thread_exit_callbacks;
33             boost::detail::tss_data_node* tss_data;
34             bool interruption_enabled;
35             unsigned id;
36
37             thread_data_base():
38                 count(0),thread_handle(detail::win32::invalid_handle_value),
39                 interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)),
40                 thread_exit_callbacks(0),tss_data(0),
41                 interruption_enabled(true),
42                 id(0)
43             {}
44             virtual ~thread_data_base()
45             {}
46
47             friend void intrusive_ptr_add_ref(thread_data_base * p)
48             {
49                 BOOST_INTERLOCKED_INCREMENT(&p->count);
50             }
51             
52             friend void intrusive_ptr_release(thread_data_base * p)
53             {
54                 if(!BOOST_INTERLOCKED_DECREMENT(&p->count))
55                 {
56                     detail::heap_delete(p);
57                 }
58             }
59
60             void interrupt()
61             {
62                 BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0);
63             }
64             
65             typedef detail::win32::handle native_handle_type;
66
67             virtual void run()=0;
68         };
69
70         typedef boost::intrusive_ptr<detail::thread_data_base> thread_data_ptr;
71
72         struct timeout
73         {
74             unsigned long start;
75             uintmax_t milliseconds;
76             bool relative;
77             boost::system_time abs_time;
78
79             static unsigned long const max_non_infinite_wait=0xfffffffe;
80
81             timeout(uintmax_t milliseconds_):
82                 start(win32::GetTickCount()),
83                 milliseconds(milliseconds_),
84                 relative(true),
85                 abs_time(boost::get_system_time())
86             {}
87
88             timeout(boost::system_time const& abs_time_):
89                 start(win32::GetTickCount()),
90                 milliseconds(0),
91                 relative(false),
92                 abs_time(abs_time_)
93             {}
94
95             struct remaining_time
96             {
97                 bool more;
98                 unsigned long milliseconds;
99
100                 remaining_time(uintmax_t remaining):
101                     more(remaining>max_non_infinite_wait),
102                     milliseconds(more?max_non_infinite_wait:(unsigned long)remaining)
103                 {}
104             };
105
106             remaining_time remaining_milliseconds() const
107             {
108                 if(is_sentinel())
109                 {
110                     return remaining_time(win32::infinite);
111                 }
112                 else if(relative)
113                 {
114                     unsigned long const now=win32::GetTickCount();
115                     unsigned long const elapsed=now-start;
116                     return remaining_time((elapsed<milliseconds)?(milliseconds-elapsed):0);
117                 }
118                 else
119                 {
120                     system_time const now=get_system_time();
121                     if(abs_time<=now)
122                     {
123                         return remaining_time(0);
124                     }
125                     return remaining_time((abs_time-now).total_milliseconds()+1);
126                 }
127             }
128
129             bool is_sentinel() const
130             {
131                 return milliseconds==~uintmax_t(0);
132             }
133             
134
135             static timeout sentinel()
136             {
137                 return timeout(sentinel_type());
138             }
139         private:
140             struct sentinel_type
141             {};
142                 
143             explicit timeout(sentinel_type):
144                 start(0),milliseconds(~uintmax_t(0)),relative(true)
145             {}
146         };
147
148         inline uintmax_t pin_to_zero(intmax_t value)
149         {
150             return (value<0)?0u:(uintmax_t)value;
151         }
152     }
153
154     namespace this_thread
155     {
156         void BOOST_THREAD_DECL yield();
157
158         bool BOOST_THREAD_DECL interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time);
159         inline void interruptible_wait(uintmax_t milliseconds)
160         {
161             interruptible_wait(detail::win32::invalid_handle_value,milliseconds);
162         }
163         inline void interruptible_wait(system_time const& abs_time)
164         {
165             interruptible_wait(detail::win32::invalid_handle_value,abs_time);
166         }
167
168         template<typename TimeDuration>
169         inline void sleep(TimeDuration const& rel_time)
170         {
171             interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds()));
172         }
173         inline void sleep(system_time const& abs_time)
174         {
175             interruptible_wait(abs_time);
176         }
177     }
178     
179 }
180
181 #include <boost/config/abi_suffix.hpp>
182
183 #endif