nux-1.16.0
|
00001 /* 00002 * Copyright 2010 Inalogic® Inc. 00003 * 00004 * This program is free software: you can redistribute it and/or modify it 00005 * under the terms of the GNU Lesser General Public License, as 00006 * published by the Free Software Foundation; either version 2.1 or 3.0 00007 * of the License. 00008 * 00009 * This program is distributed in the hope that it will be useful, but 00010 * WITHOUT ANY WARRANTY; without even the implied warranties of 00011 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR 00012 * PURPOSE. See the applicable version of the GNU Lesser General Public 00013 * License for more details. 00014 * 00015 * You should have received a copy of both the GNU Lesser General Public 00016 * License along with this program. If not, see <http://www.gnu.org/licenses/> 00017 * 00018 * Authored by: Jay Taoko <jaytaoko@inalogic.com> 00019 * 00020 */ 00021 00022 00023 #ifndef NTHREADGNU_H 00024 #define NTHREADGNU_H 00025 00026 #include "ObjectType.h" 00027 00028 /*#include <sys/ppu_thread.h> 00029 #include <sys/synchronization.h> 00030 #include <sys/sys_time.h> 00031 #include <sys/timer.h> 00032 #include <sys/process.h>*/ 00033 00034 namespace nux 00035 { 00036 class NThreadSafeCounter 00037 { 00038 public: 00039 NThreadSafeCounter() 00040 { 00041 m_Counter = 0; 00042 } 00043 NThreadSafeCounter (t_int i) 00044 { 00045 m_Counter = i; 00046 } 00047 t_int Increment(); 00048 t_int Decrement(); 00049 t_int Set (t_int i); 00050 t_int GetValue() const; 00051 t_int operator ++ (); 00052 t_int operator -- (); 00053 t_bool operator == (t_int i); 00054 private: 00055 t_int m_Counter; 00056 }; 00057 00058 class NCriticalSection 00059 { 00060 public: 00062 00065 NCriticalSection() 00066 { 00067 pthread_mutex_init (&m_lock, 0); 00068 } 00069 00071 00074 ~NCriticalSection() 00075 { 00076 pthread_mutex_destroy (&m_lock); 00077 } 00078 00080 00084 void Lock() const 00085 { 00086 // NUXTODO: There are issues with locking on Linux when starting nux in embedded mode.,. 00087 #ifndef NUX_OS_LINUX 00088 pthread_mutex_lock (&m_lock); 00089 #endif 00090 } 00091 00093 00097 void Unlock() const 00098 { 00099 // NUXTODO: There are issues with locking on Linux when starting nux in embedded mode.,. 00100 #ifndef NUX_OS_LINUX 00101 pthread_mutex_unlock (&m_lock); 00102 #endif 00103 } 00104 00105 private: 00107 00110 NCriticalSection (const NCriticalSection &); 00112 00115 NCriticalSection &operator= (const NCriticalSection &); 00116 00117 mutable pthread_mutex_t m_lock; 00118 }; 00119 00121 00126 class NScopeLock 00127 { 00128 public: 00130 00134 NScopeLock (NCriticalSection *CriticalSectionObject) 00135 : m_CriticalSectionObject (CriticalSectionObject) 00136 { 00137 nuxAssert (m_CriticalSectionObject); 00138 m_CriticalSectionObject->Lock(); 00139 } 00140 00142 00145 ~NScopeLock (void) 00146 { 00147 nuxAssert (m_CriticalSectionObject); 00148 m_CriticalSectionObject->Unlock(); 00149 } 00150 00151 private: 00153 00156 NScopeLock (void); 00157 00159 00162 NScopeLock (const NScopeLock &ScopeLockObject); 00163 00165 00168 NScopeLock &operator= (const NScopeLock &ScopeLockObject) 00169 { 00170 return *this; 00171 } 00172 00174 00177 NCriticalSection *m_CriticalSectionObject; 00178 }; 00179 00180 class NThreadLocalStorage 00181 { 00182 public: 00183 enum 00184 { 00185 NbTLS = 128, 00186 InvalidTLS = 0xFFFFFFFF 00187 }; 00188 00189 typedef void (*TLS_ShutdownCallback) (); 00190 00191 static BOOL m_TLSUsed[NbTLS]; 00192 static __thread void *m_TLSIndex[NbTLS]; 00193 static TLS_ShutdownCallback m_TLSCallbacks[NbTLS]; 00194 00195 static void Initialize(); 00196 static void Shutdown(); 00197 static BOOL RegisterTLS (t_u32 index, TLS_ShutdownCallback shutdownCallback); 00198 static BOOL UnRegisterTLS (unsigned int index); 00199 static void ThreadInit(); 00200 static void ThreadShutdown(); 00201 00202 public: 00203 00204 template<class T> static inline T GetData (t_u32 index) 00205 { 00206 nuxAssert (sizeof (T) <= sizeof (size_t) ); 00207 nuxAssert (index < NbTLS); 00208 nuxAssert (m_TLSUsed[index]); 00209 00210 // T and (unsigned long) can be of different sizes 00211 // but this limits the use of GetData to classes without copy constructors 00212 union 00213 { 00214 T t; 00215 void *v; 00216 } temp; 00217 temp.v = m_TLSIndex[index]; 00218 return temp.t; 00219 } 00220 00221 template<class T> static inline void SetData (t_u32 index, T value) 00222 { 00223 nuxAssert (sizeof (T) <= sizeof (size_t) ); 00224 nuxAssert (index < NbTLS); 00225 nuxAssert (m_TLSUsed[index]); 00226 00227 // T and (unsigned long) can be of different sizes 00228 // but this limits the use of GetData to classes without copy constructors 00229 union 00230 { 00231 T t; 00232 void *v; 00233 } temp; 00234 temp.t = value; 00235 m_TLSIndex[index] = temp.v; 00236 } 00237 }; 00238 00239 #define inlDeclareThreadLocalStorage(type, index, name) \ 00240 struct ThreadLocalStorageDef##name { enum Const { Index = index}; };\ 00241 inline type GetTLS_##name() { return nux::NThreadLocalStorage::GetData<type>(ThreadLocalStorageDef##name::Index); }\ 00242 inline void SetTLS_##name(type value) { nux::NThreadLocalStorage::SetData<type>(ThreadLocalStorageDef##name::Index, value); } 00243 00244 #define inlRegisterThreadLocalIndex(index, name, shutdownCallback) \ 00245 nuxVerifyExpr(index == ThreadLocalStorageDef##name::Index); \ 00246 nuxVerifyExpr(nux::NThreadLocalStorage::RegisterTLS(index, shutdownCallback)) 00247 00248 #define inlUnRegisterThreadLocalIndex(name) \ 00249 nuxVerifyExpr(nux::NThreadLocalStorage::UnRegisterTLS(ThreadLocalStorageDef##name::Index)) 00250 00251 00252 #define inlGetThreadLocalStorage(name) GetTLS_##name() 00253 #define inlSetThreadLocalStorage(name, value) SetTLS_##name(value) 00254 00255 #ifdef POP_CHECK_THREADS 00256 #define nuxAssertInsideThread(threadtype) nuxAssert( inlGetThreadLocalStorage(ThreadType) == threadtype) 00257 #define nuxAssertInsideThread2(threadtype1, threadtype2) nuxAssert( inlGetThreadLocalStorage(ThreadType) == threadtype1 || popGetThreadLocalData(ThreadType) == threadtype2) 00258 #define nuxAssertNotInsideThread(threadtype) nuxAssert( inlGetThreadLocalStorage(ThreadType) != threadtype) 00259 #else 00260 #define nuxAssertInsideThread(threadtype) ((void) 0) 00261 #define nuxAssertInsideThread2(threadtype1, threadtype2) ((void) 0) 00262 #define nuxAssertNotInsideThread(threadtype) ((void) 0) 00263 #endif 00264 00265 typedef enum 00266 { 00267 THREADINIT, 00268 THREADRUNNING, 00269 THREADSUSPENDED, 00270 THREADSTOP, 00271 THREAD_START_ERROR, 00272 THREAD_STOP_ERROR, 00273 THREAD_SUSPEND_ERROR, 00274 THREAD_RESUME_ERROR, 00275 } ThreadState; 00276 00277 // http://www.codeguru.com/cpp/misc/misc/threadsprocesses/article.php/c3793/ 00278 00279 typedef void* (*ThreadRoutineFunc) (void *); 00280 00281 class NThread 00282 { 00283 NUX_DECLARE_ROOT_OBJECT_TYPE (NThread); 00284 public: 00288 NThread(); 00289 00296 NThread (ThreadRoutineFunc lpExternalRoutine); 00297 00304 virtual ~NThread(); 00305 00311 virtual ThreadState Start ( void *arg = NULL ); 00312 00319 virtual ThreadState Stop ( bool bForceKill = false ); 00320 00321 ThreadState Suspend(); 00322 ThreadState Resume(); 00323 ThreadState ResumeStart(); 00324 ThreadState ResumeExit(); 00325 00331 t_u32 GetExitCode() const; 00332 00338 void Attach ( ThreadRoutineFunc lpThreadFunc ) 00339 { 00340 m_pThreadFunc = lpThreadFunc; 00341 } 00342 00349 void Detach ( void ) 00350 { 00351 m_pThreadFunc = NThread::EntryPoint; 00352 } 00353 00354 t_u32 GetThreadId(); 00355 00356 00357 ThreadState GetThreadState() const; 00358 void SetThreadState (ThreadState state); 00359 00360 protected: 00361 volatile ThreadState m_ThreadState; 00362 00376 static void *EntryPoint (void *); 00377 00385 virtual t_u32 Run (void* /* arg */) 00386 { 00387 return m_ThreadCtx.m_dwExitCode; 00388 } 00389 00399 virtual bool ThreadCtor() 00400 { 00401 return true; 00402 } 00403 00413 virtual bool ThreadDtor() 00414 { 00415 return true; 00416 } 00417 00418 private: 00430 class NThreadContext 00431 { 00432 public: 00433 NThreadContext () 00434 : m_pUserData (NULL) 00435 , m_pParent (NULL) 00436 , m_dwExitCode (0) 00437 { 00438 memset (&m_ThreadAttribute, 0, sizeof (m_ThreadAttribute)); 00439 memset (&m_dwTID, 0, sizeof (m_dwTID)); 00440 } 00441 00442 /* 00443 * Attributes Section 00444 */ 00445 public: 00446 pthread_attr_t m_ThreadAttribute; 00447 pthread_t m_dwTID; // The Thread ID 00448 void *m_pUserData; // The user data pointer 00449 void *m_pParent; // The this pointer of the parent NThread object 00450 t_u32 m_dwExitCode; // The Exit Code of the thread 00451 }; 00452 00456 protected: 00460 NThreadContext m_ThreadCtx; // The Thread Context member 00461 ThreadRoutineFunc m_pThreadFunc; // The Worker Thread Function Pointer 00462 }; 00463 00464 } 00465 00466 #endif // NTHREADGNU_H 00467