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