add HLH_Ref
[HLH_utils.git] / HLH_Thread.cpp
blobffd609195b56380aee329ccf5e38c69bd9f493ca
1 /*******************************************************************************
2 * File Name : HLH_Thread.cpp
3 *
4 * Author : Henry He
5 * Created Time : 2009-10-8 11:18:18
6 * Description :
7 ******************************************************************************/
10 /*******************************************************************************
11 * Desc : Includes Files
12 ******************************************************************************/
14 #include <sys/time.h>
15 #include <time.h>
17 #include "HLH_utils/HLH_Thread.h"
21 /*******************************************************************************
22 * Desc : Macro Definations
23 ******************************************************************************/
26 /*******************************************************************************
27 * Desc : Type Definations
28 ******************************************************************************/
31 /*******************************************************************************
32 * Desc : Global Variables
33 ******************************************************************************/
36 /*******************************************************************************
37 * Desc : File Variables
38 ******************************************************************************/
44 /******************************************************************************
45 * Desc : Member Functions
46 ******************************************************************************/
51 /******************************************************************************
52 * Func : HLH_Thread::HLH_Thread
53 * Desc : Constructor of HLH_Thread
54 * Args : NONE
55 * Outs : NONE
56 ******************************************************************************/
57 HLH_Thread::HLH_Thread ()
59 m_zhmRunMutex.Init ();
60 m_zhmContinueMutex.Init ();
61 m_zhmContinueMutex2.Init ();
63 m_pvRetval = NULL;
64 m_bRunning = false;
65 m_bStopping = false;
69 /******************************************************************************
70 * Func : HLH_Thread::~HLH_Thread
71 * Desc : Deconstructor of HLH_Thread
72 * Args : NONE
73 * Outs : NONE
74 ******************************************************************************/
75 HLH_Thread::~HLH_Thread ()
77 Kill();
81 /******************************************************************************
82 * Func : HLH_Thread::Start
83 * Desc : Start a thread calling \c ztfThreadFunc (pvThreadParam)
84 * Args : ztfThreadFunc Function called in this thread
85 * Outs : If success return 0, otherwise return error code.
86 ******************************************************************************/
87 int HLH_Thread::Start (ThreadFunc ztfThreadFunc, void *pvThreadParam)
89 int nRetval;
91 // Force TheThread () to wait before call m_ztfThreadFunc ():
92 // TheThread () will set m_bRunning
93 // and wait Start () to confirm before it call m_ztfThreadFunc ()
94 m_zhmContinueMutex.Lock ();
96 // Check if already running
97 m_zhmRunMutex.Lock ();
98 if (m_bRunning) {
99 m_zhmRunMutex.Unlock ();
100 return HLH_THREAD_ERR_ALREADY_RUNNING;
102 m_zhmRunMutex.Unlock ();
104 // Set Thread Function
105 m_ztfThreadFunc = ztfThreadFunc;
106 m_pvThreadParam = pvThreadParam;
108 pthread_attr_t attr;
109 pthread_attr_init (&attr);
110 pthread_attr_setdetachstate (&attr,PTHREAD_CREATE_DETACHED);
112 nRetval = pthread_create (&m_zpThreadId, &attr, TheThread, this);
113 pthread_attr_destroy (&attr);
114 if (nRetval != 0) {
115 m_zhmContinueMutex.Unlock ();
116 return HLH_THREAD_ERR_CANT_START_THREAD;
119 /* Wait until 'm_bRunning' is set */
121 m_zhmRunMutex.Lock ();
122 while (!m_bRunning)
124 m_zhmRunMutex.Unlock ();
126 struct timespec tsReq;
127 struct timespec tsRem;
129 tsReq.tv_sec = 0;
130 tsReq.tv_nsec = 1000000;
131 nanosleep (&tsReq, &tsRem);
133 m_zhmRunMutex.Lock();
135 m_zhmRunMutex.Unlock();
137 // Unlock to let TheThread () continue and call m_ztfThreadFunc ()
138 m_zhmContinueMutex.Unlock();
140 // Make sure that m_ztfThreadFunc () has call ThreadStarted ()
141 m_zhmContinueMutex2.Lock();
142 m_zhmContinueMutex2.Unlock();
144 return 0;
148 /******************************************************************************
149 * Func : HLH_Thread::Stop
150 * Desc : Stop this thread
151 * Args : NONE
152 * Outs : If success return 0, otherwise return error code
153 ******************************************************************************/
154 int HLH_Thread::Stop ()
156 struct timespec tsReq;
157 struct timespec tsRem;
160 m_zhmRunMutex.Lock ();
162 // If the thread isn't running, abort
163 if (!m_bRunning)
165 m_zhmRunMutex.Unlock();
166 return HLH_THREAD_ERR_NOT_RUNNING;
169 if (m_bStopping) {
170 m_zhmRunMutex.Unlock();
171 return HLH_THREAD_ERR_ALREADY_STOPPING;
174 // Send stop request to m_ztfThreadFunc ()
175 m_bStopping = true;
177 m_zhmRunMutex.Unlock ();
179 // Wait until 'm_bRunning' is unset
181 m_zhmRunMutex.Lock ();
182 while (m_bRunning)
184 m_zhmRunMutex.Unlock ();
186 tsReq.tv_sec = 0;
187 tsReq.tv_nsec = 1000000;
189 // Wait for a while
190 nanosleep (&tsReq, &tsRem);
192 m_zhmRunMutex.Lock ();
194 m_zhmRunMutex.Unlock ();
196 return 0;
199 /******************************************************************************
200 * Func : HLH_Thread::Kill
201 * Desc : Kill this thread
202 * Args : NONE
203 * Outs : If success return 0, otherwise return error code.
204 ******************************************************************************/
205 int HLH_Thread::Kill ()
207 m_zhmRunMutex.Lock ();
209 if (!m_bRunning)
211 m_zhmRunMutex.Unlock();
212 return HLH_THREAD_ERR_NOT_RUNNING;
215 pthread_cancel (m_zpThreadId);
217 m_bRunning = false;
218 m_bStopping = false;
219 m_pvRetval = NULL;
221 m_zhmRunMutex.Unlock();
223 return 0;
226 /******************************************************************************
227 * Func : HLH_Thread::IsRunning
228 * Desc : Whether this thread is running
229 * Args : NONE
230 * Outs : If running return true, otherwise return false.
231 ******************************************************************************/
232 bool HLH_Thread::IsRunning ()
234 bool bRunning;
236 m_zhmRunMutex.Lock();
237 bRunning = m_bRunning;
238 m_zhmRunMutex.Unlock();
240 return bRunning;
244 /******************************************************************************
245 * Func : HLH_Thread::IsStopping
246 * Desc : Whether this thread is requested to stop
247 * Args : NONE
248 * Outs : If requested to stop return true, otherwise return false
249 ******************************************************************************/
250 bool HLH_Thread::IsStopping ()
252 bool bStopping;
254 m_zhmRunMutex.Lock();
255 bStopping = m_bStopping;
256 m_zhmRunMutex.Unlock();
258 return bStopping;
262 /******************************************************************************
263 * Func : HLH_Thread::GetReturnValue
264 * Desc : Get return value of this thread
265 * Args : NONE
266 * Outs : return return value of this thread in last run
267 ******************************************************************************/
268 void * HLH_Thread::GetReturnValue ()
270 void *pvVal;
272 m_zhmRunMutex.Lock ();
273 pvVal = m_pvRetval;
274 m_zhmRunMutex.Unlock ();
276 return pvVal;
279 /******************************************************************************
280 * Func : HLH_Thread::TheThread
281 * Desc : Thread callback function of this thread
282 * Args : pvThis pointer to this instance
283 * Outs : Always return NULL.
284 ******************************************************************************/
285 void * HLH_Thread::TheThread (void *pvThis)
287 HLH_Thread *pzhThread;
288 void *pvRet;
290 ASSERT (pvThis != NULL);
291 pzhThread = (HLH_Thread *)pvThis;
293 pzhThread->m_zhmContinueMutex2.Lock ();
295 // Identify that this thread is running
296 pzhThread->m_zhmRunMutex.Lock ();
297 pzhThread->m_bRunning = true;
298 pzhThread->m_bStopping = false;
299 pzhThread->m_zhmRunMutex.Unlock ();
301 // Wait until Start () confirm that m_bRunning is set
302 pzhThread->m_zhmContinueMutex.Lock ();
303 pzhThread->m_zhmContinueMutex.Unlock ();
305 // pzhThread->m_zhmContinueMutex2 will be unlock here
306 pvRet = pzhThread->m_ztfThreadFunc ( *pzhThread, pzhThread->m_pvThreadParam );
308 // Identify that this thread is stopped
309 pzhThread->m_zhmRunMutex.Lock ();
310 pzhThread->m_bRunning = false;
311 pzhThread->m_bStopping = false;
312 pzhThread->m_pvRetval = pvRet;
313 pzhThread->m_zhmRunMutex.Unlock ();
315 return NULL;
318 /******************************************************************************
319 * Func : HLH_Thread::ThreadStarted
320 * Desc : Called by m_ztfThreadFunc () to notify \c Start ()
321 * that \c m_ztfThreadFunc () started
322 * Args : NONE
323 * Outs : NONE
324 ******************************************************************************/
325 void HLH_Thread::ThreadStarted ()
327 m_zhmContinueMutex2.Unlock ();