lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
|
00001 /*****************************************************/ 00002 /* lean Concurrent (c) Tobias Zirr 2011 */ 00003 /*****************************************************/ 00004 00005 #ifndef LEAN_CONCURRENT_THREAD 00006 #define LEAN_CONCURRENT_THREAD 00007 00008 #include "../lean.h" 00009 #include "../tags/noncopyable.h" 00010 #include <process.h> 00011 #include <windows.h> 00012 #include <lean/logging/win_errors.h> 00013 00014 namespace lean 00015 { 00016 namespace concurrent 00017 { 00018 00020 class thread : public noncopyable 00021 { 00022 private: 00023 HANDLE m_handle; 00024 00026 template <class Callable> 00027 static unsigned int _stdcall run_thread(void *args) 00028 { 00029 unsigned int result = 0; 00030 00031 Callable *callable = static_cast<Callable*>(args); 00032 LEAN_ASSERT_NOT_NULL(callable); 00033 00034 try 00035 { 00036 try 00037 { 00038 (*callable)(); 00039 } 00040 catch (const std::exception &exc) 00041 { 00042 LEAN_LOG_ERROR_CTX("Unhandled exception during execution of thread", exc.what()); 00043 result = static_cast<unsigned int>(-1); 00044 } 00045 catch (...) 00046 { 00047 LEAN_LOG_ERROR_MSG("Unhandled exception during execution of thread"); 00048 result = static_cast<unsigned int>(-1); 00049 } 00050 00051 delete callable; 00052 } 00053 catch (...) 00054 { 00055 result = static_cast<unsigned int>(-2); 00056 } 00057 00058 return result; 00059 } 00060 00062 template <class Callable> 00063 static HANDLE run_thread(Callable *callable) 00064 { 00065 LEAN_ASSERT_NOT_NULL(callable); 00066 00067 HANDLE handle = reinterpret_cast<HANDLE>( 00068 ::_beginthreadex(nullptr, 0, &run_thread<Callable>, callable, 0, nullptr) 00069 ); 00070 00071 if (handle == NULL) 00072 { 00073 delete callable; 00074 LEAN_THROW_WIN_ERROR_MSG("_beginthreadex() failed"); 00075 } 00076 00077 return handle; 00078 } 00079 00080 public: 00082 thread() 00083 : m_handle(NULL) { } 00085 template <class Callable> 00086 thread(const Callable &callable) 00087 : m_handle( run_thread( new Callable(callable) ) ) { } 00088 #ifndef LEAN0X_NO_RVALUE_REFERENCES 00089 00090 template <class Callable> 00091 thread(Callable &&callable) 00092 : m_handle( run_thread( new Callable(std::move(callable)) ) ) { } 00094 thread(thread &&right) 00095 : m_handle(right.m_handle) 00096 { 00097 right.m_handle = NULL; 00098 } 00099 #endif 00100 00101 ~thread() 00102 { 00103 if (m_handle != NULL) 00104 ::CloseHandle(m_handle); 00105 } 00106 00107 #ifndef LEAN0X_NO_RVALUE_REFERENCES 00108 00109 thread& operator =(thread &&right) 00110 { 00111 if (m_handle != right.m_handle) 00112 { 00113 detach(); 00114 m_handle = right.m_handle; 00115 right.m_handle = NULL; 00116 } 00117 return *this; 00118 } 00119 #endif 00120 00122 void detach() 00123 { 00124 if (m_handle != NULL) 00125 { 00126 ::CloseHandle(m_handle); 00127 m_handle = NULL; 00128 } 00129 } 00130 00132 LEAN_INLINE bool joinable() const 00133 { 00134 return (m_handle != NULL); 00135 } 00137 void join() 00138 { 00139 if (m_handle != NULL) 00140 if (::WaitForSingleObject(m_handle, INFINITE) == WAIT_FAILED) 00141 LEAN_THROW_WIN_ERROR_MSG("WaitForSingleObject()"); 00142 } 00143 00145 LEAN_INLINE HANDLE native_handle() const 00146 { 00147 return m_handle; 00148 } 00149 }; 00150 00151 } // namespace 00152 00153 using concurrent::thread; 00154 00155 } // namespace 00156 00157 #endif