1 //
2 // detail/win_thread.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10 
11 #ifndef ASIO_DETAIL_WIN_THREAD_HPP
12 #define ASIO_DETAIL_WIN_THREAD_HPP
13 
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17 
18 #include "asio/detail/config.hpp"
19 
20 #if defined(ASIO_WINDOWS) && !defined(UNDER_CE)
21 
22 #include "asio/detail/noncopyable.hpp"
23 #include "asio/detail/socket_types.hpp"
24 
25 #include "asio/detail/push_options.hpp"
26 
27 namespace clmdep_asio {
28 namespace detail {
29 
30 ASIO_DECL unsigned int __stdcall win_thread_function(void* arg);
31 
32 #if defined(WINVER) && (WINVER < 0x0500)
33 ASIO_DECL void __stdcall apc_function(ULONG data);
34 #else
35 ASIO_DECL void __stdcall apc_function(ULONG_PTR data);
36 #endif
37 
38 template <typename T>
39 class win_thread_base
40 {
41 public:
terminate_threads()42   static bool terminate_threads()
43   {
44     return ::InterlockedExchangeAdd(&terminate_threads_, 0) != 0;
45   }
46 
set_terminate_threads(bool b)47   static void set_terminate_threads(bool b)
48   {
49     ::InterlockedExchange(&terminate_threads_, b ? 1 : 0);
50   }
51 
52 private:
53   static long terminate_threads_;
54 };
55 
56 template <typename T>
57 long win_thread_base<T>::terminate_threads_ = 0;
58 
59 class win_thread
60   : private noncopyable,
61     public win_thread_base<win_thread>
62 {
63 public:
64   // Constructor.
65   template <typename Function>
win_thread(Function f,unsigned int stack_size=0)66   win_thread(Function f, unsigned int stack_size = 0)
67     : thread_(0),
68       exit_event_(0)
69   {
70     start_thread(new func<Function>(f), stack_size);
71   }
72 
73   // Destructor.
74   ASIO_DECL ~win_thread();
75 
76   // Wait for the thread to exit.
77   ASIO_DECL void join();
78 
79 private:
80   friend ASIO_DECL unsigned int __stdcall win_thread_function(void* arg);
81 
82 #if defined(WINVER) && (WINVER < 0x0500)
83   friend ASIO_DECL void __stdcall apc_function(ULONG);
84 #else
85   friend ASIO_DECL void __stdcall apc_function(ULONG_PTR);
86 #endif
87 
88   class func_base
89   {
90   public:
~func_base()91     virtual ~func_base() {}
92     virtual void run() = 0;
93     ::HANDLE entry_event_;
94     ::HANDLE exit_event_;
95   };
96 
97   struct auto_func_base_ptr
98   {
99     func_base* ptr;
~auto_func_base_ptrclmdep_asio::detail::win_thread::auto_func_base_ptr100     ~auto_func_base_ptr() { delete ptr; }
101   };
102 
103   template <typename Function>
104   class func
105     : public func_base
106   {
107   public:
func(Function f)108     func(Function f)
109       : f_(f)
110     {
111     }
112 
run()113     virtual void run()
114     {
115       f_();
116     }
117 
118   private:
119     Function f_;
120   };
121 
122   ASIO_DECL void start_thread(func_base* arg, unsigned int stack_size);
123 
124   ::HANDLE thread_;
125   ::HANDLE exit_event_;
126 };
127 
128 } // namespace detail
129 } // namespace clmdep_asio
130 
131 #include "asio/detail/pop_options.hpp"
132 
133 #if defined(ASIO_HEADER_ONLY)
134 # include "asio/detail/impl/win_thread.ipp"
135 #endif // defined(ASIO_HEADER_ONLY)
136 
137 #endif // defined(ASIO_WINDOWS) && !defined(UNDER_CE)
138 
139 #endif // ASIO_DETAIL_WIN_THREAD_HPP
140