/*==LICENSE==* CyanWorlds.com Engine - MMOG client, server and tools Copyright (C) 2011 Cyan Worlds, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . You can contact Cyan Worlds, Inc. by email legal@cyan.com or by snail mail at: Cyan Worlds, Inc. 14617 N Newport Hwy Mead, WA 99021 *==LICENSE==*/ #include #include "hsThread.h" #include "hsExceptions.h" #include "hsMemory.h" // typedef unsigned int __stdcall (*EntryPtCB)(void*); static DWORD __stdcall gEntryPoint(void* param) { return ((hsThread*)param)->WinRun(); } static unsigned int __stdcall gEntryPointBT(void* param) { return ((hsThread*)param)->WinRun(); } hsThread::hsThread(UInt32 stackSize) : fStackSize(stackSize), fQuit(false), fThreadH(nil), fQuitSemaH(nil) { } hsThread::~hsThread() { this->Stop(); } void hsThread::Start() { if (fThreadH == nil) { fQuitSemaH = ::CreateSemaphore(nil, 0, kPosInfinity32, nil); if (fQuitSemaH == nil) throw hsOSException(-1); #if 0 fThreadH = ::CreateThread(nil, fStackSize, gEntryPoint, this, 0, &fThreadId); #else fThreadH = (HANDLE)_beginthreadex(nil, fStackSize, gEntryPointBT, this, 0, (unsigned int*)&fThreadId); #endif if (fThreadH == nil) throw hsOSException(-1); } } void hsThread::Stop() { if (fThreadH != nil) { this->fQuit = true; if (fQuitSemaH != nil) ::WaitForSingleObject(fQuitSemaH, INFINITE); // wait for the thread to quit ::CloseHandle(fThreadH); fThreadH = nil; ::CloseHandle(fQuitSemaH); fQuitSemaH = nil; } } DWORD hsThread::WinRun() { DWORD result = this->Run(); ::ReleaseSemaphore(fQuitSemaH, 1, nil); // signal that we've quit return result; } ///////////////////////////////////////////////////////////////////////////////////////// void* hsThread::Alloc(size_t size) { return HSMemory::New(size); } void hsThread::Free(void* p) { HSMemory::Delete(p); } void hsThread::ThreadYield() { // Don't know how to explicitly yield on WIN32 } ////////////////////////////////////////////////////////////////////////////// hsMutex::hsMutex() { fMutexH = ::CreateMutex(nil, false, nil); if (fMutexH == nil) throw hsOSException(-1); } hsMutex::~hsMutex() { ::CloseHandle(fMutexH); } void hsMutex::Lock() { DWORD state = ::WaitForSingleObject(fMutexH, INFINITE); hsAssert(state != WAIT_FAILED,"hsMutex::Lock -> Wait Failed"); hsAssert(state != WAIT_ABANDONED,"hsMutex::Lock -> Abandoned Mutex"); hsAssert(state != WAIT_TIMEOUT,"hsMutex::Lock -> Infinite Timeout expired?"); } hsBool hsMutex::TryLock() { DWORD state = ::WaitForSingleObject(fMutexH, 0); hsAssert(state != WAIT_ABANDONED,"hsMutex::TryLock -> Abandoned Mutex"); return state == WAIT_OBJECT_0?true:false; } void hsMutex::Unlock() { BOOL result = ::ReleaseMutex(fMutexH); hsAssert(result != 0, "hsMutex::Unlock Failed!"); } ////////////////////////////////////////////////////////////////////////////// hsSemaphore::hsSemaphore(int initialValue, const char *name) { fSemaH = ::CreateSemaphore(nil, initialValue, kPosInfinity32, name); if (fSemaH == nil) throw hsOSException(-1); } hsSemaphore::~hsSemaphore() { ::CloseHandle(fSemaH); } hsBool hsSemaphore::Wait(hsMilliseconds timeToWait) { if (timeToWait == kPosInfinity32) timeToWait = INFINITE; DWORD result =::WaitForSingleObject(fSemaH, timeToWait); if (result == WAIT_OBJECT_0) return true; else { hsThrowIfFalse(result == WAIT_TIMEOUT); return false; } } void hsSemaphore::Signal() { ::ReleaseSemaphore(fSemaH, 1, nil); } /////////////////////////////////////////////////////////////// hsEvent::hsEvent() { fEvent = ::CreateEvent(nil,true,false,nil); if (fEvent == nil) throw hsOSException(-1); } hsEvent::~hsEvent() { ::CloseHandle(fEvent); } hsBool hsEvent::Wait(hsMilliseconds timeToWait) { if (timeToWait == kPosInfinity32) timeToWait = INFINITE; DWORD result =::WaitForSingleObject(fEvent, timeToWait); if (result == WAIT_OBJECT_0) { ::ResetEvent(fEvent); return true; } else { hsThrowIfFalse(result == WAIT_TIMEOUT); return false; } } void hsEvent::Signal() { ::SetEvent(fEvent); }