Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members

RageThreads.h

Go to the documentation of this file.
00001 #ifndef RAGE_THREADS_H 00002 #define RAGE_THREADS_H 00003 00004 struct ThreadSlot; 00005 class RageTimer; 00006 class RageThread 00007 { 00008 ThreadSlot *m_pSlot; 00009 CString name; 00010 00011 static bool m_bSystemSupportsTLS; 00012 00013 public: 00014 RageThread(); 00015 ~RageThread(); 00016 00017 void SetName( const CString &n ) { name = n; } 00018 void Create( int (*fn)(void *), void *data ); 00019 00020 /* For crash handlers: kill or suspend all threads (except for 00021 * the running one) immediately. */ 00022 static void HaltAllThreads( bool Kill=false ); 00023 00024 /* If HaltAllThreads was called (with Kill==false), resume. */ 00025 static void ResumeAllThreads(); 00026 00027 static uint64_t GetCurrentThreadID(); 00028 00029 static const char *GetCurThreadName(); 00030 static const char *GetThreadNameByID( uint64_t iID ); 00031 static bool EnumThreadIDs( int n, uint64_t &iID ); 00032 int Wait(); 00033 bool IsCreated() const { return m_pSlot != NULL; } 00034 00035 /* A system can define HAVE_TLS, indicating that it can compile thread_local 00036 * code, but an individual environment may not actually have functional TLS. 00037 * If this returns false, thread_local variables are considered undefined. */ 00038 static bool GetSupportsTLS() { return m_bSystemSupportsTLS; } 00039 00040 static void SetSupportsTLS( bool b ) { m_bSystemSupportsTLS = b; } 00041 }; 00042 00043 namespace Checkpoints 00044 { 00045 void LogCheckpoints( bool yes=true ); 00046 void SetCheckpoint( const char *file, int line, const char *message ); 00047 void GetLogs( char *pBuf, int iSize, const char *delim ); 00048 }; 00049 00050 #define CHECKPOINT (Checkpoints::SetCheckpoint(__FILE__, __LINE__, NULL)) 00051 #define CHECKPOINT_M(m) (Checkpoints::SetCheckpoint(__FILE__, __LINE__, m)) 00052 00053 /* Mutex class that follows the behavior of Windows mutexes: if the same 00054 * thread locks the same mutex twice, we just increase a refcount; a mutex 00055 * is considered unlocked when the refcount reaches zero. This is more 00056 * convenient, though much slower on some archs. (We don't have any tightly- 00057 * coupled threads, so that's OK.) */ 00058 class MutexImpl; 00059 class RageMutex 00060 { 00061 public: 00062 CString GetName() const { return m_sName; } 00063 void SetName( const CString &s ) { m_sName = s; } 00064 virtual void Lock(); 00065 virtual bool TryLock(); 00066 virtual void Unlock(); 00067 virtual bool IsLockedByThisThread() const; 00068 00069 RageMutex( CString name ); 00070 virtual ~RageMutex(); 00071 00072 protected: 00073 MutexImpl *m_pMutex; 00074 CString m_sName; 00075 00076 int m_UniqueID; 00077 00078 uint64_t m_LockedBy; 00079 int m_LockCnt; 00080 00081 void MarkLockedMutex(); 00082 }; 00083 00084 /* Lock a mutex on construction, unlock it on destruction. Helps for functions 00085 * with more than one return path. */ 00086 class LockMutex 00087 { 00088 RageMutex &mutex; 00089 00090 const char *file; 00091 int line; 00092 float locked_at; 00093 bool locked; 00094 00095 public: 00096 LockMutex(RageMutex &mut, const char *file, int line); 00097 LockMutex(RageMutex &mut): mutex(mut), file(NULL), line(-1), locked_at(-1), locked(true) { mutex.Lock(); } 00098 ~LockMutex(); 00099 LockMutex(LockMutex &cpy): mutex(cpy.mutex), file(NULL), line(-1), locked_at(cpy.locked_at), locked(true) { mutex.Lock(); } 00100 00101 /* Unlock the mutex (before this would normally go out of scope). This can 00102 * only be called once. */ 00103 void Unlock(); 00104 }; 00105 00106 00107 /* Double-abstracting __LINE__ lets us append it to other text, to generate 00108 * locally unique variable names. (Otherwise we get "LocalLock__LINE__".) I'm 00109 * not sure why this works, but it does, in both VC and GCC. */ 00110 00111 #if 0 00112 #ifdef DEBUG 00113 /* Use the debug version, which logs if something holds a lock for a long time. 00114 * __FUNCTION__ is nonstandard, but both GCC and VC support it; VC doesn't 00115 * support the standard, __func__. */ 00116 #define LockMutL2(m, l) LockMutex LocalLock ## l (m, __FUNCTION__, __LINE__) 00117 #else 00118 #define LockMutL2(m, l) LockMutex LocalLock ## l (m) 00119 #endif 00120 00121 #define LockMutL(m, l) LockMutL2(m, l) 00122 #define LockMut(m) LockMutL(m, __LINE__) 00123 #endif 00124 00125 /* Gar. It works in VC7, but not VC6, so for now this can only be used once 00126 * per function. If you need more than that, declare LockMutexes yourself. 00127 * Also, VC6 doesn't support __FUNCTION__. */ 00128 #if _MSC_VER < 1300 /* VC6, not VC7 */ 00129 #define LockMut(m) LockMutex LocalLock(m, __FILE__, __LINE__) 00130 #else 00131 #define LockMut(m) LockMutex LocalLock(m, __FUNCTION__, __LINE__) 00132 #endif 00133 00134 class EventImpl; 00135 class RageEvent: public RageMutex 00136 { 00137 public: 00138 RageEvent( CString name ); 00139 ~RageEvent(); 00140 00141 /* 00142 * If pTimeout is non-NULL, the event will be automatically signalled at the given 00143 * time. Note that implementing this timeout is optional; not all archs support it. 00144 * If false is returned, the wait timed out (and the mutex is locked, as if the 00145 * event had been signalled). 00146 */ 00147 bool Wait( RageTimer *pTimeout = NULL ); 00148 void Signal(); 00149 void Broadcast(); 00150 00151 private: 00152 EventImpl *m_pEvent; 00153 }; 00154 00155 class SemaImpl; 00156 class RageSemaphore 00157 { 00158 public: 00159 RageSemaphore( CString sName, int iInitialValue = 0 ); 00160 ~RageSemaphore(); 00161 00162 CString GetName() const { return m_sName; } 00163 int GetValue() const; 00164 void Post(); 00165 void Wait( bool bFailOnTimeout=true ); 00166 bool TryWait(); 00167 00168 private: 00169 SemaImpl *m_pSema; 00170 CString m_sName; 00171 }; 00172 00173 #endif 00174 00175 /* 00176 * Copyright (c) 2001-2004 Glenn Maynard 00177 * All rights reserved. 00178 * 00179 * Permission is hereby granted, free of charge, to any person obtaining a 00180 * copy of this software and associated documentation files (the 00181 * "Software"), to deal in the Software without restriction, including 00182 * without limitation the rights to use, copy, modify, merge, publish, 00183 * distribute, and/or sell copies of the Software, and to permit persons to 00184 * whom the Software is furnished to do so, provided that the above 00185 * copyright notice(s) and this permission notice appear in all copies of 00186 * the Software and that both the above copyright notice(s) and this 00187 * permission notice appear in supporting documentation. 00188 * 00189 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00190 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00191 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF 00192 * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS 00193 * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT 00194 * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 00195 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 00196 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 00197 * PERFORMANCE OF THIS SOFTWARE. 00198 */

Generated on Thu Jan 27 20:57:29 2005 for StepMania by doxygen 1.3.7