File indexing completed on 2025-01-18 09:38:26
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #ifndef BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
0023 #define BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
0024
0025 #ifndef BOOST_CONFIG_HPP
0026 # include <boost/config.hpp>
0027 #endif
0028 #
0029 #if defined(BOOST_HAS_PRAGMA_ONCE)
0030 # pragma once
0031 #endif
0032
0033 #include <boost/interprocess/detail/config_begin.hpp>
0034 #include <boost/interprocess/detail/workaround.hpp>
0035 #include <boost/interprocess/streams/bufferstream.hpp>
0036 #include <cstddef>
0037 #include <ostream>
0038
0039 #if defined(BOOST_INTERPROCESS_WINDOWS)
0040 # include <boost/interprocess/detail/win32_api.hpp>
0041 # include <boost/winapi/thread.hpp>
0042 #else
0043 # include <pthread.h>
0044 # include <unistd.h>
0045 # include <sched.h>
0046 # include <time.h>
0047 # ifdef BOOST_INTERPROCESS_BSD_DERIVATIVE
0048
0049
0050 # include <sys/types.h>
0051 # include <sys/param.h>
0052 # include <sys/sysctl.h>
0053 # endif
0054 #if defined(__VXWORKS__)
0055 #include <vxCpuLib.h>
0056 #endif
0057
0058
0059
0060 # if (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
0061 # include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t
0062 # define BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
0063 # elif defined(CLOCK_MONOTONIC_PRECISE)
0064 # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_PRECISE
0065 # elif defined(CLOCK_MONOTONIC_RAW)
0066 # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_RAW
0067 # elif defined(CLOCK_HIGHRES)
0068 # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_HIGHRES
0069 # elif defined(CLOCK_MONOTONIC)
0070 # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC
0071 # else
0072 # error "No high resolution steady clock in your system, please provide a patch"
0073 # endif
0074 #endif
0075
0076 namespace boost {
0077 namespace interprocess {
0078 namespace ipcdetail{
0079
0080 #if defined (BOOST_INTERPROCESS_WINDOWS)
0081
0082 typedef unsigned long OS_process_id_t;
0083 typedef unsigned long OS_thread_id_t;
0084 struct OS_thread_t
0085 {
0086 OS_thread_t()
0087 : m_handle()
0088 {}
0089
0090
0091 void* handle() const
0092 { return m_handle; }
0093
0094 void* m_handle;
0095 };
0096
0097 typedef OS_thread_id_t OS_systemwide_thread_id_t;
0098
0099
0100 inline OS_process_id_t get_current_process_id()
0101 { return winapi::get_current_process_id(); }
0102
0103 inline OS_process_id_t get_invalid_process_id()
0104 { return OS_process_id_t(0); }
0105
0106
0107 inline OS_thread_id_t get_current_thread_id()
0108 { return winapi::get_current_thread_id(); }
0109
0110 inline OS_thread_id_t get_invalid_thread_id()
0111 { return OS_thread_id_t(0xffffffff); }
0112
0113 inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
0114 { return id1 == id2; }
0115
0116
0117 inline unsigned long get_system_tick_ns()
0118 {
0119 unsigned long curres, ignore1, ignore2;
0120 winapi::query_timer_resolution(&ignore1, &ignore2, &curres);
0121
0122 return (curres - 1ul)*100ul;
0123 }
0124
0125
0126 inline unsigned long get_system_tick_us()
0127 {
0128 unsigned long curres, ignore1, ignore2;
0129 winapi::query_timer_resolution(&ignore1, &ignore2, &curres);
0130
0131 return (curres - 1ul)/10ul + 1ul;
0132 }
0133
0134 typedef unsigned __int64 OS_highres_count_t;
0135
0136 inline unsigned long get_system_tick_in_highres_counts()
0137 {
0138 __int64 freq;
0139 unsigned long curres, ignore1, ignore2;
0140 winapi::query_timer_resolution(&ignore1, &ignore2, &curres);
0141
0142 if(!winapi::query_performance_frequency(&freq)){
0143
0144 return (curres-1ul)/10000ul + 1ul;
0145 }
0146 else{
0147
0148 __int64 count_fs = (1000000000000000LL - 1LL)/freq + 1LL;
0149 __int64 tick_counts = (static_cast<__int64>(curres)*100000000LL - 1LL)/count_fs + 1LL;
0150 return static_cast<unsigned long>(tick_counts);
0151 }
0152 }
0153
0154 inline OS_highres_count_t get_current_system_highres_count()
0155 {
0156 __int64 count;
0157 if(!winapi::query_performance_counter(&count)){
0158 count = winapi::get_tick_count();
0159 }
0160 return (OS_highres_count_t)count;
0161 }
0162
0163 inline void zero_highres_count(OS_highres_count_t &count)
0164 { count = 0; }
0165
0166 inline bool is_highres_count_zero(const OS_highres_count_t &count)
0167 { return count == 0; }
0168
0169 template <class Ostream>
0170 inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
0171 {
0172 ostream << count;
0173 return ostream;
0174 }
0175
0176 inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
0177 { return l - r; }
0178
0179 inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
0180 { return l < r; }
0181
0182 inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r)
0183 { return l < static_cast<OS_highres_count_t>(r); }
0184
0185 inline void thread_sleep_tick()
0186 { winapi::sleep_tick(); }
0187
0188 inline void thread_yield()
0189 { winapi::sched_yield(); }
0190
0191 inline void thread_sleep(unsigned int ms)
0192 { winapi::sleep(ms); }
0193
0194
0195 inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
0196 {
0197 return get_current_thread_id();
0198 }
0199
0200 inline void systemwide_thread_id_copy
0201 (const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
0202 {
0203 to = from;
0204 }
0205
0206 inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
0207 {
0208 return equal_thread_id(id1, id2);
0209 }
0210
0211 inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
0212 {
0213 return get_invalid_thread_id();
0214 }
0215
0216 inline long double get_current_process_creation_time()
0217 {
0218 winapi::interprocess_filetime CreationTime, ExitTime, KernelTime, UserTime;
0219
0220 winapi::get_process_times
0221 ( winapi::get_current_process(), &CreationTime, &ExitTime, &KernelTime, &UserTime);
0222
0223 typedef long double ldouble_t;
0224 const ldouble_t resolution = (100.0l/1000000000.0l);
0225 return CreationTime.dwHighDateTime*(ldouble_t(1u<<31u)*2.0l*resolution) +
0226 CreationTime.dwLowDateTime*resolution;
0227 }
0228
0229 inline unsigned int get_num_cores()
0230 {
0231 winapi::interprocess_system_info sysinfo;
0232 winapi::get_system_info( &sysinfo );
0233
0234 return static_cast<unsigned>(sysinfo.dwNumberOfProcessors);
0235 }
0236
0237 #else
0238
0239 typedef pthread_t OS_thread_t;
0240 typedef pthread_t OS_thread_id_t;
0241 typedef pid_t OS_process_id_t;
0242
0243 struct OS_systemwide_thread_id_t
0244 {
0245 OS_systemwide_thread_id_t()
0246 : pid(), tid()
0247 {}
0248
0249 OS_systemwide_thread_id_t(pid_t p, pthread_t t)
0250 : pid(p), tid(t)
0251 {}
0252
0253 OS_systemwide_thread_id_t(const OS_systemwide_thread_id_t &x)
0254 : pid(x.pid), tid(x.tid)
0255 {}
0256
0257 OS_systemwide_thread_id_t(const volatile OS_systemwide_thread_id_t &x)
0258 : pid(x.pid), tid(x.tid)
0259 {}
0260
0261 OS_systemwide_thread_id_t & operator=(const OS_systemwide_thread_id_t &x)
0262 { pid = x.pid; tid = x.tid; return *this; }
0263
0264 OS_systemwide_thread_id_t & operator=(const volatile OS_systemwide_thread_id_t &x)
0265 { pid = x.pid; tid = x.tid; return *this; }
0266
0267 void operator=(const OS_systemwide_thread_id_t &x) volatile
0268 { pid = x.pid; tid = x.tid; }
0269
0270 pid_t pid;
0271 pthread_t tid;
0272 };
0273
0274 inline void systemwide_thread_id_copy
0275 (const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
0276 {
0277 to.pid = from.pid;
0278 to.tid = from.tid;
0279 }
0280
0281
0282 inline OS_process_id_t get_current_process_id()
0283 { return ::getpid(); }
0284
0285 inline OS_process_id_t get_invalid_process_id()
0286 { return pid_t(0); }
0287
0288
0289 inline OS_thread_id_t get_current_thread_id()
0290 { return ::pthread_self(); }
0291
0292 inline OS_thread_id_t get_invalid_thread_id()
0293 {
0294 static pthread_t invalid_id;
0295 return invalid_id;
0296 }
0297
0298 inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
0299 { return 0 != pthread_equal(id1, id2); }
0300
0301 inline void thread_yield()
0302 { ::sched_yield(); }
0303
0304 #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
0305 typedef struct timespec OS_highres_count_t;
0306 #else
0307 typedef unsigned long long OS_highres_count_t;
0308 #endif
0309
0310 inline unsigned long get_system_tick_ns()
0311 {
0312 #ifdef _SC_CLK_TCK
0313 long ticks_per_second =::sysconf(_SC_CLK_TCK);
0314 if(ticks_per_second <= 0){
0315 ticks_per_second = 100;
0316 }
0317 return 999999999ul/static_cast<unsigned long>(ticks_per_second)+1ul;
0318 #else
0319 #error "Can't obtain system tick value for your system, please provide a patch"
0320 #endif
0321 }
0322
0323 inline unsigned long get_system_tick_in_highres_counts()
0324 {
0325 #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
0326 return get_system_tick_ns();
0327 #else
0328 mach_timebase_info_data_t info;
0329 mach_timebase_info(&info);
0330
0331 return static_cast<unsigned long>
0332 (
0333 static_cast<double>(get_system_tick_ns())
0334 / (static_cast<double>(info.numer) / info.denom)
0335 );
0336 #endif
0337 }
0338
0339
0340 inline unsigned long get_system_tick_us()
0341 {
0342 return (get_system_tick_ns()-1)/1000ul + 1ul;
0343 }
0344
0345 inline OS_highres_count_t get_current_system_highres_count()
0346 {
0347 #if defined(BOOST_INTERPROCESS_CLOCK_MONOTONIC)
0348 struct timespec count;
0349 ::clock_gettime(BOOST_INTERPROCESS_CLOCK_MONOTONIC, &count);
0350 return count;
0351 #elif defined(BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME)
0352 return ::mach_absolute_time();
0353 #endif
0354 }
0355
0356 #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
0357
0358 inline void zero_highres_count(OS_highres_count_t &count)
0359 { count.tv_sec = 0; count.tv_nsec = 0; }
0360
0361 inline bool is_highres_count_zero(const OS_highres_count_t &count)
0362 { return count.tv_sec == 0 && count.tv_nsec == 0; }
0363
0364 template <class Ostream>
0365 inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
0366 {
0367 ostream << count.tv_sec << "s:" << count.tv_nsec << "ns";
0368 return ostream;
0369 }
0370
0371 inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
0372 {
0373 OS_highres_count_t res;
0374
0375 if (l.tv_nsec < r.tv_nsec){
0376 res.tv_nsec = 1000000000 + l.tv_nsec - r.tv_nsec;
0377 res.tv_sec = l.tv_sec - 1 - r.tv_sec;
0378 }
0379 else{
0380 res.tv_nsec = l.tv_nsec - r.tv_nsec;
0381 res.tv_sec = l.tv_sec - r.tv_sec;
0382 }
0383
0384 return res;
0385 }
0386
0387 inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
0388 { return l.tv_sec < r.tv_sec || (l.tv_sec == r.tv_sec && l.tv_nsec < r.tv_nsec); }
0389
0390 inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r)
0391 { return !l.tv_sec && (static_cast<unsigned long>(l.tv_nsec) < r); }
0392
0393 #else
0394
0395 inline void zero_highres_count(OS_highres_count_t &count)
0396 { count = 0; }
0397
0398 inline bool is_highres_count_zero(const OS_highres_count_t &count)
0399 { return count == 0; }
0400
0401 template <class Ostream>
0402 inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
0403 {
0404 ostream << count ;
0405 return ostream;
0406 }
0407
0408 inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
0409 { return l - r; }
0410
0411 inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
0412 { return l < r; }
0413
0414 inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r)
0415 { return l < static_cast<OS_highres_count_t>(r); }
0416
0417 #endif
0418
0419 inline void thread_sleep_tick()
0420 {
0421 struct timespec rqt;
0422
0423 rqt.tv_sec = 0;
0424 rqt.tv_nsec = (long)get_system_tick_ns()/2;
0425 ::nanosleep(&rqt, 0);
0426 }
0427
0428 inline void thread_sleep(unsigned int ms)
0429 {
0430 struct timespec rqt;
0431 rqt.tv_sec = ms/1000u;
0432 rqt.tv_nsec = (ms%1000u)*1000000u;
0433 ::nanosleep(&rqt, 0);
0434 }
0435
0436
0437 inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
0438 {
0439 return OS_systemwide_thread_id_t(::getpid(), ::pthread_self());
0440 }
0441
0442 inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
0443 {
0444 return (0 != pthread_equal(id1.tid, id2.tid)) && (id1.pid == id2.pid);
0445 }
0446
0447 inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
0448 {
0449 return OS_systemwide_thread_id_t(get_invalid_process_id(), get_invalid_thread_id());
0450 }
0451
0452 inline long double get_current_process_creation_time()
0453 { return 0.0L; }
0454
0455 inline unsigned int get_num_cores()
0456 {
0457 #ifdef _SC_NPROCESSORS_ONLN
0458 long cores = ::sysconf(_SC_NPROCESSORS_ONLN);
0459
0460
0461
0462
0463 if(cores <= 0){
0464 return 1;
0465 }
0466
0467 else if(static_cast<unsigned long>(cores) >=
0468 static_cast<unsigned long>(static_cast<unsigned int>(-1))){
0469 return static_cast<unsigned int>(-1);
0470 }
0471 else{
0472 return static_cast<unsigned int>(cores);
0473 }
0474 #elif defined(BOOST_INTERPROCESS_BSD_DERIVATIVE) && defined(HW_NCPU)
0475 int request[2] = { CTL_HW, HW_NCPU };
0476 int num_cores;
0477 std::size_t result_len = sizeof(num_cores);
0478 if ( (::sysctl (request, 2, &num_cores, &result_len, 0, 0) < 0) || (num_cores <= 0) ){
0479
0480 return 1;
0481 }
0482 else{
0483 return static_cast<unsigned int>(num_cores);
0484 }
0485 #elif defined(__VXWORKS__)
0486 cpuset_t set = ::vxCpuEnabledGet();
0487 #ifdef __DCC__
0488 int i;
0489 for( i = 0; set; ++i)
0490 {
0491 set &= set -1;
0492 }
0493 return(i);
0494 #else
0495 return (__builtin_popcount(set) );
0496 #endif
0497 #endif
0498 }
0499
0500 inline int thread_create(OS_thread_t * thread, void *(*start_routine)(void*), void* arg)
0501 { return pthread_create(thread, 0, start_routine, arg); }
0502
0503 inline void thread_join(OS_thread_t thread)
0504 { (void)pthread_join(thread, 0); }
0505
0506 #endif
0507
0508 typedef char pid_str_t[sizeof(OS_process_id_t)*3+1];
0509
0510 inline void get_pid_str(pid_str_t &pid_str, OS_process_id_t pid)
0511 {
0512 bufferstream bstream(pid_str, sizeof(pid_str));
0513 bstream << pid << std::ends;
0514 }
0515
0516 inline void get_pid_str(pid_str_t &pid_str)
0517 { get_pid_str(pid_str, get_current_process_id()); }
0518
0519 #if defined(BOOST_INTERPROCESS_WINDOWS)
0520
0521 inline int thread_create( OS_thread_t * thread, boost::ipwinapiext::LPTHREAD_START_ROUTINE_ start_routine, void* arg )
0522 {
0523 void* h = boost::ipwinapiext::CreateThread(0, 0, start_routine, arg, 0, 0);
0524
0525 if( h != 0 ){
0526 thread->m_handle = h;
0527 return 0;
0528 }
0529 else{
0530 return 1;
0531 }
0532 }
0533
0534 inline void thread_join( OS_thread_t thread)
0535 {
0536 winapi::wait_for_single_object( thread.handle(), winapi::infinite_time );
0537 winapi::close_handle( thread.handle() );
0538 }
0539
0540 #endif
0541
0542 class abstract_thread
0543 {
0544 public:
0545 virtual ~abstract_thread() {}
0546 virtual void run() = 0;
0547 };
0548
0549 template<class T>
0550 class os_thread_func_ptr_deleter
0551 {
0552 public:
0553 explicit os_thread_func_ptr_deleter(T* p)
0554 : m_p(p)
0555 {}
0556
0557 T *release()
0558 { T *p = m_p; m_p = 0; return p; }
0559
0560 T *get() const
0561 { return m_p; }
0562
0563 T *operator ->() const
0564 { return m_p; }
0565
0566 ~os_thread_func_ptr_deleter()
0567 { delete m_p; }
0568
0569 private:
0570 T *m_p;
0571 };
0572
0573 #if defined(BOOST_INTERPROCESS_WINDOWS)
0574
0575 inline boost::winapi::DWORD_ __stdcall launch_thread_routine(boost::winapi::LPVOID_ pv)
0576 {
0577 os_thread_func_ptr_deleter<abstract_thread> pt( static_cast<abstract_thread *>( pv ) );
0578 pt->run();
0579 return 0;
0580 }
0581
0582 #else
0583
0584 extern "C" void * launch_thread_routine( void * pv );
0585
0586 inline void * launch_thread_routine( void * pv )
0587 {
0588 os_thread_func_ptr_deleter<abstract_thread> pt( static_cast<abstract_thread *>( pv ) );
0589 pt->run();
0590 return 0;
0591 }
0592
0593 #endif
0594
0595 template<class F>
0596 class launch_thread_impl
0597 : public abstract_thread
0598 {
0599 public:
0600 explicit launch_thread_impl( F f )
0601 : f_( f )
0602 {}
0603
0604 virtual void run() BOOST_OVERRIDE
0605 { f_(); }
0606
0607 private:
0608 F f_;
0609 };
0610
0611 template<class F>
0612 inline int thread_launch( OS_thread_t & pt, F f )
0613 {
0614 os_thread_func_ptr_deleter<abstract_thread> p( new launch_thread_impl<F>( f ) );
0615
0616 int r = thread_create(&pt, launch_thread_routine, p.get());
0617 if( r == 0 ){
0618 p.release();
0619 }
0620
0621 return r;
0622 }
0623
0624 }
0625 }
0626 }
0627
0628 #include <boost/interprocess/detail/config_end.hpp>
0629
0630 #endif