1 //
2 // detail/winapp_thread.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2021 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 BOOST_ASIO_DETAIL_WINAPP_THREAD_HPP
12 #define BOOST_ASIO_DETAIL_WINAPP_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 <boost/asio/detail/config.hpp>
19 
20 #if defined(BOOST_ASIO_WINDOWS) && defined(BOOST_ASIO_WINDOWS_APP)
21 
22 #include <boost/asio/detail/noncopyable.hpp>
23 #include <boost/asio/detail/scoped_ptr.hpp>
24 #include <boost/asio/detail/socket_types.hpp>
25 #include <boost/asio/detail/throw_error.hpp>
26 #include <boost/asio/error.hpp>
27 
28 #include <boost/asio/detail/push_options.hpp>
29 
30 namespace boost {
31 namespace asio {
32 namespace detail {
33 
34 DWORD WINAPI winapp_thread_function(LPVOID arg);
35 
36 class winapp_thread
37   : private noncopyable
38 {
39 public:
40   // Constructor.
41   template <typename Function>
winapp_thread(Function f,unsigned int=0)42   winapp_thread(Function f, unsigned int = 0)
43   {
44     scoped_ptr<func_base> arg(new func<Function>(f));
45     DWORD thread_id = 0;
46     thread_ = ::CreateThread(0, 0, winapp_thread_function,
47         arg.get(), 0, &thread_id);
48     if (!thread_)
49     {
50       DWORD last_error = ::GetLastError();
51       boost::system::error_code ec(last_error,
52           boost::asio::error::get_system_category());
53       boost::asio::detail::throw_error(ec, "thread");
54     }
55     arg.release();
56   }
57 
58   // Destructor.
~winapp_thread()59   ~winapp_thread()
60   {
61     ::CloseHandle(thread_);
62   }
63 
64   // Wait for the thread to exit.
join()65   void join()
66   {
67     ::WaitForSingleObjectEx(thread_, INFINITE, false);
68   }
69 
70   // Get number of CPUs.
hardware_concurrency()71   static std::size_t hardware_concurrency()
72   {
73     SYSTEM_INFO system_info;
74     ::GetNativeSystemInfo(&system_info);
75     return system_info.dwNumberOfProcessors;
76   }
77 
78 private:
79   friend DWORD WINAPI winapp_thread_function(LPVOID arg);
80 
81   class func_base
82   {
83   public:
~func_base()84     virtual ~func_base() {}
85     virtual void run() = 0;
86   };
87 
88   template <typename Function>
89   class func
90     : public func_base
91   {
92   public:
func(Function f)93     func(Function f)
94       : f_(f)
95     {
96     }
97 
run()98     virtual void run()
99     {
100       f_();
101     }
102 
103   private:
104     Function f_;
105   };
106 
107   ::HANDLE thread_;
108 };
109 
winapp_thread_function(LPVOID arg)110 inline DWORD WINAPI winapp_thread_function(LPVOID arg)
111 {
112   scoped_ptr<winapp_thread::func_base> func(
113       static_cast<winapp_thread::func_base*>(arg));
114   func->run();
115   return 0;
116 }
117 
118 } // namespace detail
119 } // namespace asio
120 } // namespace boost
121 
122 #include <boost/asio/detail/pop_options.hpp>
123 
124 #endif // defined(BOOST_ASIO_WINDOWS) && defined(BOOST_ASIO_WINDOWS_APP)
125 
126 #endif // BOOST_ASIO_DETAIL_WINAPP_THREAD_HPP
127