Back to index

nux  3.0.0
ThreadGNU.h
Go to the documentation of this file.
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 (int i)
00044     {
00045       m_Counter = i;
00046     }
00047     int Increment();
00048     int Decrement();
00049     int Set (int i);
00050     int GetValue() const;
00051     int operator ++ ();
00052     int operator -- ();
00053     bool operator == (int i);
00054   private:
00055     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 (unsigned int 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 (unsigned int 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 (unsigned int 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   enum ThreadState
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   };
00276 
00277   enum ThreadWaitTimeout
00278   {
00279     THREAD_WAIT_TIMEOUT_NONE    = 0,
00280     THREAD_WAIT_TIMEOUT_FOREVER = 0xFFFFFFFF,
00281   };
00282 
00283   enum ThreadWaitResult
00284   {
00285     THREAD_WAIT_RESULT_COMPLETED  = 0,
00286     THREAD_WAIT_RESULT_ABANDONED  = 1,
00287     THREAD_WAIT_RESULT_TIMEOUT    = 2,
00288     THREAD_WAIT_RESULT_FAILED     = 3,
00289   };
00290 
00291 // http://www.codeguru.com/cpp/misc/misc/threadsprocesses/article.php/c3793/
00292 
00293   typedef void* (*ThreadRoutineFunc) (void *);
00294 
00295   class NThread
00296   {
00297     NUX_DECLARE_ROOT_OBJECT_TYPE (NThread);
00298   public:
00302     NThread();
00303 
00310     NThread (ThreadRoutineFunc lpExternalRoutine);
00311 
00318     virtual ~NThread();
00319 
00325     virtual ThreadState Start ( void *arg = NULL );
00326 
00333     virtual ThreadState Stop ( bool bForceKill = false );
00334 
00335     ThreadState Suspend();
00336     ThreadState Resume();
00337     ThreadState ResumeStart();
00338     ThreadState ResumeExit();
00339 
00345     unsigned int GetExitCode() const;
00346 
00352     void Attach ( ThreadRoutineFunc lpThreadFunc )
00353     {
00354       m_pThreadFunc = lpThreadFunc;
00355     }
00356 
00363     void  Detach ( void )
00364     {
00365       m_pThreadFunc = NThread::EntryPoint;
00366     }
00367 
00368     pthread_t GetPThread();
00369 
00370     ThreadState GetThreadState() const;
00371     void SetThreadState (ThreadState state);
00372 
00383     static ThreadWaitResult JoinThread(NThread *thread, unsigned int milliseconds);
00384 
00385   protected:
00386     volatile ThreadState m_ThreadState;
00387 
00401     static void *EntryPoint (void *);
00402 
00410     virtual int Run (void* /* arg */)
00411     {
00412       return m_ThreadCtx.m_dwExitCode;
00413     }
00414 
00424     virtual bool ThreadCtor()
00425     {
00426       return true;
00427     }
00428 
00438     virtual bool ThreadDtor()
00439     {
00440       return true;
00441     }
00442 
00443   private:
00455     class NThreadContext
00456     {
00457     public:
00458       NThreadContext ()
00459         : m_pUserData (NULL)
00460         , m_pParent (NULL)
00461         , m_dwExitCode (0)
00462       {
00463         memset (&m_ThreadAttribute, 0, sizeof (m_ThreadAttribute));
00464         memset (&m_dwTID, 0, sizeof (m_dwTID));
00465       }
00466 
00467       /*
00468       *       Attributes Section
00469       */
00470     public:
00471       pthread_attr_t  m_ThreadAttribute;
00472       pthread_t       m_dwTID;             // The Thread ID
00473       void           *m_pUserData;         // The user data pointer
00474       void           *m_pParent;           // The this pointer of the parent NThread object
00475       unsigned int            m_dwExitCode;         // The Exit Code of the thread
00476     };
00477 
00481   protected:
00485     NThreadContext                 m_ThreadCtx;  //     The Thread Context member
00486     ThreadRoutineFunc       m_pThreadFunc;       //     The Worker Thread Function Pointer
00487   };
00488 
00489 }
00490 
00491 #endif // NTHREADGNU_H
00492