os_thread_functions.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/interprocess for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. //Thread launching functions are adapted from boost/detail/lightweight_thread.hpp
  11. //
  12. // boost/detail/lightweight_thread.hpp
  13. //
  14. // Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
  15. // Copyright (c) 2008 Peter Dimov
  16. //
  17. // Distributed under the Boost Software License, Version 1.0.
  18. // See accompanying file LICENSE_1_0.txt or copy at
  19. // http://www.boost.org/LICENSE_1_0.txt
  20. #ifndef BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
  21. #define BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
  22. #ifndef BOOST_CONFIG_HPP
  23. # include <boost/config.hpp>
  24. #endif
  25. #
  26. #if defined(BOOST_HAS_PRAGMA_ONCE)
  27. # pragma once
  28. #endif
  29. #include <boost/interprocess/detail/config_begin.hpp>
  30. #include <boost/interprocess/detail/workaround.hpp>
  31. #include <boost/interprocess/streams/bufferstream.hpp>
  32. #include <cstddef>
  33. #include <cassert>
  34. #if defined(BOOST_INTERPROCESS_WINDOWS)
  35. # include <boost/interprocess/detail/win32_api.hpp>
  36. # include <boost/winapi/thread.hpp>
  37. #else
  38. # include <pthread.h>
  39. # include <unistd.h>
  40. # include <sched.h>
  41. # include <time.h>
  42. # include <errno.h>
  43. # ifdef BOOST_INTERPROCESS_BSD_DERIVATIVE
  44. //Some *BSD systems (OpenBSD & NetBSD) need sys/param.h before sys/sysctl.h, whereas
  45. //others (FreeBSD & Darwin) need sys/types.h
  46. # include <sys/types.h>
  47. # include <sys/param.h>
  48. # include <sys/sysctl.h>
  49. # endif
  50. #if defined(__VXWORKS__)
  51. #include <vxCpuLib.h>
  52. #endif
  53. //According to the article "C/C++ tip: How to measure elapsed real time for benchmarking"
  54. //Check MacOs first as macOS 10.12 SDK defines both CLOCK_MONOTONIC and
  55. //CLOCK_MONOTONIC_RAW and no clock_gettime.
  56. # if (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
  57. # include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t
  58. # define BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
  59. # elif defined(CLOCK_MONOTONIC_PRECISE) //BSD
  60. # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_PRECISE
  61. # elif defined(CLOCK_MONOTONIC_RAW) //Linux
  62. # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_RAW
  63. # elif defined(CLOCK_HIGHRES) //Solaris
  64. # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_HIGHRES
  65. # elif defined(CLOCK_MONOTONIC) //POSIX (AIX, BSD, Linux, Solaris)
  66. # define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC
  67. # else
  68. # error "No high resolution steady clock in your system, please provide a patch"
  69. # endif
  70. #endif
  71. namespace boost {
  72. namespace interprocess {
  73. namespace ipcdetail{
  74. #if defined (BOOST_INTERPROCESS_WINDOWS)
  75. typedef unsigned long OS_process_id_t;
  76. typedef unsigned long OS_thread_id_t;
  77. struct OS_thread_t
  78. {
  79. OS_thread_t()
  80. : m_handle()
  81. {}
  82. void* handle() const
  83. { return m_handle; }
  84. void* m_handle;
  85. };
  86. typedef OS_thread_id_t OS_systemwide_thread_id_t;
  87. //process
  88. inline OS_process_id_t get_current_process_id()
  89. { return winapi::get_current_process_id(); }
  90. inline OS_process_id_t get_invalid_process_id()
  91. { return OS_process_id_t(0); }
  92. //thread
  93. inline OS_thread_id_t get_current_thread_id()
  94. { return winapi::get_current_thread_id(); }
  95. inline OS_thread_id_t get_invalid_thread_id()
  96. { return OS_thread_id_t(0xffffffff); }
  97. inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
  98. { return id1 == id2; }
  99. //return the system tick in ns
  100. inline unsigned long get_system_tick_ns()
  101. {
  102. unsigned long curres, ignore1, ignore2;
  103. winapi::query_timer_resolution(&ignore1, &ignore2, &curres);
  104. //Windows API returns the value in hundreds of ns
  105. return (curres - 1ul)*100ul;
  106. }
  107. //return the system tick in us
  108. inline unsigned long get_system_tick_us()
  109. {
  110. unsigned long curres, ignore1, ignore2;
  111. winapi::query_timer_resolution(&ignore1, &ignore2, &curres);
  112. //Windows API returns the value in hundreds of ns
  113. return (curres - 1ul)/10ul + 1ul;
  114. }
  115. typedef unsigned __int64 OS_highres_count_t;
  116. inline unsigned long get_system_tick_in_highres_counts()
  117. {
  118. __int64 freq;
  119. unsigned long curres, ignore1, ignore2;
  120. winapi::query_timer_resolution(&ignore1, &ignore2, &curres);
  121. //Frequency in counts per second
  122. if(!winapi::query_performance_frequency(&freq)){
  123. //Tick resolution in ms
  124. return (curres-1ul)/10000ul + 1ul;
  125. }
  126. else{
  127. //In femtoseconds
  128. __int64 count_fs = (1000000000000000LL - 1LL)/freq + 1LL;
  129. __int64 tick_counts = (static_cast<__int64>(curres)*100000000LL - 1LL)/count_fs + 1LL;
  130. return static_cast<unsigned long>(tick_counts);
  131. }
  132. }
  133. inline OS_highres_count_t get_current_system_highres_count()
  134. {
  135. __int64 count;
  136. if(!winapi::query_performance_counter(&count)){
  137. count = winapi::get_tick_count();
  138. }
  139. return (OS_highres_count_t)count;
  140. }
  141. inline unsigned get_current_system_highres_rand()
  142. {
  143. unsigned __int64 count = (unsigned __int64) get_current_system_highres_count();
  144. return static_cast<unsigned>(count + (count >> 32u));
  145. }
  146. inline void zero_highres_count(OS_highres_count_t &count)
  147. { count = 0; }
  148. inline bool is_highres_count_zero(const OS_highres_count_t &count)
  149. { return count == 0; }
  150. template <class Ostream>
  151. inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
  152. {
  153. ostream << count;
  154. return ostream;
  155. }
  156. inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
  157. { return l - r; }
  158. inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
  159. { return l < r; }
  160. inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r)
  161. { return l < static_cast<OS_highres_count_t>(r); }
  162. inline void thread_sleep_tick()
  163. { winapi::sleep_tick(); }
  164. inline void thread_yield()
  165. { winapi::sched_yield(); }
  166. inline void thread_sleep_ms(unsigned int ms)
  167. { winapi::sleep(ms); }
  168. //systemwide thread
  169. inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
  170. {
  171. return get_current_thread_id();
  172. }
  173. inline void systemwide_thread_id_copy
  174. (const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
  175. {
  176. to = from;
  177. }
  178. inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
  179. {
  180. return equal_thread_id(id1, id2);
  181. }
  182. inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
  183. {
  184. return get_invalid_thread_id();
  185. }
  186. inline unsigned long long get_current_process_creation_time()
  187. {
  188. winapi::interprocess_filetime CreationTime, ExitTime, KernelTime, UserTime;
  189. winapi::get_process_times
  190. ( winapi::get_current_process(), &CreationTime, &ExitTime, &KernelTime, &UserTime);
  191. unsigned long long microsecs = CreationTime.dwHighDateTime;
  192. microsecs <<= 32u;
  193. microsecs |= CreationTime.dwLowDateTime;
  194. microsecs /= 10u;
  195. return microsecs;
  196. }
  197. inline unsigned int get_num_cores()
  198. {
  199. winapi::interprocess_system_info sysinfo;
  200. winapi::get_system_info( &sysinfo );
  201. //in Windows dw is long which is equal in bits to int
  202. return static_cast<unsigned>(sysinfo.dwNumberOfProcessors);
  203. }
  204. #else //#if defined (BOOST_INTERPROCESS_WINDOWS)
  205. typedef pthread_t OS_thread_t;
  206. typedef pthread_t OS_thread_id_t;
  207. typedef pid_t OS_process_id_t;
  208. struct OS_systemwide_thread_id_t
  209. {
  210. OS_systemwide_thread_id_t()
  211. : pid(), tid()
  212. {}
  213. OS_systemwide_thread_id_t(pid_t p, pthread_t t)
  214. : pid(p), tid(t)
  215. {}
  216. OS_systemwide_thread_id_t(const OS_systemwide_thread_id_t &x)
  217. : pid(x.pid), tid(x.tid)
  218. {}
  219. OS_systemwide_thread_id_t(const volatile OS_systemwide_thread_id_t &x)
  220. : pid(x.pid), tid(x.tid)
  221. {}
  222. OS_systemwide_thread_id_t & operator=(const OS_systemwide_thread_id_t &x)
  223. { pid = x.pid; tid = x.tid; return *this; }
  224. OS_systemwide_thread_id_t & operator=(const volatile OS_systemwide_thread_id_t &x)
  225. { pid = x.pid; tid = x.tid; return *this; }
  226. void operator=(const OS_systemwide_thread_id_t &x) volatile
  227. { pid = x.pid; tid = x.tid; }
  228. pid_t pid;
  229. pthread_t tid;
  230. };
  231. inline void systemwide_thread_id_copy
  232. (const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
  233. {
  234. to.pid = from.pid;
  235. to.tid = from.tid;
  236. }
  237. //process
  238. inline OS_process_id_t get_current_process_id()
  239. { return ::getpid(); }
  240. inline OS_process_id_t get_invalid_process_id()
  241. { return pid_t(0); }
  242. //thread
  243. inline OS_thread_id_t get_current_thread_id()
  244. { return ::pthread_self(); }
  245. inline OS_thread_id_t get_invalid_thread_id()
  246. {
  247. static pthread_t invalid_id;
  248. return invalid_id;
  249. }
  250. inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
  251. { return 0 != pthread_equal(id1, id2); }
  252. inline void thread_yield()
  253. { ::sched_yield(); }
  254. #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
  255. typedef struct timespec OS_highres_count_t;
  256. #else
  257. typedef unsigned long long OS_highres_count_t;
  258. #endif
  259. inline unsigned long get_system_tick_ns()
  260. {
  261. #ifdef _SC_CLK_TCK
  262. long ticks_per_second =::sysconf(_SC_CLK_TCK); // ticks per sec
  263. if(ticks_per_second <= 0){ //Try a typical value on error
  264. ticks_per_second = 100;
  265. }
  266. return 999999999ul/static_cast<unsigned long>(ticks_per_second)+1ul;
  267. #else
  268. #error "Can't obtain system tick value for your system, please provide a patch"
  269. #endif
  270. }
  271. inline unsigned long get_system_tick_in_highres_counts()
  272. {
  273. #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
  274. return get_system_tick_ns();
  275. #else
  276. mach_timebase_info_data_t info;
  277. mach_timebase_info(&info);
  278. //ns
  279. return static_cast<unsigned long>
  280. (
  281. static_cast<double>(get_system_tick_ns())
  282. / (static_cast<double>(info.numer) / info.denom)
  283. );
  284. #endif
  285. }
  286. //return system ticks in us
  287. inline unsigned long get_system_tick_us()
  288. {
  289. return (get_system_tick_ns()-1)/1000ul + 1ul;
  290. }
  291. inline OS_highres_count_t get_current_system_highres_count()
  292. {
  293. #if defined(BOOST_INTERPROCESS_CLOCK_MONOTONIC)
  294. struct timespec count;
  295. ::clock_gettime(BOOST_INTERPROCESS_CLOCK_MONOTONIC, &count);
  296. return count;
  297. #elif defined(BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME)
  298. return ::mach_absolute_time();
  299. #endif
  300. }
  301. inline unsigned get_current_system_highres_rand()
  302. {
  303. OS_highres_count_t count = get_current_system_highres_count();
  304. #if defined(BOOST_INTERPROCESS_CLOCK_MONOTONIC)
  305. return static_cast<unsigned>(count.tv_sec + count.tv_nsec);
  306. #elif defined(BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME)
  307. return static_cast<unsigned>(count);
  308. #endif
  309. }
  310. #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
  311. inline void zero_highres_count(OS_highres_count_t &count)
  312. { count.tv_sec = 0; count.tv_nsec = 0; }
  313. inline bool is_highres_count_zero(const OS_highres_count_t &count)
  314. { return count.tv_sec == 0 && count.tv_nsec == 0; }
  315. template <class Ostream>
  316. inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
  317. {
  318. ostream << count.tv_sec << "s:" << count.tv_nsec << "ns";
  319. return ostream;
  320. }
  321. inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
  322. {
  323. OS_highres_count_t res;
  324. if (l.tv_nsec < r.tv_nsec){
  325. res.tv_nsec = 1000000000 + l.tv_nsec - r.tv_nsec;
  326. res.tv_sec = l.tv_sec - 1 - r.tv_sec;
  327. }
  328. else{
  329. res.tv_nsec = l.tv_nsec - r.tv_nsec;
  330. res.tv_sec = l.tv_sec - r.tv_sec;
  331. }
  332. return res;
  333. }
  334. inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
  335. { return l.tv_sec < r.tv_sec || (l.tv_sec == r.tv_sec && l.tv_nsec < r.tv_nsec); }
  336. inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r)
  337. { return !l.tv_sec && (static_cast<unsigned long>(l.tv_nsec) < r); }
  338. #else
  339. inline void zero_highres_count(OS_highres_count_t &count)
  340. { count = 0; }
  341. inline bool is_highres_count_zero(const OS_highres_count_t &count)
  342. { return count == 0; }
  343. template <class Ostream>
  344. inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
  345. {
  346. ostream << count ;
  347. return ostream;
  348. }
  349. inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
  350. { return l - r; }
  351. inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
  352. { return l < r; }
  353. inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r)
  354. { return l < static_cast<OS_highres_count_t>(r); }
  355. #endif
  356. inline void thread_sleep_tick()
  357. {
  358. struct timespec rqt;
  359. //Sleep for the half of the tick time
  360. rqt.tv_sec = 0;
  361. rqt.tv_nsec = (long)get_system_tick_ns()/2;
  362. struct timespec rmn;
  363. while (0 != BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::nanosleep(&rqt, &rmn)) && errno == EINTR) {
  364. rqt.tv_sec = rmn.tv_sec;
  365. rqt.tv_nsec = rmn.tv_nsec;
  366. }
  367. }
  368. inline void thread_sleep_ms(unsigned int ms)
  369. {
  370. struct timespec rqt;
  371. rqt.tv_sec = static_cast<time_t>(ms/1000u);
  372. rqt.tv_nsec = static_cast<long int>((ms%1000u)*1000000u);
  373. struct timespec rmn;
  374. while (0 != BOOST_INTERPROCESS_EINTR_RETRY(int, -1, ::nanosleep(&rqt, &rmn)) && errno == EINTR) {
  375. rqt.tv_sec = rmn.tv_sec;
  376. rqt.tv_nsec = rmn.tv_nsec;
  377. }
  378. }
  379. //systemwide thread
  380. inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
  381. {
  382. return OS_systemwide_thread_id_t(::getpid(), ::pthread_self());
  383. }
  384. inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
  385. {
  386. return (0 != pthread_equal(id1.tid, id2.tid)) && (id1.pid == id2.pid);
  387. }
  388. inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
  389. {
  390. return OS_systemwide_thread_id_t(get_invalid_process_id(), get_invalid_thread_id());
  391. }
  392. inline unsigned long long get_current_process_creation_time()
  393. { return 0u; }
  394. inline unsigned int get_num_cores()
  395. {
  396. #ifdef _SC_NPROCESSORS_ONLN
  397. long cores = ::sysconf(_SC_NPROCESSORS_ONLN);
  398. // sysconf returns -1 if the name is invalid, the option does not exist or
  399. // does not have a definite limit.
  400. // if sysconf returns some other negative number, we have no idea
  401. // what is going on. Default to something safe.
  402. if(cores <= 0){
  403. return 1;
  404. }
  405. //Check for overflow (unlikely)
  406. else if(static_cast<unsigned long>(cores) >=
  407. static_cast<unsigned long>(static_cast<unsigned int>(-1))){
  408. return static_cast<unsigned int>(-1);
  409. }
  410. else{
  411. return static_cast<unsigned int>(cores);
  412. }
  413. #elif defined(BOOST_INTERPROCESS_BSD_DERIVATIVE) && defined(HW_NCPU)
  414. int request[2] = { CTL_HW, HW_NCPU };
  415. int num_cores;
  416. std::size_t result_len = sizeof(num_cores);
  417. if ( (::sysctl (request, 2, &num_cores, &result_len, 0, 0) < 0) || (num_cores <= 0) ){
  418. //Return a safe value
  419. return 1;
  420. }
  421. else{
  422. return static_cast<unsigned int>(num_cores);
  423. }
  424. #elif defined(__VXWORKS__)
  425. cpuset_t set = ::vxCpuEnabledGet();
  426. #ifdef __DCC__
  427. int i;
  428. for( i = 0; set; ++i)
  429. {
  430. set &= set -1;
  431. }
  432. return(i);
  433. #else
  434. return (__builtin_popcount(set) );
  435. #endif
  436. #endif
  437. }
  438. inline int thread_create(OS_thread_t * thread, void *(*start_routine)(void*), void* arg)
  439. { return pthread_create(thread, 0, start_routine, arg); }
  440. inline void thread_join(OS_thread_t thread)
  441. {
  442. int ret = pthread_join(thread, 0);
  443. (void)ret;
  444. assert(0 == ret);
  445. }
  446. #endif //#if defined (BOOST_INTERPROCESS_WINDOWS)
  447. typedef char pid_str_t[sizeof(OS_process_id_t)*3+1];
  448. inline void get_pid_str(pid_str_t &pid_str, OS_process_id_t pid)
  449. {
  450. bufferstream bstream(pid_str, sizeof(pid_str));
  451. bstream << pid << std::ends;
  452. }
  453. inline void get_pid_str(pid_str_t &pid_str)
  454. { get_pid_str(pid_str, get_current_process_id()); }
  455. #if defined(BOOST_INTERPROCESS_WINDOWS)
  456. inline int thread_create( OS_thread_t * thread, boost::ipwinapiext::LPTHREAD_START_ROUTINE_ start_routine, void* arg )
  457. {
  458. void* h = boost::ipwinapiext::CreateThread(0, 0, start_routine, arg, 0, 0);
  459. if( h != 0 ){
  460. thread->m_handle = h;
  461. return 0;
  462. }
  463. else{
  464. return 1;
  465. }
  466. }
  467. inline void thread_join( OS_thread_t thread)
  468. {
  469. {
  470. unsigned long ret = winapi::wait_for_single_object( thread.handle(), winapi::infinite_time );
  471. assert(0 == ret);
  472. (void)ret;
  473. }
  474. {
  475. bool ret = winapi::close_handle(thread.handle());
  476. assert(true == ret);
  477. (void)ret;
  478. }
  479. }
  480. #endif
  481. class abstract_thread
  482. {
  483. public:
  484. virtual ~abstract_thread() {}
  485. virtual void run() = 0;
  486. };
  487. template<class T>
  488. class os_thread_func_ptr_deleter
  489. {
  490. public:
  491. explicit os_thread_func_ptr_deleter(T* p)
  492. : m_p(p)
  493. {}
  494. T *release()
  495. { T *p = m_p; m_p = 0; return p; }
  496. T *get() const
  497. { return m_p; }
  498. T *operator ->() const
  499. { return m_p; }
  500. ~os_thread_func_ptr_deleter()
  501. { delete m_p; }
  502. private:
  503. T *m_p;
  504. };
  505. #if defined(BOOST_INTERPROCESS_WINDOWS)
  506. inline boost::winapi::DWORD_ __stdcall launch_thread_routine(boost::winapi::LPVOID_ pv)
  507. {
  508. os_thread_func_ptr_deleter<abstract_thread> pt( static_cast<abstract_thread *>( pv ) );
  509. pt->run();
  510. return 0;
  511. }
  512. #else
  513. extern "C" void * launch_thread_routine( void * pv );
  514. inline void * launch_thread_routine( void * pv )
  515. {
  516. os_thread_func_ptr_deleter<abstract_thread> pt( static_cast<abstract_thread *>( pv ) );
  517. pt->run();
  518. return 0;
  519. }
  520. #endif
  521. template<class F>
  522. class launch_thread_impl
  523. : public abstract_thread
  524. {
  525. public:
  526. explicit launch_thread_impl( F f )
  527. : f_( f )
  528. {}
  529. virtual void run() BOOST_OVERRIDE
  530. { f_(); }
  531. private:
  532. F f_;
  533. };
  534. template<class F>
  535. inline int thread_launch( OS_thread_t & pt, F f )
  536. {
  537. os_thread_func_ptr_deleter<abstract_thread> p( new launch_thread_impl<F>( f ) );
  538. int r = thread_create(&pt, launch_thread_routine, p.get());
  539. if( r == 0 ){
  540. p.release();
  541. }
  542. return r;
  543. }
  544. } //namespace ipcdetail{
  545. } //namespace interprocess {
  546. } //namespace boost {
  547. #include <boost/interprocess/detail/config_end.hpp>
  548. #endif //BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP