nux-1.14.0
ThreadGNU.cpp
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 #include "NuxCore.h"
00024 
00025 
00026 namespace nux
00027 {
00028 
00029   t_int NThreadSafeCounter::Increment()
00030   {
00031     return __sync_add_and_fetch (&m_Counter, 1);
00032   }
00033 
00034   t_int NThreadSafeCounter::Decrement()
00035   {
00036     return __sync_add_and_fetch (&m_Counter, -1);
00037   }
00038 
00039   t_int NThreadSafeCounter::Set (t_int i)
00040   {
00041     return __sync_lock_test_and_set (&m_Counter, i);
00042   }
00043 
00044   t_int NThreadSafeCounter::GetValue() const
00045   {
00046     return m_Counter;
00047   }
00048 
00049   t_int NThreadSafeCounter::operator ++ ()
00050   {
00051     return Increment();
00052   }
00053 
00054   t_int NThreadSafeCounter::operator -- ()
00055   {
00056     return Decrement();
00057   }
00058 
00059   t_bool NThreadSafeCounter::operator == (t_int i)
00060   {
00061     return (m_Counter == i);
00062   }
00063 
00064   __thread void *NThreadLocalStorage::m_TLSIndex[NThreadLocalStorage::NbTLS];
00065   BOOL NThreadLocalStorage::m_TLSUsed[NThreadLocalStorage::NbTLS];
00066   NThreadLocalStorage::TLS_ShutdownCallback  NThreadLocalStorage::m_TLSCallbacks[NThreadLocalStorage::NbTLS];
00067 
00068   BOOL NThreadLocalStorage::RegisterTLS(t_u32 index, NThreadLocalStorage::TLS_ShutdownCallback shutdownCallback)
00069   {
00070     NUX_RETURN_VALUE_IF_FALSE(index < NThreadLocalStorage::NbTLS, FALSE);
00071     NUX_RETURN_VALUE_IF_TRUE(m_TLSUsed[index], TRUE); // already registered
00072 
00073     m_TLSUsed[index]  = TRUE;
00074     m_TLSCallbacks[index] =  shutdownCallback;
00075     return TRUE;
00076   }
00077 
00078   BOOL NThreadLocalStorage::UnRegisterTLS (t_u32 index)
00079   {
00080     NUX_RETURN_VALUE_IF_FALSE(index < NThreadLocalStorage::NbTLS, FALSE);
00081     NUX_RETURN_VALUE_IF_FALSE(m_TLSUsed[index], FALSE);
00082 
00083     m_TLSUsed[index]  = FALSE;
00084     m_TLSCallbacks[index] =  NULL;
00085     m_TLSIndex[index]  = NULL;
00086 
00087     return TRUE;
00088   }
00089 
00090   void NThreadLocalStorage::Initialize()
00091   {
00092     Memset (m_TLSUsed, 0, sizeof (m_TLSUsed) );
00093 
00094     for (t_u32 i = 0; i < NThreadLocalStorage::NbTLS; i++)
00095     {
00096       // Fill the array with invalid values
00097       m_TLSIndex[i] = 0;
00098     }
00099   }
00100 
00101   void NThreadLocalStorage::Shutdown()
00102   {
00103     ThreadShutdown();
00104   }
00105 
00106   void NThreadLocalStorage::ThreadInit()
00107   {
00108   }
00109 
00110   void NThreadLocalStorage::ThreadShutdown()
00111   {
00112     TLS_ShutdownCallback *callback = m_TLSCallbacks;
00113 
00114     for (t_u32 i = 0; i < NThreadLocalStorage::NbTLS; ++i, ++callback)
00115     {
00116       if (*callback)
00117       {
00118         (**callback) ();
00119       }
00120     }
00121   }
00122 
00123   NUX_IMPLEMENT_ROOT_OBJECT_TYPE (NThread);
00124 
00125   NThread::NThread()
00126     :   m_ThreadState (THREADINIT)
00127   {
00128     m_pThreadFunc = NThread::EntryPoint; // Can call Detach() also.
00129   }
00130 
00131   NThread::NThread (ThreadRoutineFunc lpExternalRoutine)
00132   {
00133     Attach (lpExternalRoutine);
00134   }
00135 
00136   NThread::~NThread()
00137   {
00138     if (m_ThreadCtx.m_dwTID)
00139       pthread_detach (m_ThreadCtx.m_dwTID);
00140   }
00141 
00142   ThreadState NThread::Start ( void *arg )
00143   {
00144     m_ThreadCtx.m_pUserData = arg;
00145     int ret = pthread_create (&m_ThreadCtx.m_dwTID,
00146                               NULL,
00147                               m_pThreadFunc,
00148                               this);
00149 
00150     if (ret != 0)
00151     {
00152       nuxDebugMsg (TEXT ("[NThread::Start] Cannot start thread.") );
00153       m_ThreadState = THREAD_START_ERROR;
00154       return m_ThreadState;
00155     }
00156 
00157     return m_ThreadState;
00158   }
00159 
00160   ThreadState NThread::Stop ( bool bForceKill )
00161   {
00162     int ret = pthread_detach (m_ThreadCtx.m_dwTID);
00163 
00164     if (ret != 0)
00165     {
00166       nuxDebugMsg (TEXT ("[NThread::Stop] Cannot detach thread.") );
00167       m_ThreadState = THREAD_STOP_ERROR;
00168       return m_ThreadState;
00169     }
00170 
00171     m_ThreadState = THREADSTOP;
00172     return m_ThreadState;
00173   }
00174 
00175   ThreadState NThread::Suspend()
00176   {
00177     m_ThreadState = THREADSUSPENDED;
00178     return m_ThreadState;
00179   }
00180 
00181   ThreadState NThread::Resume()
00182   {
00183     return m_ThreadState;
00184   }
00185 
00186 // go from suspended to thread start
00187   ThreadState NThread::ResumeStart()
00188   {
00189     m_ThreadState = THREADINIT;
00190     return m_ThreadState;
00191   }
00192 
00193 // go from suspended to thread exit
00194   ThreadState NThread::ResumeExit()
00195   {
00196     m_ThreadState = THREADSTOP;
00197     return m_ThreadState;
00198   }
00199 
00200   void *NThread::EntryPoint (void *pArg)
00201   {
00202     NThread *pParent = reinterpret_cast<NThread *> (pArg);
00203 
00204     if (pParent == 0)
00205     {
00206       nuxDebugMsg (TEXT ("[NThread::EntryPoint] Invalid pointer. The thread will exit.") );
00207       return 0;
00208     }
00209 
00210     if (!pParent->ThreadCtor() )
00211     {
00212       // return another message saying the thread could not execute due to error in ThreadCtor;
00213     }
00214 
00215     pParent->Run ( pParent->m_ThreadCtx.m_pUserData );
00216 
00217     pParent->ThreadDtor();
00218     return 0;
00219   }
00220 
00221   t_u32 NThread::GetExitCode() const
00222   {
00223     return m_ThreadCtx.m_dwExitCode;
00224   }
00225 
00226   t_u32 NThread::GetThreadId()
00227   {
00228     return (t_u32) m_ThreadCtx.m_dwTID;
00229   }
00230 
00231   ThreadState NThread::GetThreadState() const
00232   {
00233     return m_ThreadState;
00234   }
00235 
00236   void NThread::SetThreadState (ThreadState state)
00237   {
00238     m_ThreadState = state;
00239   }
00240 
00241 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends