1 /*
2  *			GPAC - Multimedia Framework C SDK
3  *
4  *			Authors: Jean Le Feuvre
5  *			Copyright (c) Telecom ParisTech 2000-2019
6  *					All rights reserved
7  *
8  *  This file is part of GPAC / common tools sub-project
9  *
10  *  GPAC is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU Lesser General Public License as published by
12  *  the Free Software Foundation; either version 2, or (at your option)
13  *  any later version.
14  *
15  *  GPAC is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU Lesser General Public License for more details.
19  *
20  *  You should have received a copy of the GNU Lesser General Public
21  *  License along with this library; see the file COPYING.  If not, write to
22  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  */
25 
26 #ifndef _GF_THREAD_H_
27 #define _GF_THREAD_H_
28 
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32 
33 /*!
34 \file <gpac/thread.h>
35 \brief Threading and Mutual Exclusion
36 */
37 
38 /*!
39 \addtogroup thr_grp
40 \brief Threading and Mutual Exclusion
41 
42 This section documents the threading of the GPAC framework. These provide an easy way to implement
43 safe multithreaded tools.
44 
45 Available tools are thread, mutex and semaphore
46 
47 \defgroup thread_grp Thread
48 \ingroup thr_grp
49 \defgroup mutex_grp Mutex
50 \ingroup thr_grp
51 \defgroup sema_grp Semaphore
52 \ingroup thr_grp
53 */
54 
55 /*!
56 \addtogroup thread_grp
57 \brief Thread processing
58 
59 The thread object allows executing some code independently of the main process of your application.
60 @{
61 */
62 
63 #include <gpac/tools.h>
64 
65 
66  //atomic ref_count++ / ref_count--
67 #if defined(WIN32) || defined(_WIN32_WCE)
68 #include <Windows.h>
69 #include <WinBase.h>
70 
71 #define safe_int_inc(__v) InterlockedIncrement((int *) (__v))
72 #define safe_int_dec(__v) InterlockedDecrement((int *) (__v))
73 
74 #define safe_int_add(__v, inc_val) InterlockedAdd((int *) (__v), inc_val)
75 #define safe_int_sub(__v, dec_val) InterlockedAdd((int *) (__v), -dec_val)
76 
77 #define safe_int64_add(__v, inc_val) InterlockedAdd64((LONG64 *) (__v), inc_val)
78 #define safe_int64_sub(__v, dec_val) InterlockedAdd64((LONG64 *) (__v), -dec_val)
79 
80 #else
81 
82 #define safe_int_inc(__v) __sync_add_and_fetch((int *) (__v), 1)
83 #define safe_int_dec(__v) __sync_sub_and_fetch((int *) (__v), 1)
84 
85 #define safe_int_add(__v, inc_val) __sync_add_and_fetch((int *) (__v), inc_val)
86 #define safe_int_sub(__v, dec_val) __sync_sub_and_fetch((int *) (__v), dec_val)
87 
88 #define safe_int64_add(__v, inc_val) __sync_add_and_fetch((int64_t *) (__v), inc_val)
89 #define safe_int64_sub(__v, dec_val) __sync_sub_and_fetch((int64_t *) (__v), dec_val)
90 #endif
91 
92 
93 /*!
94 \brief Thread states
95  *
96  *Indicates the execution status of a thread
97  */
98 enum
99 {
100 	/*! the thread has been initialized but is not started yet*/
101 	GF_THREAD_STATUS_STOP = 0,
102 	/*! the thread is running*/
103 	GF_THREAD_STATUS_RUN = 1,
104 	/*! the thread has exited its body function*/
105 	GF_THREAD_STATUS_DEAD = 2
106 };
107 
108 /*!
109 \brief abstracted thread object
110 */
111 typedef struct __tag_thread GF_Thread;
112 
113 /*!
114 \brief thread constructor
115 
116 Constructs a new thread object
117 \param name log name of the thread if any
118 \return new thread object
119  */
120 GF_Thread *gf_th_new(const char *name);
121 /*!
122 \brief thread destructor
123 
124 Kills the thread if running and destroys the object
125 \param th the thread object
126  */
127 void gf_th_del(GF_Thread *th);
128 
129 /*!
130 \brief thread run function callback
131 
132 The gf_thread_run type is the type for the callback of the \ref gf_thread_run function
133 \param par opaque user data
134 \return exit code of the thread, usually 1 for error and 0 if normal execution
135  */
136 typedef u32 (*gf_thread_run)(void *par);
137 
138 /*!
139 \brief thread execution
140 
141 Executes the thread with the given function
142 \note A thread may be run several times but cannot be run twice in the same time.
143 \param th the thread object
144 \param run the function this thread will call
145 \param par the argument to the function the thread will call
146 \return error if any
147  */
148 GF_Err gf_th_run(GF_Thread *th, gf_thread_run run, void *par);
149 /*!
150 \brief thread stopping
151 
152 Waits for the thread exit until return
153 \param th the thread object
154  */
155 void gf_th_stop(GF_Thread *th);
156 /*!
157 \brief thread status query
158 
159 Gets the thread status
160 \param th the thread object
161 \return thread status
162  */
163 u32 gf_th_status(GF_Thread *th);
164 
165 /*! thread priorities */
166 enum
167 {
168 	/*!Idle Priority*/
169 	GF_THREAD_PRIORITY_IDLE=0,
170 	/*!Less Idle Priority*/
171 	GF_THREAD_PRIORITY_LESS_IDLE,
172 	/*!Lowest Priority*/
173 	GF_THREAD_PRIORITY_LOWEST,
174 	/*!Low Priority*/
175 	GF_THREAD_PRIORITY_LOW,
176 	/*!Normal Priority (the default one)*/
177 	GF_THREAD_PRIORITY_NORMAL,
178 	/*!High Priority*/
179 	GF_THREAD_PRIORITY_HIGH,
180 	/*!Highest Priority*/
181 	GF_THREAD_PRIORITY_HIGHEST,
182 	/*!First real-time priority*/
183 	GF_THREAD_PRIORITY_REALTIME,
184 	/*!Last real-time priority*/
185 	GF_THREAD_PRIORITY_REALTIME_END=255
186 };
187 
188 /*!
189 \brief thread priority
190 
191 Sets the thread execution priority level.
192 \param th the thread object
193 \param priority the desired priority
194 \note this should be used with caution, especially use of real-time priorities.
195  */
196 void gf_th_set_priority(GF_Thread *th, s32 priority);
197 /*!
198 \brief current thread ID
199 
200 Gets the ID of the current thread the caller is in.
201 \return thread ID
202 */
203 u32 gf_th_id();
204 
205 #ifdef GPAC_CONFIG_ANDROID
206 /*! Register a function that will be called before pthread_exist is called */
207 GF_Err gf_register_before_exit_function(GF_Thread *t, u32 (*toRunBeforePthreadExit)(void *param));
208 
209 /*! Get the current Thread if any. May return NULL
210  */
211 GF_Thread * gf_th_current();
212 
213 #endif /* GPAC_CONFIG_ANDROID */
214 
215 /*! @} */
216 
217 /*!
218 \addtogroup mutex_grp
219 \brief Mutual exclusion
220 
221 The mutex object allows ensuring that portions of the code (typically access to variables) cannot be executed by two threads (or a thread and the main process) at the same time.
222 
223 @{
224 */
225 
226 /*!
227 \brief abstracted mutex object*/
228 typedef struct __tag_mutex GF_Mutex;
229 /*!
230 \brief mutex constructor
231 
232 Contructs a new mutex object
233 \param name log name of the thread if any
234 \return new mutex
235 */
236 GF_Mutex *gf_mx_new(const char *name);
237 /*!
238 \brief mutex denstructor
239 
240 Destroys a mutex object. This will wait for the mutex to be released if needed.
241 \param mx the mutex object
242 */
243 void gf_mx_del(GF_Mutex *mx);
244 /*!
245 \brief mutex locking
246 
247 Locks the mutex object, making sure that another thread locking this mutex cannot execute until the mutex is unlocked.
248 \param mx the mutex object
249 \return 1 if success, 0 if error locking the mutex (which should never happen)
250 */
251 u32 gf_mx_p(GF_Mutex *mx);
252 /*!
253 \brief mutex unlocking
254 
255 Unlocks the mutex object, allowing other threads waiting on this mutex to continue their execution
256 \param mx the mutex object
257 */
258 void gf_mx_v(GF_Mutex *mx);
259 /*!
260 \brief mutex non-blocking lock
261 
262 Attemps to lock the mutex object without blocking until the object is released.
263 \param mx the mutex object
264 \return GF_TRUE if the mutex has been successfully locked, in which case it shall then be unlocked, or GF_FALSE if the mutex is locked by another thread.
265 */
266 Bool gf_mx_try_lock(GF_Mutex *mx);
267 
268 /*!
269 \brief get mutex number of locks
270 
271 Returns the number of locks on the mutex if the caller thread is holding the mutex.
272 \param mx the mutex object
273 \return -1 if the mutex is not hold by the calling thread, or the number of locks (possibly 0) otherwise.
274  */
275 s32 gf_mx_get_num_locks(GF_Mutex *mx);
276 
277 /*! @} */
278 
279 /*!
280 \addtogroup sema_grp
281 \brief Semaphore
282 
283 
284 The semaphore object allows controling how portions of the code (typically access to variables) are
285  executed by two threads (or a thread and the main process) at the same time. The best image for a semaphore is a limited set
286  of money coins (always easy to understand hmm?). If no money is in the set, nobody can buy anything until a coin is put back in the set.
287  When the set is full, the money is wasted (call it "the bank"...).
288 
289 @{
290 */
291 
292 /*********************************************************************
293 					Semaphore Object
294 **********************************************************************/
295 /*!
296 \brief abstracted semaphore object
297 */
298 typedef struct __tag_semaphore GF_Semaphore;
299 /*!
300 \brief semaphore constructor
301 
302 Constructs a new semaphore object
303 \param MaxCount the maximum notification count of this semaphore
304 \param InitCount the initial notification count of this semaphore upon construction
305 \return the semaphore object
306  */
307 GF_Semaphore *gf_sema_new(u32 MaxCount, u32 InitCount);
308 /*!
309 \brief semaphore destructor
310 
311 Destructs the semaphore object. This will wait for the semaphore to be released if needed.
312 \param sm the semaphore object
313  */
314 void gf_sema_del(GF_Semaphore *sm);
315 /*!
316 \brief semaphore notification.
317 
318 Notifies the semaphore of a certain amount of releases.
319 \param sm the semaphore object
320 \param nb_rel sm the number of release to notify
321 \return GF_TRUE if success, GF_FALSE otherwise
322 */
323 Bool gf_sema_notify(GF_Semaphore *sm, u32 nb_rel);
324 /*!
325 \brief semaphore wait
326 
327 Waits for the semaphore to be accessible (eg, may wait an infinite time).
328 \param sm the semaphore object
329 \return GF_TRUE if successfull wait, GF_FALSE if wait failed
330 */
331 Bool gf_sema_wait(GF_Semaphore *sm);
332 /*!
333 \brief semaphore time wait
334 
335 Waits for a certain for the semaphore to be accessible, and returns when semaphore is accessible or wait time has passed.
336 \param sm the semaphore object
337 \param time_out the amount of time to wait for the release in milliseconds
338 \return returns 1 if the semaphore was released before the timeout, 0 if the semaphore is still not released after the timeout.
339 */
340 Bool gf_sema_wait_for(GF_Semaphore *sm, u32 time_out);
341 
342 
343 /*! @} */
344 
345 #ifdef __cplusplus
346 }
347 #endif
348 
349 
350 #endif		/*_GF_THREAD_H_*/
351 
352