00001 #ifndef _MERCURY_THREADS_H 00002 #define _MERCURY_THREADS_H 00003 00004 #include "MercuryString.h" 00005 00006 #if !defined(WIN32) 00007 #if !defined(_EE) 00008 #include <pthread.h> 00009 #else 00010 #include <kernel.h> 00011 #endif 00012 #endif 00013 00015 class MercuryThread 00016 { 00017 public: 00018 MercuryThread(); 00019 MercuryThread( const MString &name ); 00020 ~MercuryThread(); 00021 00023 int Create( void * (*fn)(void *), void *data ); 00024 00026 int Wait( long lMilliseconds = 10000000 ); 00027 00029 int Halt( bool kill = true ); 00030 00032 int Resume( ); 00033 00035 void Close( ); 00036 private: 00037 MString m_name; 00038 00039 #if defined(WIN32) 00040 void * m_thread; 00041 #else 00042 #if defined(_EE) 00043 s32 m_thread; 00044 #else 00045 pthread_t m_thread; 00046 #endif 00047 #endif 00048 00049 }; 00050 00052 class MercuryMutex 00053 { 00054 public: 00055 MercuryMutex( ); 00056 MercuryMutex( const MString &name ); 00057 ~MercuryMutex(); 00058 00060 int Wait( long lMilliseconds = 0xFFFFFF ); 00061 00063 int UnLock( ); 00064 00066 int Open( ); 00067 00069 int Close( ); 00070 private: 00071 MString m_name; 00072 00073 #if defined( WIN32 ) 00074 void * m_mutex; 00075 #else 00076 #if defined( _EE ) 00077 s32 m_mutex; 00078 #else 00079 pthread_mutex_t m_mutex; 00080 #endif 00081 #endif 00082 }; 00083 00084 //http://www.ddj.com/dept/cpp/184403766 00085 //has some very good ideas in terms of threads and volatile variables 00086 00088 template <typename T> 00089 class MLockPtr 00090 { 00091 public: 00092 MLockPtr(volatile const T& obj, const MercuryMutex& mutex) 00093 :m_obj(const_cast<T*>(&obj)), m_mutex(const_cast<MercuryMutex*>(&mutex)) 00094 { 00095 m_mutex->Wait(); 00096 } 00097 ~MLockPtr() { m_mutex->UnLock(); } 00098 inline T& operator*() { return *m_obj; } 00099 inline T* operator->() { return m_obj; } 00100 private: 00101 T* m_obj; 00102 MercuryMutex* m_mutex; 00103 //Disallow 00104 MLockPtr(const MLockPtr&); 00105 MLockPtr& operator=(const MLockPtr&); 00106 }; 00107 00108 //Utility functions for conditional threading 00109 // The purpose of this is to allow you to conditionally define whether or not a mutex 00110 // exists, allowing one to benchmark the overhead of threading as well as removing 00111 // functionality if it is known that the system will not be using threads. 00112 00113 #if !defined( NOT_THREADSAFE ) 00114 00115 #define COND_MUTEX( x ) \ 00116 MercuryMutex x 00117 00118 #define SETUP_MUTEX( x ) \ 00119 x.Open(); \ 00120 x.UnLock() 00121 00122 #define LOCK_MUTEX( x ) \ 00123 x.Wait() 00124 00125 #define UNLOCK_MUTEX( x ) \ 00126 x.UnLock() 00127 00128 #else 00129 00130 #define COND_MUTEX( x ) 00131 #define SETUP_MUTEX( x ) 00132 #define LOCK_MUTEX( x ) 00133 #define UNLOCK_MUTEX( x ) 00134 00135 #endif 00136 00137 #endif 00138