nux-1.14.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 #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 }