Chris@16
|
1 //////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2 //
|
Chris@16
|
3 // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
|
Chris@16
|
4 // Software License, Version 1.0. (See accompanying file
|
Chris@16
|
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6 //
|
Chris@16
|
7 // See http://www.boost.org/libs/interprocess for documentation.
|
Chris@16
|
8 //
|
Chris@16
|
9 //////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
10
|
Chris@16
|
11 //Thread launching functions are adapted from boost/detail/lightweight_thread.hpp
|
Chris@16
|
12 //
|
Chris@16
|
13 // boost/detail/lightweight_thread.hpp
|
Chris@16
|
14 //
|
Chris@16
|
15 // Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
Chris@16
|
16 // Copyright (c) 2008 Peter Dimov
|
Chris@16
|
17 //
|
Chris@16
|
18 // Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
19 // See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
20 // http://www.boost.org/LICENSE_1_0.txt
|
Chris@16
|
21
|
Chris@16
|
22 #ifndef BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
|
Chris@16
|
23 #define BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
|
Chris@16
|
24
|
Chris@101
|
25 #ifndef BOOST_CONFIG_HPP
|
Chris@101
|
26 # include <boost/config.hpp>
|
Chris@101
|
27 #endif
|
Chris@101
|
28 #
|
Chris@101
|
29 #if defined(BOOST_HAS_PRAGMA_ONCE)
|
Chris@101
|
30 # pragma once
|
Chris@101
|
31 #endif
|
Chris@101
|
32
|
Chris@16
|
33 #include <boost/interprocess/detail/config_begin.hpp>
|
Chris@16
|
34 #include <boost/interprocess/detail/workaround.hpp>
|
Chris@16
|
35 #include <boost/interprocess/streams/bufferstream.hpp>
|
Chris@16
|
36 #include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
Chris@16
|
37 #include <cstddef>
|
Chris@101
|
38 #include <ostream>
|
Chris@16
|
39
|
Chris@16
|
40 #if defined(BOOST_INTERPROCESS_WINDOWS)
|
Chris@16
|
41 # include <boost/interprocess/detail/win32_api.hpp>
|
Chris@16
|
42 # include <process.h>
|
Chris@16
|
43 #else
|
Chris@16
|
44 # include <pthread.h>
|
Chris@16
|
45 # include <unistd.h>
|
Chris@16
|
46 # include <sched.h>
|
Chris@16
|
47 # include <time.h>
|
Chris@16
|
48 # ifdef BOOST_INTERPROCESS_BSD_DERIVATIVE
|
Chris@16
|
49 //Some *BSD systems (OpenBSD & NetBSD) need sys/param.h before sys/sysctl.h, whereas
|
Chris@16
|
50 //others (FreeBSD & Darwin) need sys/types.h
|
Chris@16
|
51 # include <sys/types.h>
|
Chris@16
|
52 # include <sys/param.h>
|
Chris@16
|
53 # include <sys/sysctl.h>
|
Chris@16
|
54 # endif
|
Chris@16
|
55 //According to the article "C/C++ tip: How to measure elapsed real time for benchmarking"
|
Chris@16
|
56 # if defined(CLOCK_MONOTONIC_PRECISE) //BSD
|
Chris@16
|
57 # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_PRECISE
|
Chris@16
|
58 # elif defined(CLOCK_MONOTONIC_RAW) //Linux
|
Chris@16
|
59 # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_RAW
|
Chris@16
|
60 # elif defined(CLOCK_HIGHRES) //Solaris
|
Chris@16
|
61 # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_HIGHRES
|
Chris@16
|
62 # elif defined(CLOCK_MONOTONIC) //POSIX (AIX, BSD, Linux, Solaris)
|
Chris@16
|
63 # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC
|
Chris@16
|
64 # elif !defined(CLOCK_MONOTONIC) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
|
Chris@16
|
65 # include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t
|
Chris@16
|
66 # define BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
|
Chris@16
|
67 # else
|
Chris@16
|
68 # error "No high resolution steady clock in your system, please provide a patch"
|
Chris@16
|
69 # endif
|
Chris@16
|
70 #endif
|
Chris@16
|
71
|
Chris@16
|
72 namespace boost {
|
Chris@16
|
73 namespace interprocess {
|
Chris@16
|
74 namespace ipcdetail{
|
Chris@16
|
75
|
Chris@101
|
76 #if defined (BOOST_INTERPROCESS_WINDOWS)
|
Chris@16
|
77
|
Chris@16
|
78 typedef unsigned long OS_process_id_t;
|
Chris@16
|
79 typedef unsigned long OS_thread_id_t;
|
Chris@16
|
80 typedef void* OS_thread_t;
|
Chris@16
|
81 typedef OS_thread_id_t OS_systemwide_thread_id_t;
|
Chris@16
|
82
|
Chris@16
|
83 //process
|
Chris@16
|
84 inline OS_process_id_t get_current_process_id()
|
Chris@16
|
85 { return winapi::get_current_process_id(); }
|
Chris@16
|
86
|
Chris@16
|
87 inline OS_process_id_t get_invalid_process_id()
|
Chris@16
|
88 { return OS_process_id_t(0); }
|
Chris@16
|
89
|
Chris@16
|
90 //thread
|
Chris@16
|
91 inline OS_thread_id_t get_current_thread_id()
|
Chris@16
|
92 { return winapi::get_current_thread_id(); }
|
Chris@16
|
93
|
Chris@16
|
94 inline OS_thread_id_t get_invalid_thread_id()
|
Chris@16
|
95 { return OS_thread_id_t(0xffffffff); }
|
Chris@16
|
96
|
Chris@16
|
97 inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
|
Chris@16
|
98 { return id1 == id2; }
|
Chris@16
|
99
|
Chris@16
|
100 //return the system tick in ns
|
Chris@16
|
101 inline unsigned long get_system_tick_ns()
|
Chris@16
|
102 {
|
Chris@16
|
103 unsigned long curres;
|
Chris@16
|
104 winapi::set_timer_resolution(10000, 0, &curres);
|
Chris@16
|
105 //Windows API returns the value in hundreds of ns
|
Chris@16
|
106 return (curres - 1ul)*100ul;
|
Chris@16
|
107 }
|
Chris@16
|
108
|
Chris@16
|
109 //return the system tick in us
|
Chris@16
|
110 inline unsigned long get_system_tick_us()
|
Chris@16
|
111 {
|
Chris@16
|
112 unsigned long curres;
|
Chris@16
|
113 winapi::set_timer_resolution(10000, 0, &curres);
|
Chris@16
|
114 //Windows API returns the value in hundreds of ns
|
Chris@16
|
115 return (curres - 1ul)/10ul + 1ul;
|
Chris@16
|
116 }
|
Chris@16
|
117
|
Chris@16
|
118 typedef unsigned __int64 OS_highres_count_t;
|
Chris@16
|
119
|
Chris@16
|
120 inline unsigned long get_system_tick_in_highres_counts()
|
Chris@16
|
121 {
|
Chris@16
|
122 __int64 freq;
|
Chris@16
|
123 unsigned long curres;
|
Chris@16
|
124 winapi::set_timer_resolution(10000, 0, &curres);
|
Chris@16
|
125 //Frequency in counts per second
|
Chris@16
|
126 if(!winapi::query_performance_frequency(&freq)){
|
Chris@16
|
127 //Tick resolution in ms
|
Chris@16
|
128 return (curres-1ul)/10000ul + 1ul;
|
Chris@16
|
129 }
|
Chris@16
|
130 else{
|
Chris@16
|
131 //In femtoseconds
|
Chris@16
|
132 __int64 count_fs = (1000000000000000LL - 1LL)/freq + 1LL;
|
Chris@16
|
133 __int64 tick_counts = (static_cast<__int64>(curres)*100000000LL - 1LL)/count_fs + 1LL;
|
Chris@16
|
134 return static_cast<unsigned long>(tick_counts);
|
Chris@16
|
135 }
|
Chris@16
|
136 }
|
Chris@16
|
137
|
Chris@16
|
138 inline OS_highres_count_t get_current_system_highres_count()
|
Chris@16
|
139 {
|
Chris@16
|
140 __int64 count;
|
Chris@16
|
141 if(!winapi::query_performance_counter(&count)){
|
Chris@16
|
142 count = winapi::get_tick_count();
|
Chris@16
|
143 }
|
Chris@16
|
144 return count;
|
Chris@16
|
145 }
|
Chris@16
|
146
|
Chris@16
|
147 inline void zero_highres_count(OS_highres_count_t &count)
|
Chris@16
|
148 { count = 0; }
|
Chris@16
|
149
|
Chris@16
|
150 inline bool is_highres_count_zero(const OS_highres_count_t &count)
|
Chris@16
|
151 { return count == 0; }
|
Chris@16
|
152
|
Chris@16
|
153 template <class Ostream>
|
Chris@16
|
154 inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
|
Chris@16
|
155 {
|
Chris@16
|
156 ostream << count;
|
Chris@16
|
157 return ostream;
|
Chris@16
|
158 }
|
Chris@16
|
159
|
Chris@16
|
160 inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
|
Chris@16
|
161 { return l - r; }
|
Chris@16
|
162
|
Chris@16
|
163 inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
|
Chris@101
|
164 { return l < r; }
|
Chris@16
|
165
|
Chris@16
|
166 inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r)
|
Chris@16
|
167 { return l < static_cast<OS_highres_count_t>(r); }
|
Chris@16
|
168
|
Chris@16
|
169 inline void thread_sleep_tick()
|
Chris@16
|
170 { winapi::sleep_tick(); }
|
Chris@16
|
171
|
Chris@16
|
172 inline void thread_yield()
|
Chris@16
|
173 { winapi::sched_yield(); }
|
Chris@16
|
174
|
Chris@16
|
175 inline void thread_sleep(unsigned int ms)
|
Chris@101
|
176 { winapi::sleep(ms); }
|
Chris@16
|
177
|
Chris@16
|
178 //systemwide thread
|
Chris@16
|
179 inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
|
Chris@16
|
180 {
|
Chris@16
|
181 return get_current_thread_id();
|
Chris@16
|
182 }
|
Chris@16
|
183
|
Chris@16
|
184 inline void systemwide_thread_id_copy
|
Chris@16
|
185 (const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
|
Chris@16
|
186 {
|
Chris@16
|
187 to = from;
|
Chris@16
|
188 }
|
Chris@16
|
189
|
Chris@16
|
190 inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
|
Chris@16
|
191 {
|
Chris@16
|
192 return equal_thread_id(id1, id2);
|
Chris@16
|
193 }
|
Chris@16
|
194
|
Chris@16
|
195 inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
|
Chris@16
|
196 {
|
Chris@16
|
197 return get_invalid_thread_id();
|
Chris@16
|
198 }
|
Chris@16
|
199
|
Chris@16
|
200 inline long double get_current_process_creation_time()
|
Chris@16
|
201 {
|
Chris@16
|
202 winapi::interprocess_filetime CreationTime, ExitTime, KernelTime, UserTime;
|
Chris@16
|
203
|
Chris@101
|
204 winapi::get_process_times
|
Chris@16
|
205 ( winapi::get_current_process(), &CreationTime, &ExitTime, &KernelTime, &UserTime);
|
Chris@16
|
206
|
Chris@16
|
207 typedef long double ldouble_t;
|
Chris@16
|
208 const ldouble_t resolution = (100.0l/1000000000.0l);
|
Chris@16
|
209 return CreationTime.dwHighDateTime*(ldouble_t(1u<<31u)*2.0l*resolution) +
|
Chris@16
|
210 CreationTime.dwLowDateTime*resolution;
|
Chris@16
|
211 }
|
Chris@16
|
212
|
Chris@16
|
213 inline unsigned int get_num_cores()
|
Chris@16
|
214 {
|
Chris@16
|
215 winapi::system_info sysinfo;
|
Chris@16
|
216 winapi::get_system_info( &sysinfo );
|
Chris@16
|
217 //in Windows dw is long which is equal in bits to int
|
Chris@16
|
218 return static_cast<unsigned>(sysinfo.dwNumberOfProcessors);
|
Chris@16
|
219 }
|
Chris@16
|
220
|
Chris@101
|
221 #else //#if defined (BOOST_INTERPROCESS_WINDOWS)
|
Chris@16
|
222
|
Chris@16
|
223 typedef pthread_t OS_thread_t;
|
Chris@16
|
224 typedef pthread_t OS_thread_id_t;
|
Chris@16
|
225 typedef pid_t OS_process_id_t;
|
Chris@16
|
226
|
Chris@16
|
227 struct OS_systemwide_thread_id_t
|
Chris@16
|
228 {
|
Chris@16
|
229 OS_systemwide_thread_id_t()
|
Chris@16
|
230 : pid(), tid()
|
Chris@16
|
231 {}
|
Chris@16
|
232
|
Chris@16
|
233 OS_systemwide_thread_id_t(pid_t p, pthread_t t)
|
Chris@16
|
234 : pid(p), tid(t)
|
Chris@16
|
235 {}
|
Chris@16
|
236
|
Chris@16
|
237 OS_systemwide_thread_id_t(const OS_systemwide_thread_id_t &x)
|
Chris@16
|
238 : pid(x.pid), tid(x.tid)
|
Chris@16
|
239 {}
|
Chris@16
|
240
|
Chris@16
|
241 OS_systemwide_thread_id_t(const volatile OS_systemwide_thread_id_t &x)
|
Chris@16
|
242 : pid(x.pid), tid(x.tid)
|
Chris@16
|
243 {}
|
Chris@16
|
244
|
Chris@16
|
245 OS_systemwide_thread_id_t & operator=(const OS_systemwide_thread_id_t &x)
|
Chris@16
|
246 { pid = x.pid; tid = x.tid; return *this; }
|
Chris@16
|
247
|
Chris@16
|
248 OS_systemwide_thread_id_t & operator=(const volatile OS_systemwide_thread_id_t &x)
|
Chris@16
|
249 { pid = x.pid; tid = x.tid; return *this; }
|
Chris@16
|
250
|
Chris@16
|
251 void operator=(const OS_systemwide_thread_id_t &x) volatile
|
Chris@16
|
252 { pid = x.pid; tid = x.tid; }
|
Chris@16
|
253
|
Chris@16
|
254 pid_t pid;
|
Chris@16
|
255 pthread_t tid;
|
Chris@16
|
256 };
|
Chris@16
|
257
|
Chris@16
|
258 inline void systemwide_thread_id_copy
|
Chris@16
|
259 (const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
|
Chris@16
|
260 {
|
Chris@16
|
261 to.pid = from.pid;
|
Chris@16
|
262 to.tid = from.tid;
|
Chris@16
|
263 }
|
Chris@16
|
264
|
Chris@16
|
265 //process
|
Chris@16
|
266 inline OS_process_id_t get_current_process_id()
|
Chris@16
|
267 { return ::getpid(); }
|
Chris@16
|
268
|
Chris@16
|
269 inline OS_process_id_t get_invalid_process_id()
|
Chris@16
|
270 { return pid_t(0); }
|
Chris@16
|
271
|
Chris@16
|
272 //thread
|
Chris@16
|
273 inline OS_thread_id_t get_current_thread_id()
|
Chris@16
|
274 { return ::pthread_self(); }
|
Chris@16
|
275
|
Chris@16
|
276 inline OS_thread_id_t get_invalid_thread_id()
|
Chris@16
|
277 {
|
Chris@16
|
278 static pthread_t invalid_id;
|
Chris@16
|
279 return invalid_id;
|
Chris@16
|
280 }
|
Chris@16
|
281
|
Chris@16
|
282 inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
|
Chris@16
|
283 { return 0 != pthread_equal(id1, id2); }
|
Chris@16
|
284
|
Chris@16
|
285 inline void thread_yield()
|
Chris@16
|
286 { ::sched_yield(); }
|
Chris@16
|
287
|
Chris@16
|
288 #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
|
Chris@16
|
289 typedef struct timespec OS_highres_count_t;
|
Chris@16
|
290 #else
|
Chris@16
|
291 typedef unsigned long long OS_highres_count_t;
|
Chris@16
|
292 #endif
|
Chris@16
|
293
|
Chris@16
|
294 inline unsigned long get_system_tick_ns()
|
Chris@16
|
295 {
|
Chris@16
|
296 #ifdef _SC_CLK_TCK
|
Chris@101
|
297 long ticks_per_second =::sysconf(_SC_CLK_TCK); // ticks per sec
|
Chris@101
|
298 if(ticks_per_second <= 0){ //Try a typical value on error
|
Chris@101
|
299 ticks_per_second = 100;
|
Chris@16
|
300 }
|
Chris@101
|
301 return 999999999ul/static_cast<unsigned long>(ticks_per_second)+1ul;
|
Chris@16
|
302 #else
|
Chris@16
|
303 #error "Can't obtain system tick value for your system, please provide a patch"
|
Chris@16
|
304 #endif
|
Chris@16
|
305 }
|
Chris@16
|
306
|
Chris@16
|
307 inline unsigned long get_system_tick_in_highres_counts()
|
Chris@16
|
308 {
|
Chris@16
|
309 #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
|
Chris@16
|
310 return get_system_tick_ns();
|
Chris@16
|
311 #else
|
Chris@16
|
312 mach_timebase_info_data_t info;
|
Chris@16
|
313 mach_timebase_info(&info);
|
Chris@16
|
314 //ns
|
Chris@16
|
315 return static_cast<unsigned long>
|
Chris@101
|
316 (
|
Chris@101
|
317 static_cast<double>(get_system_tick_ns())
|
Chris@16
|
318 / (static_cast<double>(info.numer) / info.denom)
|
Chris@16
|
319 );
|
Chris@16
|
320 #endif
|
Chris@16
|
321 }
|
Chris@16
|
322
|
Chris@16
|
323 //return system ticks in us
|
Chris@16
|
324 inline unsigned long get_system_tick_us()
|
Chris@16
|
325 {
|
Chris@16
|
326 return (get_system_tick_ns()-1)/1000ul + 1ul;
|
Chris@16
|
327 }
|
Chris@16
|
328
|
Chris@16
|
329 inline OS_highres_count_t get_current_system_highres_count()
|
Chris@16
|
330 {
|
Chris@16
|
331 #if defined(BOOST_INTERPROCESS_CLOCK_MONOTONIC)
|
Chris@16
|
332 struct timespec count;
|
Chris@16
|
333 ::clock_gettime(BOOST_INTERPROCESS_CLOCK_MONOTONIC, &count);
|
Chris@16
|
334 return count;
|
Chris@16
|
335 #elif defined(BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME)
|
Chris@16
|
336 return ::mach_absolute_time();
|
Chris@16
|
337 #endif
|
Chris@16
|
338 }
|
Chris@16
|
339
|
Chris@16
|
340 #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
|
Chris@16
|
341
|
Chris@16
|
342 inline void zero_highres_count(OS_highres_count_t &count)
|
Chris@16
|
343 { count.tv_sec = 0; count.tv_nsec = 0; }
|
Chris@16
|
344
|
Chris@16
|
345 inline bool is_highres_count_zero(const OS_highres_count_t &count)
|
Chris@16
|
346 { return count.tv_sec == 0 && count.tv_nsec == 0; }
|
Chris@16
|
347
|
Chris@16
|
348 template <class Ostream>
|
Chris@16
|
349 inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
|
Chris@16
|
350 {
|
Chris@16
|
351 ostream << count.tv_sec << "s:" << count.tv_nsec << "ns";
|
Chris@16
|
352 return ostream;
|
Chris@16
|
353 }
|
Chris@16
|
354
|
Chris@16
|
355 inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
|
Chris@16
|
356 {
|
Chris@16
|
357 OS_highres_count_t res;
|
Chris@16
|
358
|
Chris@16
|
359 if (l.tv_nsec < r.tv_nsec){
|
Chris@101
|
360 res.tv_nsec = 1000000000 + l.tv_nsec - r.tv_nsec;
|
Chris@16
|
361 res.tv_sec = l.tv_sec - 1 - r.tv_sec;
|
Chris@16
|
362 }
|
Chris@16
|
363 else{
|
Chris@101
|
364 res.tv_nsec = l.tv_nsec - r.tv_nsec;
|
Chris@16
|
365 res.tv_sec = l.tv_sec - r.tv_sec;
|
Chris@16
|
366 }
|
Chris@16
|
367
|
Chris@16
|
368 return res;
|
Chris@16
|
369 }
|
Chris@16
|
370
|
Chris@16
|
371 inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
|
Chris@16
|
372 { return l.tv_sec < r.tv_sec || (l.tv_sec == r.tv_sec && l.tv_nsec < r.tv_nsec); }
|
Chris@16
|
373
|
Chris@16
|
374 inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r)
|
Chris@101
|
375 { return !l.tv_sec && (static_cast<unsigned long>(l.tv_nsec) < r); }
|
Chris@16
|
376
|
Chris@16
|
377 #else
|
Chris@16
|
378
|
Chris@16
|
379 inline void zero_highres_count(OS_highres_count_t &count)
|
Chris@16
|
380 { count = 0; }
|
Chris@16
|
381
|
Chris@16
|
382 inline bool is_highres_count_zero(const OS_highres_count_t &count)
|
Chris@16
|
383 { return count == 0; }
|
Chris@16
|
384
|
Chris@16
|
385 template <class Ostream>
|
Chris@16
|
386 inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
|
Chris@16
|
387 {
|
Chris@16
|
388 ostream << count ;
|
Chris@16
|
389 return ostream;
|
Chris@16
|
390 }
|
Chris@16
|
391
|
Chris@16
|
392 inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
|
Chris@16
|
393 { return l - r; }
|
Chris@16
|
394
|
Chris@16
|
395 inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
|
Chris@16
|
396 { return l < r; }
|
Chris@16
|
397
|
Chris@16
|
398 inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r)
|
Chris@16
|
399 { return l < static_cast<OS_highres_count_t>(r); }
|
Chris@16
|
400
|
Chris@16
|
401 #endif
|
Chris@16
|
402
|
Chris@16
|
403 inline void thread_sleep_tick()
|
Chris@16
|
404 {
|
Chris@16
|
405 struct timespec rqt;
|
Chris@16
|
406 //Sleep for the half of the tick time
|
Chris@16
|
407 rqt.tv_sec = 0;
|
Chris@16
|
408 rqt.tv_nsec = get_system_tick_ns()/2;
|
Chris@16
|
409 ::nanosleep(&rqt, 0);
|
Chris@16
|
410 }
|
Chris@16
|
411
|
Chris@16
|
412 inline void thread_sleep(unsigned int ms)
|
Chris@16
|
413 {
|
Chris@16
|
414 struct timespec rqt;
|
Chris@16
|
415 rqt.tv_sec = ms/1000u;
|
Chris@16
|
416 rqt.tv_nsec = (ms%1000u)*1000000u;
|
Chris@16
|
417 ::nanosleep(&rqt, 0);
|
Chris@16
|
418 }
|
Chris@16
|
419
|
Chris@16
|
420 //systemwide thread
|
Chris@16
|
421 inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
|
Chris@16
|
422 {
|
Chris@16
|
423 return OS_systemwide_thread_id_t(::getpid(), ::pthread_self());
|
Chris@16
|
424 }
|
Chris@16
|
425
|
Chris@16
|
426 inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
|
Chris@16
|
427 {
|
Chris@16
|
428 return (0 != pthread_equal(id1.tid, id2.tid)) && (id1.pid == id2.pid);
|
Chris@16
|
429 }
|
Chris@16
|
430
|
Chris@16
|
431 inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
|
Chris@16
|
432 {
|
Chris@16
|
433 return OS_systemwide_thread_id_t(get_invalid_process_id(), get_invalid_thread_id());
|
Chris@16
|
434 }
|
Chris@16
|
435
|
Chris@16
|
436 inline long double get_current_process_creation_time()
|
Chris@16
|
437 { return 0.0L; }
|
Chris@16
|
438
|
Chris@16
|
439 inline unsigned int get_num_cores()
|
Chris@16
|
440 {
|
Chris@16
|
441 #ifdef _SC_NPROCESSORS_ONLN
|
Chris@16
|
442 long cores = ::sysconf(_SC_NPROCESSORS_ONLN);
|
Chris@16
|
443 // sysconf returns -1 if the name is invalid, the option does not exist or
|
Chris@16
|
444 // does not have a definite limit.
|
Chris@16
|
445 // if sysconf returns some other negative number, we have no idea
|
Chris@16
|
446 // what is going on. Default to something safe.
|
Chris@16
|
447 if(cores <= 0){
|
Chris@16
|
448 return 1;
|
Chris@16
|
449 }
|
Chris@16
|
450 //Check for overflow (unlikely)
|
Chris@16
|
451 else if(static_cast<unsigned long>(cores) >=
|
Chris@16
|
452 static_cast<unsigned long>(static_cast<unsigned int>(-1))){
|
Chris@16
|
453 return static_cast<unsigned int>(-1);
|
Chris@16
|
454 }
|
Chris@16
|
455 else{
|
Chris@16
|
456 return static_cast<unsigned int>(cores);
|
Chris@16
|
457 }
|
Chris@16
|
458 #elif defined(BOOST_INTERPROCESS_BSD_DERIVATIVE) && defined(HW_NCPU)
|
Chris@16
|
459 int request[2] = { CTL_HW, HW_NCPU };
|
Chris@16
|
460 int num_cores;
|
Chris@16
|
461 std::size_t result_len = sizeof(num_cores);
|
Chris@16
|
462 if ( (::sysctl (request, 2, &num_cores, &result_len, 0, 0) < 0) || (num_cores <= 0) ){
|
Chris@16
|
463 //Return a safe value
|
Chris@16
|
464 return 1;
|
Chris@16
|
465 }
|
Chris@16
|
466 else{
|
Chris@16
|
467 return static_cast<unsigned int>(num_cores);
|
Chris@16
|
468 }
|
Chris@16
|
469 #endif
|
Chris@16
|
470 }
|
Chris@16
|
471
|
Chris@16
|
472 inline int thread_create(OS_thread_t * thread, void *(*start_routine)(void*), void* arg)
|
Chris@16
|
473 { return pthread_create(thread, 0, start_routine, arg); }
|
Chris@16
|
474
|
Chris@16
|
475 inline void thread_join(OS_thread_t thread)
|
Chris@16
|
476 { (void)pthread_join(thread, 0); }
|
Chris@16
|
477
|
Chris@101
|
478 #endif //#if defined (BOOST_INTERPROCESS_WINDOWS)
|
Chris@16
|
479
|
Chris@16
|
480 typedef char pid_str_t[sizeof(OS_process_id_t)*3+1];
|
Chris@16
|
481
|
Chris@16
|
482 inline void get_pid_str(pid_str_t &pid_str, OS_process_id_t pid)
|
Chris@16
|
483 {
|
Chris@16
|
484 bufferstream bstream(pid_str, sizeof(pid_str));
|
Chris@16
|
485 bstream << pid << std::ends;
|
Chris@16
|
486 }
|
Chris@16
|
487
|
Chris@16
|
488 inline void get_pid_str(pid_str_t &pid_str)
|
Chris@16
|
489 { get_pid_str(pid_str, get_current_process_id()); }
|
Chris@16
|
490
|
Chris@16
|
491 #if defined(BOOST_INTERPROCESS_WINDOWS)
|
Chris@16
|
492
|
Chris@16
|
493 inline int thread_create( OS_thread_t * thread, unsigned (__stdcall * start_routine) (void*), void* arg )
|
Chris@16
|
494 {
|
Chris@16
|
495 void* h = (void*)_beginthreadex( 0, 0, start_routine, arg, 0, 0 );
|
Chris@16
|
496
|
Chris@16
|
497 if( h != 0 ){
|
Chris@16
|
498 *thread = h;
|
Chris@16
|
499 return 0;
|
Chris@16
|
500 }
|
Chris@16
|
501 else{
|
Chris@16
|
502 return 1;
|
Chris@16
|
503 }
|
Chris@16
|
504 }
|
Chris@16
|
505
|
Chris@16
|
506 inline void thread_join( OS_thread_t thread)
|
Chris@16
|
507 {
|
Chris@16
|
508 winapi::wait_for_single_object( thread, winapi::infinite_time );
|
Chris@16
|
509 winapi::close_handle( thread );
|
Chris@16
|
510 }
|
Chris@16
|
511
|
Chris@16
|
512 #endif
|
Chris@16
|
513
|
Chris@16
|
514 class abstract_thread
|
Chris@16
|
515 {
|
Chris@16
|
516 public:
|
Chris@16
|
517 virtual ~abstract_thread() {}
|
Chris@16
|
518 virtual void run() = 0;
|
Chris@16
|
519 };
|
Chris@16
|
520
|
Chris@101
|
521 template<class T>
|
Chris@101
|
522 class os_thread_func_ptr_deleter
|
Chris@101
|
523 {
|
Chris@101
|
524 public:
|
Chris@101
|
525 explicit os_thread_func_ptr_deleter(T* p)
|
Chris@101
|
526 : m_p(p)
|
Chris@101
|
527 {}
|
Chris@101
|
528
|
Chris@101
|
529 T *release()
|
Chris@101
|
530 { T *p = m_p; m_p = 0; return p; }
|
Chris@101
|
531
|
Chris@101
|
532 T *get() const
|
Chris@101
|
533 { return m_p; }
|
Chris@101
|
534
|
Chris@101
|
535 T *operator ->() const
|
Chris@101
|
536 { return m_p; }
|
Chris@101
|
537
|
Chris@101
|
538 ~os_thread_func_ptr_deleter()
|
Chris@101
|
539 { delete m_p; }
|
Chris@101
|
540
|
Chris@101
|
541 private:
|
Chris@101
|
542 T *m_p;
|
Chris@101
|
543 };
|
Chris@101
|
544
|
Chris@16
|
545 #if defined(BOOST_INTERPROCESS_WINDOWS)
|
Chris@16
|
546
|
Chris@16
|
547 inline unsigned __stdcall launch_thread_routine( void * pv )
|
Chris@16
|
548 {
|
Chris@101
|
549 os_thread_func_ptr_deleter<abstract_thread> pt( static_cast<abstract_thread *>( pv ) );
|
Chris@16
|
550 pt->run();
|
Chris@16
|
551 return 0;
|
Chris@16
|
552 }
|
Chris@16
|
553
|
Chris@16
|
554 #else
|
Chris@16
|
555
|
Chris@16
|
556 extern "C" void * launch_thread_routine( void * pv );
|
Chris@16
|
557
|
Chris@16
|
558 inline void * launch_thread_routine( void * pv )
|
Chris@16
|
559 {
|
Chris@101
|
560 os_thread_func_ptr_deleter<abstract_thread> pt( static_cast<abstract_thread *>( pv ) );
|
Chris@16
|
561 pt->run();
|
Chris@16
|
562 return 0;
|
Chris@16
|
563 }
|
Chris@16
|
564
|
Chris@16
|
565 #endif
|
Chris@16
|
566
|
Chris@16
|
567 template<class F>
|
Chris@16
|
568 class launch_thread_impl
|
Chris@16
|
569 : public abstract_thread
|
Chris@16
|
570 {
|
Chris@16
|
571 public:
|
Chris@16
|
572 explicit launch_thread_impl( F f )
|
Chris@16
|
573 : f_( f )
|
Chris@16
|
574 {}
|
Chris@16
|
575
|
Chris@16
|
576 void run()
|
Chris@16
|
577 { f_(); }
|
Chris@16
|
578
|
Chris@16
|
579 private:
|
Chris@16
|
580 F f_;
|
Chris@16
|
581 };
|
Chris@16
|
582
|
Chris@16
|
583 template<class F>
|
Chris@16
|
584 inline int thread_launch( OS_thread_t & pt, F f )
|
Chris@16
|
585 {
|
Chris@101
|
586 os_thread_func_ptr_deleter<abstract_thread> p( new launch_thread_impl<F>( f ) );
|
Chris@16
|
587
|
Chris@16
|
588 int r = thread_create(&pt, launch_thread_routine, p.get());
|
Chris@16
|
589 if( r == 0 ){
|
Chris@16
|
590 p.release();
|
Chris@16
|
591 }
|
Chris@16
|
592
|
Chris@16
|
593 return r;
|
Chris@16
|
594 }
|
Chris@16
|
595
|
Chris@16
|
596 } //namespace ipcdetail{
|
Chris@16
|
597 } //namespace interprocess {
|
Chris@16
|
598 } //namespace boost {
|
Chris@16
|
599
|
Chris@16
|
600 #include <boost/interprocess/detail/config_end.hpp>
|
Chris@16
|
601
|
Chris@16
|
602 #endif //BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
|