win_thread.hpp
Go to the documentation of this file.
00001 //
00002 // win_thread.hpp
00003 // ~~~~~~~~~~~~~~
00004 //
00005 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
00006 //
00007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
00008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
00009 //
00010 
00011 #ifndef ASIO_DETAIL_WIN_THREAD_HPP
00012 #define ASIO_DETAIL_WIN_THREAD_HPP
00013 
00014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00015 # pragma once
00016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
00017 
00018 #include "asio/detail/push_options.hpp"
00019 
00020 #include "asio/detail/push_options.hpp"
00021 #include <boost/config.hpp>
00022 #include "asio/detail/pop_options.hpp"
00023 
00024 #if defined(BOOST_WINDOWS) && !defined(UNDER_CE)
00025 
00026 #include "asio/error.hpp"
00027 #include "asio/system_error.hpp"
00028 #include "asio/detail/noncopyable.hpp"
00029 #include "asio/detail/socket_types.hpp"
00030 
00031 #include "asio/detail/push_options.hpp"
00032 #include <boost/throw_exception.hpp>
00033 #include <memory>
00034 #include <process.h>
00035 #include "asio/detail/pop_options.hpp"
00036 
00037 namespace asio {
00038 namespace detail {
00039 
00040 unsigned int __stdcall win_thread_function(void* arg);
00041 
00042 class win_thread
00043   : private noncopyable
00044 {
00045 public:
00046   // The purpose of the thread.
00047   enum purpose { internal, external };
00048 
00049   // Constructor.
00050   template <typename Function>
00051   win_thread(Function f, purpose p = internal)
00052     : exit_event_(0)
00053   {
00054     std::auto_ptr<func_base> arg(new func<Function>(f));
00055 
00056     ::HANDLE entry_event = 0;
00057     if (p == internal)
00058     {
00059       arg->entry_event_ = entry_event = ::CreateEvent(0, true, false, 0);
00060       if (!entry_event)
00061       {
00062         DWORD last_error = ::GetLastError();
00063         asio::system_error e(
00064             asio::error_code(last_error,
00065               asio::error::get_system_category()),
00066             "thread.entry_event");
00067         boost::throw_exception(e);
00068       }
00069 
00070       arg->exit_event_ = exit_event_ = ::CreateEvent(0, true, false, 0);
00071       if (!exit_event_)
00072       {
00073         DWORD last_error = ::GetLastError();
00074         ::CloseHandle(entry_event);
00075         asio::system_error e(
00076             asio::error_code(last_error,
00077               asio::error::get_system_category()),
00078             "thread.exit_event");
00079         boost::throw_exception(e);
00080       }
00081     }
00082 
00083     unsigned int thread_id = 0;
00084     thread_ = reinterpret_cast<HANDLE>(::_beginthreadex(0, 0,
00085           win_thread_function, arg.get(), 0, &thread_id));
00086     if (!thread_)
00087     {
00088       DWORD last_error = ::GetLastError();
00089       if (entry_event)
00090         ::CloseHandle(entry_event);
00091       if (exit_event_)
00092         ::CloseHandle(exit_event_);
00093       asio::system_error e(
00094           asio::error_code(last_error,
00095             asio::error::get_system_category()),
00096           "thread");
00097       boost::throw_exception(e);
00098     }
00099     arg.release();
00100 
00101     if (entry_event)
00102     {
00103       ::WaitForSingleObject(entry_event, INFINITE);
00104       ::CloseHandle(entry_event);
00105     }
00106   }
00107 
00108   // Destructor.
00109   ~win_thread()
00110   {
00111     ::CloseHandle(thread_);
00112 
00113     // The exit_event_ handle is deliberately allowed to leak here since it
00114     // is an error for the owner of an internal thread not to join() it.
00115   }
00116 
00117   // Wait for the thread to exit.
00118   void join()
00119   {
00120     if (exit_event_)
00121     {
00122       ::WaitForSingleObject(exit_event_, INFINITE);
00123       ::CloseHandle(exit_event_);
00124       ::TerminateThread(thread_, 0);
00125     }
00126     else
00127     {
00128       ::WaitForSingleObject(thread_, INFINITE);
00129     }
00130   }
00131 
00132 private:
00133   friend unsigned int __stdcall win_thread_function(void* arg);
00134 
00135   class func_base
00136   {
00137   public:
00138     virtual ~func_base() {}
00139     virtual void run() = 0;
00140     ::HANDLE entry_event_;
00141     ::HANDLE exit_event_;
00142   };
00143 
00144   template <typename Function>
00145   class func
00146     : public func_base
00147   {
00148   public:
00149     func(Function f)
00150       : f_(f)
00151     {
00152     }
00153 
00154     virtual void run()
00155     {
00156       f_();
00157     }
00158 
00159   private:
00160     Function f_;
00161   };
00162 
00163   ::HANDLE thread_;
00164   ::HANDLE exit_event_;
00165 };
00166 
00167 inline unsigned int __stdcall win_thread_function(void* arg)
00168 {
00169   std::auto_ptr<win_thread::func_base> func(
00170       static_cast<win_thread::func_base*>(arg));
00171 
00172   if (func->entry_event_)
00173     ::SetEvent(func->entry_event_);
00174 
00175   func->run();
00176 
00177   if (HANDLE exit_event = func->exit_event_)
00178   {
00179     func.reset();
00180     ::SetEvent(exit_event);
00181     ::Sleep(INFINITE);
00182   }
00183 
00184   return 0;
00185 }
00186 
00187 } // namespace detail
00188 } // namespace asio
00189 
00190 #endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE)
00191 
00192 #include "asio/detail/pop_options.hpp"
00193 
00194 #endif // ASIO_DETAIL_WIN_THREAD_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


Castor
Author(s): Carpe Noctem
autogenerated on Fri Nov 8 2013 11:05:40