dvander@2726: /** dvander@4025: * vim: set ts=4 sw=4 tw=99 noet: dvander@2726: * ============================================================================= dvander@2726: * SourceMod dvander@2726: * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. dvander@2726: * ============================================================================= dvander@2726: * dvander@2726: * This program is free software; you can redistribute it and/or modify it under dvander@2726: * the terms of the GNU General Public License, version 3.0, as published by the dvander@2726: * Free Software Foundation. dvander@2726: * dvander@2726: * This program is distributed in the hope that it will be useful, but WITHOUT dvander@2726: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@2726: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more dvander@2726: * details. dvander@2726: * dvander@2726: * You should have received a copy of the GNU General Public License along with dvander@2726: * this program. If not, see . dvander@2726: * dvander@2726: * As a special exception, AlliedModders LLC gives you permission to link the dvander@2726: * code of this program (as well as its derivative works) to "Half-Life 2," the dvander@2726: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software dvander@2726: * by the Valve Corporation. You must obey the GNU General Public License in dvander@2726: * all respects for all other code used. Additionally, AlliedModders LLC grants dvander@2726: * this exception to all derivative works. AlliedModders LLC defines further dvander@2726: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), dvander@2726: * or . dvander@2726: * dvander@2726: * Version: $Id$ dvander@2726: */ dvander@2726: dvander@2726: #include dvander@2726: #include "PosixThreads.h" dvander@2726: #include "ThreadWorker.h" dvander@2726: dvander@2726: IThreadWorker *PosixThreader::MakeWorker(IThreadWorkerCallbacks *hooks, bool threaded) dvander@2726: { dvander@2726: if (threaded) dvander@2726: { dvander@2726: return new ThreadWorker(hooks, this, DEFAULT_THINK_TIME_MS); dvander@2726: } else { dvander@2726: return new BaseWorker(hooks); dvander@2726: } dvander@2726: } dvander@2726: dvander@2726: void PosixThreader::DestroyWorker(IThreadWorker *pWorker) dvander@2726: { dvander@2726: delete pWorker; dvander@2726: } dvander@2726: dvander@2726: void PosixThreader::ThreadSleep(unsigned int ms) dvander@2726: { dvander@2726: usleep( ms * 1000 ); dvander@2726: } dvander@2726: dvander@2726: void PosixThreader::GetPriorityBounds(ThreadPriority &max, ThreadPriority &min) dvander@2726: { dvander@2726: max = ThreadPrio_Normal; dvander@2726: min = ThreadPrio_Normal; dvander@2726: } dvander@2726: dvander@2726: IMutex *PosixThreader::MakeMutex() dvander@2726: { dvander@4025: return new CompatMutex(); dvander@2726: } dvander@2726: dvander@2726: void PosixThreader::MakeThread(IThread *pThread) dvander@2726: { dvander@2726: ThreadParams defparams; dvander@2726: dvander@2726: defparams.flags = Thread_AutoRelease; dvander@2726: defparams.prio = ThreadPrio_Normal; dvander@2726: dvander@2726: MakeThread(pThread, &defparams); dvander@2726: } dvander@2726: dvander@2726: IThreadHandle *PosixThreader::MakeThread(IThread *pThread, ThreadFlags flags) dvander@2726: { dvander@2726: ThreadParams defparams; dvander@2726: dvander@2726: defparams.flags = flags; dvander@2726: defparams.prio = ThreadPrio_Normal; dvander@2726: dvander@2726: return MakeThread(pThread, &defparams); dvander@2726: } dvander@2726: dvander@4025: void PosixThreader::ThreadHandle::Run() dvander@2726: { dvander@4025: // Wait for an unpause if necessary. dvander@4025: { dvander@4025: ke::AutoLock lock(&m_runlock); dvander@4025: if (m_state == Thread_Paused) dvander@4025: m_runlock.Wait(); dvander@4025: } dvander@2726: dvander@4025: m_run->RunThread(this); dvander@4025: m_state = Thread_Done; dvander@4025: m_run->OnTerminate(this, false); dvander@2726: dvander@4025: if (m_params.flags & Thread_AutoRelease) dvander@4025: delete this; dvander@2726: } dvander@2726: dvander@2726: ThreadParams g_defparams; dvander@2726: IThreadHandle *PosixThreader::MakeThread(IThread *pThread, const ThreadParams *params) dvander@2726: { dvander@2726: if (params == NULL) dvander@2726: params = &g_defparams; dvander@2726: dvander@4025: ke::AutoPtr pHandle(new ThreadHandle(this, pThread, params)); dvander@2726: dvander@4025: pHandle->m_thread = new ke::Thread(pHandle, "SourceMod"); dvander@4025: if (!pHandle->m_thread->Succeeded()) dvander@2726: return NULL; dvander@2726: dvander@4025: if (!(params->flags & Thread_CreateSuspended)) dvander@4025: pHandle->Unpause(); dvander@2726: dvander@4025: return pHandle.take(); dvander@2726: } dvander@2726: dvander@2726: IEventSignal *PosixThreader::MakeEventSignal() dvander@2726: { dvander@4025: return new CompatCondVar(); dvander@2726: } dvander@2726: dvander@2726: /****************** dvander@2726: * Thread Handles * dvander@2726: ******************/ dvander@2726: dvander@2726: PosixThreader::ThreadHandle::ThreadHandle(IThreader *parent, IThread *run, const ThreadParams *params) : dvander@2726: m_parent(parent), m_params(*params), m_run(run), m_state(Thread_Paused) dvander@2726: { dvander@2726: } dvander@2726: dvander@2726: PosixThreader::ThreadHandle::~ThreadHandle() dvander@2726: { dvander@2726: } dvander@2726: dvander@2726: bool PosixThreader::ThreadHandle::WaitForThread() dvander@2726: { dvander@4025: if (!m_thread) dvander@2726: return false; dvander@2726: dvander@4025: m_thread->Join(); dvander@2726: return true; dvander@2726: } dvander@2726: dvander@2726: ThreadState PosixThreader::ThreadHandle::GetState() dvander@2726: { dvander@4025: return m_state; dvander@2726: } dvander@2726: dvander@2726: IThreadCreator *PosixThreader::ThreadHandle::Parent() dvander@2726: { dvander@2726: return m_parent; dvander@2726: } dvander@2726: dvander@2726: void PosixThreader::ThreadHandle::DestroyThis() dvander@2726: { dvander@2726: if (m_params.flags & Thread_AutoRelease) dvander@2726: return; dvander@2726: dvander@2726: delete this; dvander@2726: } dvander@2726: dvander@2726: void PosixThreader::ThreadHandle::GetParams(ThreadParams *ptparams) dvander@2726: { dvander@2726: if (!ptparams) dvander@2726: return; dvander@2726: dvander@2726: *ptparams = m_params; dvander@2726: } dvander@2726: dvander@2726: ThreadPriority PosixThreader::ThreadHandle::GetPriority() dvander@2726: { dvander@2726: return ThreadPrio_Normal; dvander@2726: } dvander@2726: dvander@2726: bool PosixThreader::ThreadHandle::SetPriority(ThreadPriority prio) dvander@2726: { dvander@2726: return (prio == ThreadPrio_Normal); dvander@2726: } dvander@2726: dvander@2726: bool PosixThreader::ThreadHandle::Unpause() dvander@2726: { dvander@2726: if (m_state != Thread_Paused) dvander@2726: return false; dvander@2726: dvander@4025: ke::AutoLock lock(&m_runlock); dvander@2726: m_state = Thread_Running; dvander@4025: m_runlock.Notify(); dvander@2726: return true; dvander@2726: } dvander@2726: