diff -r 000000000000 -r c24a6fa957db core/thread/BaseWorker.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core/thread/BaseWorker.cpp Sun Jul 06 04:49:55 2008 +0000
@@ -0,0 +1,303 @@
+/**
+ * vim: set ts=4 :
+ * =============================================================================
+ * SourceMod
+ * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
+ * =============================================================================
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, version 3.0, as published by the
+ * Free Software Foundation.
+ *
+ * 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 .
+ *
+ * As a special exception, AlliedModders LLC gives you permission to link the
+ * code of this program (as well as its derivative works) to "Half-Life 2," the
+ * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
+ * by the Valve Corporation. You must obey the GNU General Public License in
+ * all respects for all other code used. Additionally, AlliedModders LLC grants
+ * this exception to all derivative works. AlliedModders LLC defines further
+ * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
+ * or .
+ *
+ * Version: $Id$
+ */
+
+#include "BaseWorker.h"
+
+BaseWorker::BaseWorker(IThreadWorkerCallbacks *hooks) :
+ m_perFrame(SM_DEFAULT_THREADS_PER_FRAME),
+ m_state(Worker_Stopped),
+ m_pHooks(hooks)
+{
+}
+
+BaseWorker::~BaseWorker()
+{
+ if (m_state != Worker_Stopped || m_state != Worker_Invalid)
+ Stop(true);
+
+ if (m_ThreadQueue.size())
+ Flush(true);
+}
+
+void BaseWorker::MakeThread(IThread *pThread)
+{
+ ThreadParams pt;
+
+ pt.flags = Thread_AutoRelease;
+ pt.prio = ThreadPrio_Normal;
+
+ MakeThread(pThread, &pt);
+}
+
+IThreadHandle *BaseWorker::MakeThread(IThread *pThread, ThreadFlags flags)
+{
+ ThreadParams pt;
+
+ pt.flags = flags;
+ pt.prio = ThreadPrio_Normal;
+
+ return MakeThread(pThread, &pt);
+}
+
+IThreadHandle *BaseWorker::MakeThread(IThread *pThread, const ThreadParams *params)
+{
+ if (m_state != Worker_Running)
+ return NULL;
+
+ SWThreadHandle *swt = new SWThreadHandle(this, params, pThread);
+
+ AddThreadToQueue(swt);
+
+ return swt;
+}
+
+void BaseWorker::GetPriorityBounds(ThreadPriority &max, ThreadPriority &min)
+{
+ max = ThreadPrio_Normal;
+ min = ThreadPrio_Normal;
+}
+
+unsigned int BaseWorker::Flush(bool flush_cancel)
+{
+ SWThreadHandle *swt;
+ unsigned int num = 0;
+
+ while ((swt=PopThreadFromQueue()) != NULL)
+ {
+ swt->m_state = Thread_Done;
+ if (!flush_cancel)
+ swt->pThread->RunThread(swt);
+ swt->pThread->OnTerminate(swt, flush_cancel);
+ if (swt->m_params.flags & Thread_AutoRelease)
+ delete swt;
+ num++;
+ }
+
+ return num;
+}
+
+SWThreadHandle *BaseWorker::PopThreadFromQueue()
+{
+ if (!m_ThreadQueue.size())
+ return NULL;
+
+ SourceHook::List::iterator begin;
+ SWThreadHandle *swt;
+
+ begin = m_ThreadQueue.begin();
+ swt = (*begin);
+ m_ThreadQueue.erase(begin);
+
+ return swt;
+}
+
+void BaseWorker::AddThreadToQueue(SWThreadHandle *pHandle)
+{
+ m_ThreadQueue.push_back(pHandle);
+}
+
+unsigned int BaseWorker::GetMaxThreadsPerFrame()
+{
+ return m_perFrame;
+}
+
+WorkerState BaseWorker::GetStatus(unsigned int *threads)
+{
+ if (threads)
+ *threads = m_perFrame;
+
+ return m_state;
+}
+
+unsigned int BaseWorker::RunFrame()
+{
+ unsigned int done = 0;
+ unsigned int max = GetMaxThreadsPerFrame();
+ SWThreadHandle *swt = NULL;
+ IThread *pThread = NULL;
+
+ while (done < max)
+ {
+ if ((swt=PopThreadFromQueue()) == NULL)
+ {
+ break;
+ }
+ pThread = swt->pThread;
+ swt->m_state = Thread_Running;
+ pThread->RunThread(swt);
+ swt->m_state = Thread_Done;
+ pThread->OnTerminate(swt, false);
+ if (swt->m_params.flags & Thread_AutoRelease)
+ {
+ delete swt;
+ }
+ done++;
+ }
+
+ return done;
+}
+
+void BaseWorker::SetMaxThreadsPerFrame(unsigned int threads)
+{
+ m_perFrame = threads;
+}
+
+bool BaseWorker::Start()
+{
+ if (m_state != Worker_Invalid && m_state != Worker_Stopped)
+ {
+ return false;
+ }
+
+ m_state = Worker_Running;
+
+ if (m_pHooks)
+ {
+ m_pHooks->OnWorkerStart(this);
+ }
+
+ return true;
+}
+
+bool BaseWorker::Stop(bool flush_cancel)
+{
+ if (m_state == Worker_Invalid || m_state == Worker_Stopped)
+ {
+ return false;
+ }
+
+ if (m_state == Worker_Paused)
+ {
+ if (!Unpause())
+ {
+ return false;
+ }
+ }
+
+ m_state = Worker_Stopped;
+ Flush(flush_cancel);
+
+ if (m_pHooks)
+ {
+ m_pHooks->OnWorkerStop(this);
+ }
+
+ return true;
+}
+
+bool BaseWorker::Pause()
+{
+ if (m_state != Worker_Running)
+ {
+ return false;
+ }
+
+ m_state = Worker_Paused;
+
+ return true;
+}
+
+
+bool BaseWorker::Unpause()
+{
+ if (m_state != Worker_Paused)
+ {
+ return false;
+ }
+
+ m_state = Worker_Running;
+
+ return true;
+}
+
+/***********************
+ * THREAD HANDLE STUFF *
+ ***********************/
+
+void SWThreadHandle::DestroyThis()
+{
+ delete this;
+}
+
+void SWThreadHandle::GetParams(ThreadParams *p)
+{
+ *p = m_params;
+}
+
+ThreadPriority SWThreadHandle::GetPriority()
+{
+ return m_params.prio;
+}
+
+ThreadState SWThreadHandle::GetState()
+{
+ return m_state;
+}
+
+IThreadCreator *SWThreadHandle::Parent()
+{
+ return m_parent;
+}
+
+bool SWThreadHandle::SetPriority(ThreadPriority prio)
+{
+ if (m_params.prio != ThreadPrio_Normal)
+ return false;
+
+ m_params.prio = prio;
+
+ return true;
+}
+
+bool SWThreadHandle::Unpause()
+{
+ if (m_state != Thread_Paused)
+ return false;
+
+ m_state = Thread_Running;
+
+ return true;
+}
+
+bool SWThreadHandle::WaitForThread()
+{
+ return false;
+}
+
+SWThreadHandle::SWThreadHandle(IThreadCreator *parent, const ThreadParams *p, IThread *thread) :
+ m_state(Thread_Paused), m_params(*p), m_parent(parent), pThread(thread)
+{
+}
+
+IThread *SWThreadHandle::GetThread()
+{
+ return pThread;
+}