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