1 #ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED
2 #define BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED
3 
4 // MS compatible compilers support #pragma once
5 
6 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
7 # pragma once
8 #endif
9 
10 //  boost/detail/lightweight_thread.hpp
11 //
12 //  Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
13 //  Copyright (c) 2008, 2018 Peter Dimov
14 //
15 //  Distributed under the Boost Software License, Version 1.0.
16 //  See accompanying file LICENSE_1_0.txt or copy at
17 //  http://www.boost.org/LICENSE_1_0.txt
18 //
19 //
20 //  typedef /*...*/ lw_thread_t; // as pthread_t
21 //  template<class F> int lw_thread_create( lw_thread_t & th, F f );
22 //  void lw_thread_join( lw_thread_t th );
23 
24 
25 #include <boost/config.hpp>
26 #include <memory>
27 #include <cerrno>
28 
29 #if defined( BOOST_HAS_PTHREADS )
30 
31 #include <pthread.h>
32 
33 namespace boost
34 {
35 namespace detail
36 {
37 
38 typedef ::pthread_t lw_thread_t;
39 
lw_thread_create_(lw_thread_t * thread,const pthread_attr_t * attr,void * (* start_routine)(void *),void * arg)40 inline int lw_thread_create_( lw_thread_t* thread, const pthread_attr_t* attr, void* (*start_routine)( void* ), void* arg )
41 {
42     return ::pthread_create( thread, attr, start_routine, arg );
43 }
44 
lw_thread_join(lw_thread_t th)45 inline void lw_thread_join( lw_thread_t th )
46 {
47     ::pthread_join( th, 0 );
48 }
49 
50 } // namespace detail
51 } // namespace boost
52 
53 #else // defined( BOOST_HAS_PTHREADS )
54 
55 #include <windows.h>
56 #include <process.h>
57 
58 namespace boost
59 {
60 namespace detail
61 {
62 
63 typedef HANDLE lw_thread_t;
64 
lw_thread_create_(lw_thread_t * thread,void const *,unsigned (__stdcall * start_routine)(void *),void * arg)65 inline int lw_thread_create_( lw_thread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg )
66 {
67     HANDLE h = (HANDLE)_beginthreadex( 0, 0, start_routine, arg, 0, 0 );
68 
69     if( h != 0 )
70     {
71         *thread = h;
72         return 0;
73     }
74     else
75     {
76         return EAGAIN;
77     }
78 }
79 
lw_thread_join(lw_thread_t thread)80 inline void lw_thread_join( lw_thread_t thread )
81 {
82     ::WaitForSingleObject( thread, INFINITE );
83     ::CloseHandle( thread );
84 }
85 
86 } // namespace detail
87 } // namespace boost
88 
89 #endif // defined( BOOST_HAS_PTHREADS )
90 
91 
92 namespace boost
93 {
94 namespace detail
95 {
96 
97 class lw_abstract_thread
98 {
99 public:
100 
~lw_abstract_thread()101     virtual ~lw_abstract_thread() {}
102     virtual void run() = 0;
103 };
104 
105 #if defined( BOOST_HAS_PTHREADS )
106 
lw_thread_routine(void * pv)107 extern "C" void * lw_thread_routine( void * pv )
108 {
109 #if defined(BOOST_NO_CXX11_SMART_PTR)
110 
111     std::auto_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) );
112 
113 #else
114 
115     std::unique_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) );
116 
117 #endif
118 
119     pt->run();
120 
121     return 0;
122 }
123 
124 #else
125 
lw_thread_routine(void * pv)126 unsigned __stdcall lw_thread_routine( void * pv )
127 {
128 #if defined(BOOST_NO_CXX11_SMART_PTR)
129 
130     std::auto_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) );
131 
132 #else
133 
134     std::unique_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) );
135 
136 #endif
137 
138     pt->run();
139 
140     return 0;
141 }
142 
143 #endif
144 
145 template<class F> class lw_thread_impl: public lw_abstract_thread
146 {
147 public:
148 
lw_thread_impl(F f)149     explicit lw_thread_impl( F f ): f_( f )
150     {
151     }
152 
run()153     void run()
154     {
155         f_();
156     }
157 
158 private:
159 
160     F f_;
161 };
162 
lw_thread_create(lw_thread_t & th,F f)163 template<class F> int lw_thread_create( lw_thread_t & th, F f )
164 {
165 #if defined(BOOST_NO_CXX11_SMART_PTR)
166 
167     std::auto_ptr<lw_abstract_thread> p( new lw_thread_impl<F>( f ) );
168 
169 #else
170 
171     std::unique_ptr<lw_abstract_thread> p( new lw_thread_impl<F>( f ) );
172 
173 #endif
174 
175     int r = lw_thread_create_( &th, 0, lw_thread_routine, p.get() );
176 
177     if( r == 0 )
178     {
179         p.release();
180     }
181 
182     return r;
183 }
184 
185 } // namespace detail
186 } // namespace boost
187 
188 #endif // #ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED
189