|
Odamex
Setting the Standard in Multiplayer Doom
|
00001 // Emacs style mode select -*- C++ -*- 00002 //----------------------------------------------------------------------------- 00003 // 00004 // $Id: oda_thread.h 2164 2011-05-07 20:10:55Z hypereye $ 00005 // 00006 // Copyright (C) 2006-2010 by The Odamex Team. 00007 // 00008 // This program is free software; you can redistribute it and/or 00009 // modify it under the terms of the GNU General Public License 00010 // as published by the Free Software Foundation; either version 2 00011 // of the License, or (at your option) any later version. 00012 // 00013 // This program is distributed in the hope that it will be useful, 00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 // GNU General Public License for more details. 00017 // 00018 // DESCRIPTION: 00019 // AG_Thread C++ Wrapper 00020 // 00021 // AUTHORS: 00022 // Michael Wood (mwoodj at huntsvegas dot org) 00023 // 00024 //----------------------------------------------------------------------------- 00025 00026 #ifndef _ODA_THREAD_H 00027 #define _ODA_THREAD_H 00028 00029 #ifndef CALL_MEMBER_FN 00030 #define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember)) 00031 #endif 00032 00039 namespace agOdalaunch { 00040 00041 const size_t NUM_THREADS = 5; 00042 00043 class ODA_ThreadBase {}; 00044 00045 typedef void *(ODA_ThreadBase::*THREAD_FUNC_PTR)(void *); 00046 00047 typedef struct 00048 { 00049 ODA_ThreadBase *classPtr; 00050 THREAD_FUNC_PTR funcPtr; 00051 AG_Mutex *rMutex; 00052 bool *running; 00053 void *arg; 00054 } ThreadArg_t; 00055 00056 class ODA_Thread 00057 { 00058 public: 00059 ODA_Thread() { m_Running = false; m_RMutex = NULL; } 00060 00061 int Create(ODA_ThreadBase *classPtr, THREAD_FUNC_PTR funcPtr, void *arg) 00062 { 00063 if(m_RMutex) 00064 { 00065 if(IsRunning()) 00066 return -1; 00067 else 00068 AG_ThreadJoin(m_Thread, NULL); 00069 } 00070 else 00071 { 00072 m_RMutex = new AG_Mutex; 00073 AG_MutexInit(m_RMutex); 00074 } 00075 00076 ThreadArg_t *targ = new(ThreadArg_t); 00077 00078 m_Running = true; 00079 00080 targ->classPtr = classPtr; 00081 targ->funcPtr = funcPtr; 00082 targ->rMutex = m_RMutex; 00083 targ->running = &m_Running; 00084 targ->arg = arg; 00085 00086 return AG_ThreadCreate(&m_Thread, CallThreadFunc, targ); 00087 } 00088 00089 static void *CallThreadFunc(void *arg) 00090 { 00091 ThreadArg_t *targ = (ThreadArg_t *)arg; 00092 00093 if(targ && targ->classPtr && targ->rMutex && targ->running) 00094 { 00095 void *ret; 00096 00097 ret = CALL_MEMBER_FN(*targ->classPtr, targ->funcPtr)(targ->arg); 00098 00099 AG_MutexLock(targ->rMutex); 00100 *targ->running = false; 00101 AG_MutexUnlock(targ->rMutex); 00102 00103 delete targ; 00104 00105 AG_ThreadExit(ret); 00106 } 00107 00108 AG_ThreadExit(NULL); 00109 00110 return NULL; 00111 } 00112 00113 bool IsRunning() 00114 { 00115 bool val; 00116 00117 if(!m_RMutex) 00118 return false; 00119 00120 AG_MutexLock(m_RMutex); 00121 val = m_Running; 00122 AG_MutexUnlock(m_RMutex); 00123 00124 return val; 00125 } 00126 00127 void Cancel() { AG_ThreadCancel(m_Thread); } 00128 int Join(void **exitVal) { return AG_ThreadJoin(m_Thread, exitVal); } 00129 int Kill(int signal) { return AG_ThreadKill(m_Thread, signal); } 00130 00131 private: 00132 AG_Thread m_Thread; 00133 AG_Mutex *m_RMutex; 00134 bool m_Running; 00135 }; 00136 00137 } // namespace 00138 00139 #endif