00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00016 #include <windows.h>
00017 #include <process.h>
00018 #include <ders/thread.hpp>
00019 #include <algorithm>
00020 #include <vector>
00021 #include <ders/error.hpp>
00022
00023 namespace {
00024
00025 using namespace std;
00026 using namespace ders;
00027 using namespace ders::detail;
00028
00029 struct win_thread : public thread {
00030 mem_pool& mp;
00031 tc_ptr core;
00032
00033 win_thread(mem_pool& m, void (*strt)(void*), void* arg);
00034 ~win_thread();
00035
00036 virtual bool is_running();
00037 virtual void join();
00038 virtual void destroy(mem_pool& mp2) { destroy_this(this, mp2); }
00039
00040 void start();
00041 };
00042
00043 struct win_mutex : public mutex {
00044 CRITICAL_SECTION cs;
00045
00046 win_mutex();
00047 ~win_mutex();
00048
00049 virtual void lock();
00050 virtual void unlock();
00051
00052 virtual void destroy(mem_pool& mp2) { destroy_this(this, mp2); }
00053 };
00054
00055 class event_cache {
00056 vector<HANDLE> evs;
00057
00058 event_cache(const event_cache&);
00059 event_cache& operator=(const event_cache&);
00060
00061 public:
00062 event_cache();
00063 ~event_cache();
00064
00065 HANDLE getEvent();
00066 void returnEvent(HANDLE ev);
00067 };
00068
00069 struct win_cond_var : public cond_var {
00070 mutex& m;
00071 event_cache evc;
00072 vector<HANDLE> wts;
00073
00074 win_cond_var(mutex& mtx);
00075 ~win_cond_var();
00076
00077 virtual void wait(long timeout);
00078 virtual void notify();
00079 virtual void notify_all();
00080
00081 virtual void destroy(mem_pool& mp2) { destroy_this(this, mp2); }
00082 };
00083
00084 unsigned __stdcall win32_start(void* arg)
00085 {
00086 static_cast<thr_core*>(arg)->start();
00087 return 0;
00088 }
00089
00090 win_thread::win_thread(mem_pool& m, void (*strt)(void*), void* arg) :
00091 mp(m), core(true, new thr_core(strt, arg))
00092 {
00093 }
00094
00095 win_thread::~win_thread()
00096 {
00097 }
00098
00099 bool win_thread::is_running()
00100 {
00101 return core->is_running();
00102 }
00103
00104 void win_thread::join()
00105 {
00106 core->join();
00107 }
00108
00109 void win_thread::start()
00110 {
00111 unsigned tid;
00112 HANDLE thn=(HANDLE)_beginthreadex(0, 0, win32_start, core.ptr, 0, &tid);
00113 if (thn==0) {
00114 core->clear_rng();
00115
00116 throw newErrorException(mp, _FLINE_, "Can't begin thread", convert_errno(
00117 errno));
00118 }
00119
00120 CloseHandle(thn);
00121 }
00122
00123 win_mutex::win_mutex()
00124 {
00125 InitializeCriticalSection(&cs);
00126 }
00127
00128 win_mutex::~win_mutex()
00129 {
00130 DeleteCriticalSection(&cs);
00131 }
00132
00133 void win_mutex::lock()
00134 {
00135 EnterCriticalSection(&cs);
00136 }
00137
00138 void win_mutex::unlock()
00139 {
00140 LeaveCriticalSection(&cs);
00141 }
00142
00143 event_cache::event_cache()
00144 {
00145 evs.reserve(16);
00146 }
00147
00148 event_cache::~event_cache()
00149 {
00150 for (int i=0, end=evs.size(); i<end; i++) CloseHandle(evs[i]);
00151 }
00152
00153 HANDLE event_cache::getEvent()
00154 {
00155 HANDLE ev;
00156 if (evs.size()>0) {
00157 ev=evs.back();
00158 evs.pop_back();
00159 }
00160 else {
00161 ev=CreateEvent(0, FALSE, FALSE, 0);
00162 hard_assert(ev!=0);
00163 }
00164
00165 return ev;
00166 }
00167
00168 void event_cache::returnEvent(HANDLE ev)
00169 {
00170 assert(ev!=0);
00171 try { evs.push_back(ev); }
00172 catch (...) {
00173 CloseHandle(ev);
00174 throw;
00175 }
00176 }
00177
00178 win_cond_var::win_cond_var(mutex& mtx) : m(mtx)
00179 {
00180 wts.reserve(16);
00181 }
00182
00183 win_cond_var::~win_cond_var()
00184 {
00185 assert(wts.size()==0);
00186 }
00187
00188 void win_cond_var::wait(long timeout)
00189 {
00190 HANDLE ev=evc.getEvent();
00191 try { wts.push_back(ev); }
00192 catch (...) {
00193 CloseHandle(ev);
00194 throw;
00195 }
00196
00197 m.unlock();
00198
00199 DWORD rcd=WaitForSingleObject(ev, (timeout==infinite) ? timeout : INFINITE);
00200 hard_assert(rcd==WAIT_OBJECT_0 || rcd==WAIT_TIMEOUT);
00201
00202 m.lock();
00203
00204 if (rcd==WAIT_TIMEOUT) {
00205 vector<HANDLE>::iterator it=find(wts.begin(), wts.end(), ev);
00206 if (it==wts.end()) {
00207 BOOL rc=ResetEvent(ev);
00208 hard_assert(rc!=0);
00209 }
00210 else wts.erase(it);
00211 }
00212
00213 evc.returnEvent(ev);
00214 }
00215
00216 void win_cond_var::notify()
00217 {
00218 if (wts.size()==0) return;
00219
00220 HANDLE ev=wts.back();
00221 wts.pop_back();
00222
00223 BOOL rc=SetEvent(ev);
00224 hard_assert(rc!=0);
00225 }
00226
00227 void win_cond_var::notify_all()
00228 {
00229 if (wts.size()==0) return;
00230
00231 for (int i=0, end=wts.size(); i<end; i++) {
00232 BOOL rc=SetEvent(wts[i]);
00233 hard_assert(rc!=0);
00234 }
00235
00236 wts.clear();
00237 }
00238
00239 }
00240
00241 namespace ders {
00242
00243 sh_thread new_thread(mem_pool& mp, void (*start)(void*), void* arg)
00244 {
00245 mp_newbuf<win_thread> buf(mp);
00246 sh_thread ret(buf.pool(), buf.rls(::new(buf.get()) win_thread(buf.pool(),
00247 start, arg)));
00248
00249 static_cast<win_thread*>(ret.get())->start();
00250
00251 return ret;
00252 }
00253
00254 sh_mutex new_mutex(mem_pool& mp)
00255 {
00256 mp_newbuf<win_mutex> buf(mp);
00257 return sh_mutex(buf.pool(), buf.rls(::new(buf.get()) win_mutex));
00258 }
00259
00260 sh_cond_var new_cond_var(mem_pool& mp, mutex& mtx)
00261 {
00262 mp_newbuf<win_cond_var> buf(mp);
00263 return sh_cond_var(buf.pool(), buf.rls(::new(buf.get()) win_cond_var(mtx)));
00264 }
00265
00266 }
00267