Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // See http://www.boost.org/libs/interprocess for documentation. Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: //Thread launching functions are adapted from boost/detail/lightweight_thread.hpp Chris@16: // Chris@16: // boost/detail/lightweight_thread.hpp Chris@16: // Chris@16: // Copyright (c) 2002 Peter Dimov and Multi Media Ltd. Chris@16: // Copyright (c) 2008 Peter Dimov Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. Chris@16: // See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt Chris@16: Chris@16: #ifndef BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP Chris@16: #define BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP Chris@16: Chris@101: #ifndef BOOST_CONFIG_HPP Chris@101: # include Chris@101: #endif Chris@101: # Chris@101: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@101: # pragma once Chris@101: #endif Chris@101: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@101: #include Chris@16: Chris@16: #if defined(BOOST_INTERPROCESS_WINDOWS) Chris@16: # include Chris@16: # include Chris@16: #else Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # ifdef BOOST_INTERPROCESS_BSD_DERIVATIVE Chris@16: //Some *BSD systems (OpenBSD & NetBSD) need sys/param.h before sys/sysctl.h, whereas Chris@16: //others (FreeBSD & Darwin) need sys/types.h Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # endif Chris@16: //According to the article "C/C++ tip: How to measure elapsed real time for benchmarking" Chris@16: # if defined(CLOCK_MONOTONIC_PRECISE) //BSD Chris@16: # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_PRECISE Chris@16: # elif defined(CLOCK_MONOTONIC_RAW) //Linux Chris@16: # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_RAW Chris@16: # elif defined(CLOCK_HIGHRES) //Solaris Chris@16: # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_HIGHRES Chris@16: # elif defined(CLOCK_MONOTONIC) //POSIX (AIX, BSD, Linux, Solaris) Chris@16: # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC Chris@16: # elif !defined(CLOCK_MONOTONIC) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) Chris@16: # include // mach_absolute_time, mach_timebase_info_data_t Chris@16: # define BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME Chris@16: # else Chris@16: # error "No high resolution steady clock in your system, please provide a patch" Chris@16: # endif Chris@16: #endif Chris@16: Chris@16: namespace boost { Chris@16: namespace interprocess { Chris@16: namespace ipcdetail{ Chris@16: Chris@101: #if defined (BOOST_INTERPROCESS_WINDOWS) Chris@16: Chris@16: typedef unsigned long OS_process_id_t; Chris@16: typedef unsigned long OS_thread_id_t; Chris@16: typedef void* OS_thread_t; Chris@16: typedef OS_thread_id_t OS_systemwide_thread_id_t; Chris@16: Chris@16: //process Chris@16: inline OS_process_id_t get_current_process_id() Chris@16: { return winapi::get_current_process_id(); } Chris@16: Chris@16: inline OS_process_id_t get_invalid_process_id() Chris@16: { return OS_process_id_t(0); } Chris@16: Chris@16: //thread Chris@16: inline OS_thread_id_t get_current_thread_id() Chris@16: { return winapi::get_current_thread_id(); } Chris@16: Chris@16: inline OS_thread_id_t get_invalid_thread_id() Chris@16: { return OS_thread_id_t(0xffffffff); } Chris@16: Chris@16: inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2) Chris@16: { return id1 == id2; } Chris@16: Chris@16: //return the system tick in ns Chris@16: inline unsigned long get_system_tick_ns() Chris@16: { Chris@16: unsigned long curres; Chris@16: winapi::set_timer_resolution(10000, 0, &curres); Chris@16: //Windows API returns the value in hundreds of ns Chris@16: return (curres - 1ul)*100ul; Chris@16: } Chris@16: Chris@16: //return the system tick in us Chris@16: inline unsigned long get_system_tick_us() Chris@16: { Chris@16: unsigned long curres; Chris@16: winapi::set_timer_resolution(10000, 0, &curres); Chris@16: //Windows API returns the value in hundreds of ns Chris@16: return (curres - 1ul)/10ul + 1ul; Chris@16: } Chris@16: Chris@16: typedef unsigned __int64 OS_highres_count_t; Chris@16: Chris@16: inline unsigned long get_system_tick_in_highres_counts() Chris@16: { Chris@16: __int64 freq; Chris@16: unsigned long curres; Chris@16: winapi::set_timer_resolution(10000, 0, &curres); Chris@16: //Frequency in counts per second Chris@16: if(!winapi::query_performance_frequency(&freq)){ Chris@16: //Tick resolution in ms Chris@16: return (curres-1ul)/10000ul + 1ul; Chris@16: } Chris@16: else{ Chris@16: //In femtoseconds Chris@16: __int64 count_fs = (1000000000000000LL - 1LL)/freq + 1LL; Chris@16: __int64 tick_counts = (static_cast<__int64>(curres)*100000000LL - 1LL)/count_fs + 1LL; Chris@16: return static_cast(tick_counts); Chris@16: } Chris@16: } Chris@16: Chris@16: inline OS_highres_count_t get_current_system_highres_count() Chris@16: { Chris@16: __int64 count; Chris@16: if(!winapi::query_performance_counter(&count)){ Chris@16: count = winapi::get_tick_count(); Chris@16: } Chris@16: return count; Chris@16: } Chris@16: Chris@16: inline void zero_highres_count(OS_highres_count_t &count) Chris@16: { count = 0; } Chris@16: Chris@16: inline bool is_highres_count_zero(const OS_highres_count_t &count) Chris@16: { return count == 0; } Chris@16: Chris@16: template Chris@16: inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count) Chris@16: { Chris@16: ostream << count; Chris@16: return ostream; Chris@16: } Chris@16: Chris@16: inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r) Chris@16: { return l - r; } Chris@16: Chris@16: inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r) Chris@101: { return l < r; } Chris@16: Chris@16: inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r) Chris@16: { return l < static_cast(r); } Chris@16: Chris@16: inline void thread_sleep_tick() Chris@16: { winapi::sleep_tick(); } Chris@16: Chris@16: inline void thread_yield() Chris@16: { winapi::sched_yield(); } Chris@16: Chris@16: inline void thread_sleep(unsigned int ms) Chris@101: { winapi::sleep(ms); } Chris@16: Chris@16: //systemwide thread Chris@16: inline OS_systemwide_thread_id_t get_current_systemwide_thread_id() Chris@16: { Chris@16: return get_current_thread_id(); Chris@16: } Chris@16: Chris@16: inline void systemwide_thread_id_copy Chris@16: (const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to) Chris@16: { Chris@16: to = from; Chris@16: } Chris@16: Chris@16: inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2) Chris@16: { Chris@16: return equal_thread_id(id1, id2); Chris@16: } Chris@16: Chris@16: inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id() Chris@16: { Chris@16: return get_invalid_thread_id(); Chris@16: } Chris@16: Chris@16: inline long double get_current_process_creation_time() Chris@16: { Chris@16: winapi::interprocess_filetime CreationTime, ExitTime, KernelTime, UserTime; Chris@16: Chris@101: winapi::get_process_times Chris@16: ( winapi::get_current_process(), &CreationTime, &ExitTime, &KernelTime, &UserTime); Chris@16: Chris@16: typedef long double ldouble_t; Chris@16: const ldouble_t resolution = (100.0l/1000000000.0l); Chris@16: return CreationTime.dwHighDateTime*(ldouble_t(1u<<31u)*2.0l*resolution) + Chris@16: CreationTime.dwLowDateTime*resolution; Chris@16: } Chris@16: Chris@16: inline unsigned int get_num_cores() Chris@16: { Chris@16: winapi::system_info sysinfo; Chris@16: winapi::get_system_info( &sysinfo ); Chris@16: //in Windows dw is long which is equal in bits to int Chris@16: return static_cast(sysinfo.dwNumberOfProcessors); Chris@16: } Chris@16: Chris@101: #else //#if defined (BOOST_INTERPROCESS_WINDOWS) Chris@16: Chris@16: typedef pthread_t OS_thread_t; Chris@16: typedef pthread_t OS_thread_id_t; Chris@16: typedef pid_t OS_process_id_t; Chris@16: Chris@16: struct OS_systemwide_thread_id_t Chris@16: { Chris@16: OS_systemwide_thread_id_t() Chris@16: : pid(), tid() Chris@16: {} Chris@16: Chris@16: OS_systemwide_thread_id_t(pid_t p, pthread_t t) Chris@16: : pid(p), tid(t) Chris@16: {} Chris@16: Chris@16: OS_systemwide_thread_id_t(const OS_systemwide_thread_id_t &x) Chris@16: : pid(x.pid), tid(x.tid) Chris@16: {} Chris@16: Chris@16: OS_systemwide_thread_id_t(const volatile OS_systemwide_thread_id_t &x) Chris@16: : pid(x.pid), tid(x.tid) Chris@16: {} Chris@16: Chris@16: OS_systemwide_thread_id_t & operator=(const OS_systemwide_thread_id_t &x) Chris@16: { pid = x.pid; tid = x.tid; return *this; } Chris@16: Chris@16: OS_systemwide_thread_id_t & operator=(const volatile OS_systemwide_thread_id_t &x) Chris@16: { pid = x.pid; tid = x.tid; return *this; } Chris@16: Chris@16: void operator=(const OS_systemwide_thread_id_t &x) volatile Chris@16: { pid = x.pid; tid = x.tid; } Chris@16: Chris@16: pid_t pid; Chris@16: pthread_t tid; Chris@16: }; Chris@16: Chris@16: inline void systemwide_thread_id_copy Chris@16: (const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to) Chris@16: { Chris@16: to.pid = from.pid; Chris@16: to.tid = from.tid; Chris@16: } Chris@16: Chris@16: //process Chris@16: inline OS_process_id_t get_current_process_id() Chris@16: { return ::getpid(); } Chris@16: Chris@16: inline OS_process_id_t get_invalid_process_id() Chris@16: { return pid_t(0); } Chris@16: Chris@16: //thread Chris@16: inline OS_thread_id_t get_current_thread_id() Chris@16: { return ::pthread_self(); } Chris@16: Chris@16: inline OS_thread_id_t get_invalid_thread_id() Chris@16: { Chris@16: static pthread_t invalid_id; Chris@16: return invalid_id; Chris@16: } Chris@16: Chris@16: inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2) Chris@16: { return 0 != pthread_equal(id1, id2); } Chris@16: Chris@16: inline void thread_yield() Chris@16: { ::sched_yield(); } Chris@16: Chris@16: #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME Chris@16: typedef struct timespec OS_highres_count_t; Chris@16: #else Chris@16: typedef unsigned long long OS_highres_count_t; Chris@16: #endif Chris@16: Chris@16: inline unsigned long get_system_tick_ns() Chris@16: { Chris@16: #ifdef _SC_CLK_TCK Chris@101: long ticks_per_second =::sysconf(_SC_CLK_TCK); // ticks per sec Chris@101: if(ticks_per_second <= 0){ //Try a typical value on error Chris@101: ticks_per_second = 100; Chris@16: } Chris@101: return 999999999ul/static_cast(ticks_per_second)+1ul; Chris@16: #else Chris@16: #error "Can't obtain system tick value for your system, please provide a patch" Chris@16: #endif Chris@16: } Chris@16: Chris@16: inline unsigned long get_system_tick_in_highres_counts() Chris@16: { Chris@16: #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME Chris@16: return get_system_tick_ns(); Chris@16: #else Chris@16: mach_timebase_info_data_t info; Chris@16: mach_timebase_info(&info); Chris@16: //ns Chris@16: return static_cast Chris@101: ( Chris@101: static_cast(get_system_tick_ns()) Chris@16: / (static_cast(info.numer) / info.denom) Chris@16: ); Chris@16: #endif Chris@16: } Chris@16: Chris@16: //return system ticks in us Chris@16: inline unsigned long get_system_tick_us() Chris@16: { Chris@16: return (get_system_tick_ns()-1)/1000ul + 1ul; Chris@16: } Chris@16: Chris@16: inline OS_highres_count_t get_current_system_highres_count() Chris@16: { Chris@16: #if defined(BOOST_INTERPROCESS_CLOCK_MONOTONIC) Chris@16: struct timespec count; Chris@16: ::clock_gettime(BOOST_INTERPROCESS_CLOCK_MONOTONIC, &count); Chris@16: return count; Chris@16: #elif defined(BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME) Chris@16: return ::mach_absolute_time(); Chris@16: #endif Chris@16: } Chris@16: Chris@16: #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME Chris@16: Chris@16: inline void zero_highres_count(OS_highres_count_t &count) Chris@16: { count.tv_sec = 0; count.tv_nsec = 0; } Chris@16: Chris@16: inline bool is_highres_count_zero(const OS_highres_count_t &count) Chris@16: { return count.tv_sec == 0 && count.tv_nsec == 0; } Chris@16: Chris@16: template Chris@16: inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count) Chris@16: { Chris@16: ostream << count.tv_sec << "s:" << count.tv_nsec << "ns"; Chris@16: return ostream; Chris@16: } Chris@16: Chris@16: inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r) Chris@16: { Chris@16: OS_highres_count_t res; Chris@16: Chris@16: if (l.tv_nsec < r.tv_nsec){ Chris@101: res.tv_nsec = 1000000000 + l.tv_nsec - r.tv_nsec; Chris@16: res.tv_sec = l.tv_sec - 1 - r.tv_sec; Chris@16: } Chris@16: else{ Chris@101: res.tv_nsec = l.tv_nsec - r.tv_nsec; Chris@16: res.tv_sec = l.tv_sec - r.tv_sec; Chris@16: } Chris@16: Chris@16: return res; Chris@16: } Chris@16: Chris@16: inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r) Chris@16: { return l.tv_sec < r.tv_sec || (l.tv_sec == r.tv_sec && l.tv_nsec < r.tv_nsec); } Chris@16: Chris@16: inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r) Chris@101: { return !l.tv_sec && (static_cast(l.tv_nsec) < r); } Chris@16: Chris@16: #else Chris@16: Chris@16: inline void zero_highres_count(OS_highres_count_t &count) Chris@16: { count = 0; } Chris@16: Chris@16: inline bool is_highres_count_zero(const OS_highres_count_t &count) Chris@16: { return count == 0; } Chris@16: Chris@16: template Chris@16: inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count) Chris@16: { Chris@16: ostream << count ; Chris@16: return ostream; Chris@16: } Chris@16: Chris@16: inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r) Chris@16: { return l - r; } Chris@16: Chris@16: inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r) Chris@16: { return l < r; } Chris@16: Chris@16: inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r) Chris@16: { return l < static_cast(r); } Chris@16: Chris@16: #endif Chris@16: Chris@16: inline void thread_sleep_tick() Chris@16: { Chris@16: struct timespec rqt; Chris@16: //Sleep for the half of the tick time Chris@16: rqt.tv_sec = 0; Chris@16: rqt.tv_nsec = get_system_tick_ns()/2; Chris@16: ::nanosleep(&rqt, 0); Chris@16: } Chris@16: Chris@16: inline void thread_sleep(unsigned int ms) Chris@16: { Chris@16: struct timespec rqt; Chris@16: rqt.tv_sec = ms/1000u; Chris@16: rqt.tv_nsec = (ms%1000u)*1000000u; Chris@16: ::nanosleep(&rqt, 0); Chris@16: } Chris@16: Chris@16: //systemwide thread Chris@16: inline OS_systemwide_thread_id_t get_current_systemwide_thread_id() Chris@16: { Chris@16: return OS_systemwide_thread_id_t(::getpid(), ::pthread_self()); Chris@16: } Chris@16: Chris@16: inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2) Chris@16: { Chris@16: return (0 != pthread_equal(id1.tid, id2.tid)) && (id1.pid == id2.pid); Chris@16: } Chris@16: Chris@16: inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id() Chris@16: { Chris@16: return OS_systemwide_thread_id_t(get_invalid_process_id(), get_invalid_thread_id()); Chris@16: } Chris@16: Chris@16: inline long double get_current_process_creation_time() Chris@16: { return 0.0L; } Chris@16: Chris@16: inline unsigned int get_num_cores() Chris@16: { Chris@16: #ifdef _SC_NPROCESSORS_ONLN Chris@16: long cores = ::sysconf(_SC_NPROCESSORS_ONLN); Chris@16: // sysconf returns -1 if the name is invalid, the option does not exist or Chris@16: // does not have a definite limit. Chris@16: // if sysconf returns some other negative number, we have no idea Chris@16: // what is going on. Default to something safe. Chris@16: if(cores <= 0){ Chris@16: return 1; Chris@16: } Chris@16: //Check for overflow (unlikely) Chris@16: else if(static_cast(cores) >= Chris@16: static_cast(static_cast(-1))){ Chris@16: return static_cast(-1); Chris@16: } Chris@16: else{ Chris@16: return static_cast(cores); Chris@16: } Chris@16: #elif defined(BOOST_INTERPROCESS_BSD_DERIVATIVE) && defined(HW_NCPU) Chris@16: int request[2] = { CTL_HW, HW_NCPU }; Chris@16: int num_cores; Chris@16: std::size_t result_len = sizeof(num_cores); Chris@16: if ( (::sysctl (request, 2, &num_cores, &result_len, 0, 0) < 0) || (num_cores <= 0) ){ Chris@16: //Return a safe value Chris@16: return 1; Chris@16: } Chris@16: else{ Chris@16: return static_cast(num_cores); Chris@16: } Chris@16: #endif Chris@16: } Chris@16: Chris@16: inline int thread_create(OS_thread_t * thread, void *(*start_routine)(void*), void* arg) Chris@16: { return pthread_create(thread, 0, start_routine, arg); } Chris@16: Chris@16: inline void thread_join(OS_thread_t thread) Chris@16: { (void)pthread_join(thread, 0); } Chris@16: Chris@101: #endif //#if defined (BOOST_INTERPROCESS_WINDOWS) Chris@16: Chris@16: typedef char pid_str_t[sizeof(OS_process_id_t)*3+1]; Chris@16: Chris@16: inline void get_pid_str(pid_str_t &pid_str, OS_process_id_t pid) Chris@16: { Chris@16: bufferstream bstream(pid_str, sizeof(pid_str)); Chris@16: bstream << pid << std::ends; Chris@16: } Chris@16: Chris@16: inline void get_pid_str(pid_str_t &pid_str) Chris@16: { get_pid_str(pid_str, get_current_process_id()); } Chris@16: Chris@16: #if defined(BOOST_INTERPROCESS_WINDOWS) Chris@16: Chris@16: inline int thread_create( OS_thread_t * thread, unsigned (__stdcall * start_routine) (void*), void* arg ) Chris@16: { Chris@16: void* h = (void*)_beginthreadex( 0, 0, start_routine, arg, 0, 0 ); Chris@16: Chris@16: if( h != 0 ){ Chris@16: *thread = h; Chris@16: return 0; Chris@16: } Chris@16: else{ Chris@16: return 1; Chris@16: } Chris@16: } Chris@16: Chris@16: inline void thread_join( OS_thread_t thread) Chris@16: { Chris@16: winapi::wait_for_single_object( thread, winapi::infinite_time ); Chris@16: winapi::close_handle( thread ); Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: class abstract_thread Chris@16: { Chris@16: public: Chris@16: virtual ~abstract_thread() {} Chris@16: virtual void run() = 0; Chris@16: }; Chris@16: Chris@101: template Chris@101: class os_thread_func_ptr_deleter Chris@101: { Chris@101: public: Chris@101: explicit os_thread_func_ptr_deleter(T* p) Chris@101: : m_p(p) Chris@101: {} Chris@101: Chris@101: T *release() Chris@101: { T *p = m_p; m_p = 0; return p; } Chris@101: Chris@101: T *get() const Chris@101: { return m_p; } Chris@101: Chris@101: T *operator ->() const Chris@101: { return m_p; } Chris@101: Chris@101: ~os_thread_func_ptr_deleter() Chris@101: { delete m_p; } Chris@101: Chris@101: private: Chris@101: T *m_p; Chris@101: }; Chris@101: Chris@16: #if defined(BOOST_INTERPROCESS_WINDOWS) Chris@16: Chris@16: inline unsigned __stdcall launch_thread_routine( void * pv ) Chris@16: { Chris@101: os_thread_func_ptr_deleter pt( static_cast( pv ) ); Chris@16: pt->run(); Chris@16: return 0; Chris@16: } Chris@16: Chris@16: #else Chris@16: Chris@16: extern "C" void * launch_thread_routine( void * pv ); Chris@16: Chris@16: inline void * launch_thread_routine( void * pv ) Chris@16: { Chris@101: os_thread_func_ptr_deleter pt( static_cast( pv ) ); Chris@16: pt->run(); Chris@16: return 0; Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: template Chris@16: class launch_thread_impl Chris@16: : public abstract_thread Chris@16: { Chris@16: public: Chris@16: explicit launch_thread_impl( F f ) Chris@16: : f_( f ) Chris@16: {} Chris@16: Chris@16: void run() Chris@16: { f_(); } Chris@16: Chris@16: private: Chris@16: F f_; Chris@16: }; Chris@16: Chris@16: template Chris@16: inline int thread_launch( OS_thread_t & pt, F f ) Chris@16: { Chris@101: os_thread_func_ptr_deleter p( new launch_thread_impl( f ) ); Chris@16: Chris@16: int r = thread_create(&pt, launch_thread_routine, p.get()); Chris@16: if( r == 0 ){ Chris@16: p.release(); Chris@16: } Chris@16: Chris@16: return r; Chris@16: } Chris@16: Chris@16: } //namespace ipcdetail{ Chris@16: } //namespace interprocess { Chris@16: } //namespace boost { Chris@16: Chris@16: #include Chris@16: Chris@16: #endif //BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP