Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:34:06

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
0004 // Software License, Version 1.0. (See accompanying file
0005 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // See http://www.boost.org/libs/interprocess for documentation.
0008 //
0009 //////////////////////////////////////////////////////////////////////////////
0010 
0011 //Thread launching functions are adapted from boost/detail/lightweight_thread.hpp
0012 //
0013 //  boost/detail/lightweight_thread.hpp
0014 //
0015 //  Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
0016 //  Copyright (c) 2008 Peter Dimov
0017 //
0018 //  Distributed under the Boost Software License, Version 1.0.
0019 //  See accompanying file LICENSE_1_0.txt or copy at
0020 //  http://www.boost.org/LICENSE_1_0.txt
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       //Some *BSD systems (OpenBSD & NetBSD) need sys/param.h before sys/sysctl.h, whereas
0050       //others (FreeBSD & Darwin) need sys/types.h
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 //According to the article "C/C++ tip: How to measure elapsed real time for benchmarking"
0059 //Check MacOs first as macOS 10.12 SDK defines both CLOCK_MONOTONIC and
0060 //CLOCK_MONOTONIC_RAW and no clock_gettime.
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)   //BSD
0065 #     define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_PRECISE
0066 #  elif defined(CLOCK_MONOTONIC_RAW)     //Linux
0067 #     define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_RAW
0068 #  elif defined(CLOCK_HIGHRES)           //Solaris
0069 #     define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_HIGHRES
0070 #  elif defined(CLOCK_MONOTONIC)         //POSIX (AIX, BSD, Linux, Solaris)
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 //process
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 //thread
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 //return the system tick in ns
0118 inline unsigned long get_system_tick_ns()
0119 {
0120    unsigned long curres, ignore1, ignore2;
0121    winapi::query_timer_resolution(&ignore1, &ignore2, &curres);
0122    //Windows API returns the value in hundreds of ns
0123    return (curres - 1ul)*100ul;
0124 }
0125 
0126 //return the system tick in us
0127 inline unsigned long get_system_tick_us()
0128 {
0129    unsigned long curres, ignore1, ignore2;
0130    winapi::query_timer_resolution(&ignore1, &ignore2, &curres);
0131    //Windows API returns the value in hundreds of ns
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    //Frequency in counts per second
0143    if(!winapi::query_performance_frequency(&freq)){
0144       //Tick resolution in ms
0145       return (curres-1ul)/10000ul + 1ul;
0146    }
0147    else{
0148       //In femtoseconds
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 //systemwide thread
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    //in Windows dw is long which is equal in bits to int
0242    return static_cast<unsigned>(sysinfo.dwNumberOfProcessors);
0243 }
0244 
0245 #else    //#if defined (BOOST_INTERPROCESS_WINDOWS)
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 //process
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 //thread
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); // ticks per sec
0322    if(ticks_per_second <= 0){   //Try a typical value on error
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             //ns
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 //return system ticks in us
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    //Sleep for the half of the tick time
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 //systemwide thread
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       // sysconf returns -1 if the name is invalid, the option does not exist or
0488       // does not have a definite limit.
0489       // if sysconf returns some other negative number, we have no idea
0490       // what is going on. Default to something safe.
0491       if(cores <= 0){
0492          return 1;
0493       }
0494       //Check for overflow (unlikely)
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          //Return a safe value
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   //#if defined (BOOST_INTERPROCESS_WINDOWS)
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 }  //namespace ipcdetail{
0665 }  //namespace interprocess {
0666 }  //namespace boost {
0667 
0668 #include <boost/interprocess/detail/config_end.hpp>
0669 
0670 #endif   //BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP