nux-0.9.48

NuxCore/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 (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