blob: c2930d591ae4885483769417a0c718e89dc1b54b [file] [log] [blame]
Brian Silverman355f11d2018-08-04 23:57:00 -07001#ifndef BOOST_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED
2#define BOOST_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
33namespace boost
34{
35namespace detail
36{
37
38typedef ::pthread_t lw_thread_t;
39
40inline 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
45inline 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
58namespace boost
59{
60namespace detail
61{
62
63typedef HANDLE lw_thread_t;
64
65inline 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
80inline 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
92namespace boost
93{
94namespace detail
95{
96
97class lw_abstract_thread
98{
99public:
100
101 virtual ~lw_abstract_thread() {}
102 virtual void run() = 0;
103};
104
105#if defined( BOOST_HAS_PTHREADS )
106
107extern "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
126unsigned __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
145template<class F> class lw_thread_impl: public lw_abstract_thread
146{
147public:
148
149 explicit lw_thread_impl( F f ): f_( f )
150 {
151 }
152
153 void run()
154 {
155 f_();
156 }
157
158private:
159
160 F f_;
161};
162
163template<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_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED