1.1 --- a/core/thread/ThreadWorker.cpp Fri Jul 11 06:51:21 2008 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,320 +0,0 @@
1.4 -/**
1.5 - * vim: set ts=4 :
1.6 - * =============================================================================
1.7 - * SourceMod
1.8 - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
1.9 - * =============================================================================
1.10 - *
1.11 - * This program is free software; you can redistribute it and/or modify it under
1.12 - * the terms of the GNU General Public License, version 3.0, as published by the
1.13 - * Free Software Foundation.
1.14 - *
1.15 - * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 - * details.
1.19 - *
1.20 - * You should have received a copy of the GNU General Public License along with
1.21 - * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 - *
1.23 - * As a special exception, AlliedModders LLC gives you permission to link the
1.24 - * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 - * by the Valve Corporation. You must obey the GNU General Public License in
1.27 - * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 - * this exception to all derivative works. AlliedModders LLC defines further
1.29 - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 - * or <http://www.sourcemod.net/license.php>.
1.31 - *
1.32 - * Version: $Id$
1.33 - */
1.34 -
1.35 -#include "ThreadWorker.h"
1.36 -
1.37 -ThreadWorker::ThreadWorker(IThreadWorkerCallbacks *hooks) : BaseWorker(hooks),
1.38 - m_Threader(NULL),
1.39 - m_QueueLock(NULL),
1.40 - m_StateLock(NULL),
1.41 - m_PauseSignal(NULL),
1.42 - m_AddSignal(NULL),
1.43 - me(NULL),
1.44 - m_think_time(DEFAULT_THINK_TIME_MS)
1.45 -{
1.46 - m_state = Worker_Invalid;
1.47 -}
1.48 -
1.49 -ThreadWorker::ThreadWorker(IThreadWorkerCallbacks *hooks, IThreader *pThreader, unsigned int thinktime) :
1.50 - BaseWorker(hooks),
1.51 - m_Threader(pThreader),
1.52 - m_QueueLock(NULL),
1.53 - m_StateLock(NULL),
1.54 - m_PauseSignal(NULL),
1.55 - m_AddSignal(NULL),
1.56 - me(NULL),
1.57 - m_think_time(thinktime)
1.58 -{
1.59 - if (m_Threader)
1.60 - {
1.61 - m_state = Worker_Stopped;
1.62 - } else {
1.63 - m_state = Worker_Invalid;
1.64 - }
1.65 -}
1.66 -
1.67 -ThreadWorker::~ThreadWorker()
1.68 -{
1.69 - if (m_state != Worker_Stopped || m_state != Worker_Invalid)
1.70 - {
1.71 - Stop(true);
1.72 - }
1.73 -
1.74 - if (m_ThreadQueue.size())
1.75 - {
1.76 - Flush(true);
1.77 - }
1.78 -}
1.79 -
1.80 -void ThreadWorker::OnTerminate(IThreadHandle *pHandle, bool cancel)
1.81 -{
1.82 - //we don't particularly care
1.83 - return;
1.84 -}
1.85 -
1.86 -void ThreadWorker::RunThread(IThreadHandle *pHandle)
1.87 -{
1.88 - WorkerState this_state = Worker_Running;
1.89 - size_t num;
1.90 -
1.91 - if (m_pHooks)
1.92 - {
1.93 - m_pHooks->OnWorkerStart(this);
1.94 - }
1.95 -
1.96 - while (true)
1.97 - {
1.98 - /**
1.99 - * Check number of items in the queue
1.100 - */
1.101 - m_StateLock->Lock();
1.102 - this_state = m_state;
1.103 - m_StateLock->Unlock();
1.104 - if (this_state != Worker_Stopped)
1.105 - {
1.106 - m_QueueLock->Lock();
1.107 - num = m_ThreadQueue.size();
1.108 - if (!num)
1.109 - {
1.110 - /**
1.111 - * if none, wait for an item
1.112 - */
1.113 - m_Waiting = true;
1.114 - m_QueueLock->Unlock();
1.115 - /* first check if we should end again */
1.116 - if (this_state == Worker_Stopped)
1.117 - {
1.118 - break;
1.119 - }
1.120 - m_AddSignal->Wait();
1.121 - m_Waiting = false;
1.122 - } else {
1.123 - m_QueueLock->Unlock();
1.124 - }
1.125 - }
1.126 - m_StateLock->Lock();
1.127 - this_state = m_state;
1.128 - m_StateLock->Unlock();
1.129 - if (this_state != Worker_Running)
1.130 - {
1.131 - if (this_state == Worker_Paused || this_state == Worker_Stopped)
1.132 - {
1.133 - //wait until the lock is cleared.
1.134 - if (this_state == Worker_Paused)
1.135 - {
1.136 - m_PauseSignal->Wait();
1.137 - }
1.138 - if (this_state == Worker_Stopped)
1.139 - {
1.140 - //if we're supposed to flush cleanrly,
1.141 - // run all of the remaining frames first.
1.142 - if (!m_FlushType)
1.143 - {
1.144 - while (m_ThreadQueue.size())
1.145 - {
1.146 - RunFrame();
1.147 - }
1.148 - }
1.149 - break;
1.150 - }
1.151 - }
1.152 - }
1.153 - /**
1.154 - * Run the frame.
1.155 - */
1.156 - RunFrame();
1.157 -
1.158 - /**
1.159 - * wait in between threads if specified
1.160 - */
1.161 - if (m_think_time)
1.162 - {
1.163 - m_Threader->ThreadSleep(m_think_time);
1.164 - }
1.165 - }
1.166 -
1.167 - if (m_pHooks)
1.168 - {
1.169 - m_pHooks->OnWorkerStop(this);
1.170 - }
1.171 -}
1.172 -
1.173 -SWThreadHandle *ThreadWorker::PopThreadFromQueue()
1.174 -{
1.175 - if (m_state <= Worker_Stopped && !m_QueueLock)
1.176 - {
1.177 - return NULL;
1.178 - }
1.179 -
1.180 - SWThreadHandle *swt;
1.181 - m_QueueLock->Lock();
1.182 - swt = BaseWorker::PopThreadFromQueue();
1.183 - m_QueueLock->Unlock();
1.184 -
1.185 - return swt;
1.186 -}
1.187 -
1.188 -void ThreadWorker::AddThreadToQueue(SWThreadHandle *pHandle)
1.189 -{
1.190 - if (m_state <= Worker_Stopped)
1.191 - {
1.192 - return;
1.193 - }
1.194 -
1.195 - m_QueueLock->Lock();
1.196 - BaseWorker::AddThreadToQueue(pHandle);
1.197 - if (m_Waiting)
1.198 - {
1.199 - m_AddSignal->Signal();
1.200 - }
1.201 - m_QueueLock->Unlock();
1.202 -}
1.203 -
1.204 -WorkerState ThreadWorker::GetStatus(unsigned int *threads)
1.205 -{
1.206 - WorkerState state;
1.207 -
1.208 - m_StateLock->Lock();
1.209 - state = BaseWorker::GetStatus(threads);
1.210 - m_StateLock->Unlock();
1.211 -
1.212 - return state;
1.213 -}
1.214 -
1.215 -bool ThreadWorker::Start()
1.216 -{
1.217 - if (m_state == Worker_Invalid)
1.218 - {
1.219 - if (m_Threader == NULL)
1.220 - {
1.221 - return false;
1.222 - }
1.223 - } else if (m_state != Worker_Stopped) {
1.224 - return false;
1.225 - }
1.226 -
1.227 - m_Waiting = false;
1.228 - m_QueueLock = m_Threader->MakeMutex();
1.229 - m_StateLock = m_Threader->MakeMutex();
1.230 - m_PauseSignal = m_Threader->MakeEventSignal();
1.231 - m_AddSignal = m_Threader->MakeEventSignal();
1.232 - m_state = Worker_Running;
1.233 - ThreadParams pt;
1.234 - pt.flags = Thread_Default;
1.235 - pt.prio = ThreadPrio_Normal;
1.236 - me = m_Threader->MakeThread(this, &pt);
1.237 -
1.238 - return true;
1.239 -}
1.240 -
1.241 -bool ThreadWorker::Stop(bool flush_cancel)
1.242 -{
1.243 - if (m_state == Worker_Invalid || m_state == Worker_Stopped)
1.244 - {
1.245 - return false;
1.246 - }
1.247 -
1.248 - WorkerState oldstate;
1.249 -
1.250 - //set new state
1.251 - m_StateLock->Lock();
1.252 - oldstate = m_state;
1.253 - m_state = Worker_Stopped;
1.254 - m_FlushType = flush_cancel;
1.255 - m_StateLock->Unlock();
1.256 -
1.257 - if (oldstate == Worker_Paused)
1.258 - {
1.259 - Unpause();
1.260 - } else {
1.261 - m_QueueLock->Lock();
1.262 - if (m_Waiting)
1.263 - {
1.264 - m_AddSignal->Signal();
1.265 - }
1.266 - m_QueueLock->Unlock();
1.267 - }
1.268 -
1.269 - me->WaitForThread();
1.270 - //destroy it
1.271 - me->DestroyThis();
1.272 - //flush all remaining events
1.273 - Flush(true);
1.274 -
1.275 - //free mutex locks
1.276 - m_QueueLock->DestroyThis();
1.277 - m_StateLock->DestroyThis();
1.278 - m_PauseSignal->DestroyThis();
1.279 - m_AddSignal->DestroyThis();
1.280 -
1.281 - //invalidizzle
1.282 - m_QueueLock = NULL;
1.283 - m_StateLock = NULL;
1.284 - m_PauseSignal = NULL;
1.285 - m_AddSignal = NULL;
1.286 - me = NULL;
1.287 -
1.288 - return true;
1.289 -}
1.290 -
1.291 -bool ThreadWorker::Pause()
1.292 -{
1.293 - if (m_state != Worker_Running)
1.294 - {
1.295 - return false;
1.296 - }
1.297 -
1.298 - m_StateLock->Lock();
1.299 - m_state = Worker_Paused;
1.300 - m_StateLock->Unlock();
1.301 -
1.302 - return true;
1.303 -}
1.304 -
1.305 -
1.306 -bool ThreadWorker::Unpause()
1.307 -{
1.308 - if (m_state != Worker_Paused)
1.309 - {
1.310 - return false;
1.311 - }
1.312 -
1.313 - m_StateLock->Lock();
1.314 - m_state = Worker_Running;
1.315 - m_StateLock->Unlock();
1.316 - m_PauseSignal->Signal();
1.317 - if (m_Waiting)
1.318 - {
1.319 - m_AddSignal->Signal();
1.320 - }
1.321 -
1.322 - return true;
1.323 -}