nux-0.9.46
|
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, &mut_attr); 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 pthread_mutexattr_t mut_attr; 00118 mutable pthread_mutex_t m_lock; 00119 }; 00120 00122 00127 class NScopeLock 00128 { 00129 public: 00131 00135 NScopeLock (NCriticalSection *CriticalSectionObject) 00136 : m_CriticalSectionObject (CriticalSectionObject) 00137 { 00138 nuxAssert (m_CriticalSectionObject); 00139 m_CriticalSectionObject->Lock(); 00140 } 00141 00143 00146 ~NScopeLock (void) 00147 { 00148 nuxAssert (m_CriticalSectionObject); 00149 m_CriticalSectionObject->Unlock(); 00150 } 00151 00152 private: 00154 00157 NScopeLock (void); 00158 00160 00163 NScopeLock (const NScopeLock &ScopeLockObject); 00164 00166 00169 NScopeLock &operator= (const NScopeLock &ScopeLockObject) 00170 { 00171 return *this; 00172 } 00173 00175 00178 NCriticalSection *m_CriticalSectionObject; 00179 }; 00180 00181 class NThreadLocalStorage 00182 { 00183 public: 00184 enum 00185 { 00186 NbTLS = 128, 00187 InvalidTLS = 0xFFFFFFFF 00188 }; 00189 00190 typedef void (*TLS_ShutdownCallback) (); 00191 00192 static BOOL m_TLSUsed[NbTLS]; 00193 static __thread void *m_TLSIndex[NbTLS]; 00194 static TLS_ShutdownCallback m_TLSCallbacks[NbTLS]; 00195 00196 static void Initialize(); 00197 static void Shutdown(); 00198 static BOOL RegisterTLS (t_u32 index, TLS_ShutdownCallback shutdownCallback); 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 inlGetThreadLocalStorage(name) GetTLS_##name() 00249 #define inlSetThreadLocalStorage(name, value) SetTLS_##name(value) 00250 00251 #ifdef POP_CHECK_THREADS 00252 #define nuxAssertInsideThread(threadtype) nuxAssert( inlGetThreadLocalStorage(ThreadType) == threadtype) 00253 #define nuxAssertInsideThread2(threadtype1, threadtype2) nuxAssert( inlGetThreadLocalStorage(ThreadType) == threadtype1 || popGetThreadLocalData(ThreadType) == threadtype2) 00254 #define nuxAssertNotInsideThread(threadtype) nuxAssert( inlGetThreadLocalStorage(ThreadType) != threadtype) 00255 #else 00256 #define nuxAssertInsideThread(threadtype) ((void) 0) 00257 #define nuxAssertInsideThread2(threadtype1, threadtype2) ((void) 0) 00258 #define nuxAssertNotInsideThread(threadtype) ((void) 0) 00259 #endif 00260 00261 typedef enum 00262 { 00263 THREADINIT, 00264 THREADRUNNING, 00265 THREADSUSPENDED, 00266 THREADSTOP, 00267 THREAD_START_ERROR, 00268 THREAD_STOP_ERROR, 00269 THREAD_SUSPEND_ERROR, 00270 THREAD_RESUME_ERROR, 00271 } ThreadState; 00272 00273 // http://www.codeguru.com/cpp/misc/misc/threadsprocesses/article.php/c3793/ 00274 00275 typedef void* (*ThreadRoutineFunc) (void *); 00276 00277 class NThread 00278 { 00279 NUX_DECLARE_ROOT_OBJECT_TYPE (NThread); 00280 public: 00284 NThread(); 00285 00292 NThread (ThreadRoutineFunc lpExternalRoutine); 00293 00300 virtual ~NThread(); 00301 00307 virtual ThreadState Start ( void *arg = NULL ); 00308 00315 virtual ThreadState Stop ( bool bForceKill = false ); 00316 00317 ThreadState Suspend(); 00318 ThreadState Resume(); 00319 ThreadState ResumeStart(); 00320 ThreadState ResumeExit(); 00321 00327 t_u32 GetExitCode() const; 00328 00334 void Attach ( ThreadRoutineFunc lpThreadFunc ) 00335 { 00336 m_pThreadFunc = lpThreadFunc; 00337 } 00338 00345 void Detach ( void ) 00346 { 00347 m_pThreadFunc = NThread::EntryPoint; 00348 } 00349 00350 t_u32 GetThreadId(); 00351 00352 00353 ThreadState GetThreadState() const; 00354 void SetThreadState (ThreadState state); 00355 00356 protected: 00357 volatile ThreadState m_ThreadState; 00358 00372 static void *EntryPoint (void *); 00373 00381 virtual t_u32 Run (void* /* arg */) 00382 { 00383 return m_ThreadCtx.m_dwExitCode; 00384 } 00385 00395 virtual bool ThreadCtor() 00396 { 00397 return true; 00398 } 00399 00409 virtual bool ThreadDtor() 00410 { 00411 return true; 00412 } 00413 00414 private: 00426 class NThreadContext 00427 { 00428 public: 00429 NThreadContext () 00430 : m_pUserData (NULL) 00431 , m_pParent (NULL) 00432 , m_dwExitCode (0) 00433 { 00434 memset (&m_ThreadAttribute, 0, sizeof (m_ThreadAttribute)); 00435 memset (&m_dwTID, 0, sizeof (m_dwTID)); 00436 } 00437 00438 /* 00439 * Attributes Section 00440 */ 00441 public: 00442 pthread_attr_t m_ThreadAttribute; 00443 pthread_t m_dwTID; // The Thread ID 00444 void *m_pUserData; // The user data pointer 00445 void *m_pParent; // The this pointer of the parent NThread object 00446 t_u32 m_dwExitCode; // The Exit Code of the thread 00447 }; 00448 00452 protected: 00456 NThreadContext m_ThreadCtx; // The Thread Context member 00457 ThreadRoutineFunc m_pThreadFunc; // The Worker Thread Function Pointer 00458 }; 00459 00460 } 00461 00462 #endif // NTHREADGNU_H 00463