Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages
threading.h
Go to the documentation of this file.00001 00004 /* 00005 * Copyright © 2001-2002 Sofus Mortensen, Mikael Lindgren 00006 * 00007 * This material is provided "as is", with absolutely no warranty 00008 * expressed or implied. Any use is at your own risk. Permission to 00009 * use or copy this software for any purpose is hereby granted without 00010 * fee, provided the above notices are retained on all copies. 00011 * Permission to modify the code and to distribute modified code is 00012 * granted, provided the above notices are retained, and a notice that 00013 * the code was modified is included with the above copyright notice. 00014 * 00015 * This header is part of comet. 00016 * http://www.lambdasoft.dk/comet 00017 */ 00018 00019 #ifndef COMET_THREADING_H 00020 #define COMET_THREADING_H 00021 00022 #include <comet/config.h> 00023 #include <comet/handle.h> 00024 00025 #include <comet/error.h> 00026 00027 namespace comet { 00028 00032 class critical_section { 00033 public: 00034 critical_section() { 00035 ::InitializeCriticalSection(&cs_); 00036 } 00037 00038 ~critical_section() { 00039 ::DeleteCriticalSection(&cs_); 00040 } 00041 00042 void enter() const { 00043 ::EnterCriticalSection(&cs_); 00044 } 00045 00046 void leave() const { 00047 ::LeaveCriticalSection(&cs_); 00048 } 00049 00050 private: 00051 critical_section(const critical_section&); 00052 critical_section& operator=(const critical_section&); 00053 00054 mutable CRITICAL_SECTION cs_; 00055 }; 00056 00060 class auto_cs { 00061 public: 00062 explicit auto_cs(const critical_section& cs) : cs_(cs) { 00063 cs_.enter(); 00064 } 00065 00066 ~auto_cs() { 00067 cs_.leave(); 00068 } 00069 00070 private: 00071 auto_cs& operator=(const auto_cs&); 00072 auto_cs(const auto_cs&); 00073 00074 const critical_section& cs_; 00075 }; 00076 00082 template <typename T> class locking_ptr { 00083 public: 00084 locking_ptr(volatile T& obj, critical_section& cs) : 00085 pointer_(const_cast<T*>(&obj)), 00086 cs_(cs) 00087 { 00088 cs_.enter(); 00089 } 00090 00091 ~locking_ptr() 00092 { 00093 cs_.leave(); 00094 } 00095 00096 T& operator*() 00097 { 00098 return *pointer_; 00099 } 00100 00101 T* operator->() 00102 { 00103 return pointer_; 00104 } 00105 00106 private: 00107 T* pointer_; 00108 critical_section& cs_; 00109 00110 locking_ptr(const locking_ptr&); 00111 locking_ptr& operator=(const locking_ptr&); 00112 }; 00113 00114 class thread 00115 { 00116 private: 00117 DWORD id_; 00118 auto_handle handle_; 00119 00120 // declare non-copyable 00121 thread(const& thread); 00122 thread& operator=(const& thread); 00123 public: 00124 thread() : id_(0) 00125 {} 00126 00127 const auto_handle& start() 00128 { 00129 handle_ = auto_attach(::CreateThread(0, 0, &thread::start_proc, this, 0, &id_)); 00130 return handle_; 00131 } 00132 00133 const auto_handle& handle() const 00134 { 00135 return handle_; 00136 } 00137 00138 void exit(DWORD exit_code) 00139 { 00140 ::ExitThread(exit_code); 00141 } 00142 00143 void suspend() 00144 { 00145 ::SuspendThread(handle_); 00146 } 00147 00148 void resume() 00149 { 00150 ::ResumeThread(handle_); 00151 } 00152 00153 bool running() 00154 { 00155 DWORD code; 00156 return handle_ && 00157 ::GetExitCodeThread(handle_, &code) && 00158 code == STILL_ACTIVE; 00159 } 00160 00161 bool wait(DWORD timeout = INFINITE) 00162 { 00163 return ::WaitForSingleObject(handle_, timeout) == WAIT_OBJECT_0; 00164 } 00165 00166 private: 00167 static DWORD _stdcall start_proc(void* param) 00168 { 00169 return static_cast<thread*>(param)->thread_main(); 00170 } 00171 00172 virtual DWORD thread_main() = 0; 00173 }; 00174 00175 class event 00176 { 00177 private: 00178 auto_handle handle_; 00179 00180 // declare non-copyable 00181 event(const& event); 00182 event& operator=(const& event); 00183 public: 00184 explicit event(bool initial_state = false) 00185 { 00186 handle_ = auto_attach(::CreateEvent(0, false, initial_state, 0)); 00187 } 00188 00189 explicit event(const TCHAR* name, bool initial_state = false) 00190 { 00191 handle_ = auto_attach(::CreateEvent(0, false, initial_state, name)); 00192 } 00193 00194 void set() 00195 { 00196 if (0 == ::SetEvent(handle_)) 00197 { 00198 DWORD err = GetLastError(); 00199 raise_exception(HRESULT_FROM_WIN32(err)); 00200 } 00201 } 00202 00203 void reset() 00204 { 00205 if (0==::ResetEvent(handle_) ) 00206 { 00207 DWORD err = GetLastError(); 00208 raise_exception(HRESULT_FROM_WIN32(err)); 00209 } 00210 } 00211 00212 bool wait(DWORD timeout = INFINITE) 00213 { 00214 return ::WaitForSingleObject(handle_, timeout) == WAIT_OBJECT_0; 00215 } 00216 00217 bool is_set() 00218 { 00219 return ::WaitForSingleObject(handle_, 0) == WAIT_OBJECT_0; 00220 } 00221 00222 operator HANDLE() const 00223 { return handle_; } 00224 }; 00225 00226 } 00227 00228 #endif