2
* GPAC - Multimedia Framework C SDK
4
* Copyright (c) Jean Le Feuvre 2000-2005
7
* This file is part of GPAC / common tools sub-project
9
* GPAC is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU Lesser General Public License as published by
11
* the Free Software Foundation; either version 2, or (at your option)
14
* GPAC is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU Lesser General Public License for more details.
19
* You should have received a copy of the GNU Lesser General Public
20
* License along with this library; see the file COPYING. If not, write to
21
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
25
#include <gpac/thread.h>
29
typedef HANDLE TH_HANDLE ;
32
/*********************************************************************
33
OS-Specific Thread Object
34
**********************************************************************/
41
/* the thread procedure */
42
u32 (*Run)(void *param);
45
GF_Semaphore *_signal;
48
GF_Thread *gf_th_new()
50
GF_Thread *tmp = malloc(sizeof(GF_Thread));
51
memset(tmp, 0, sizeof(GF_Thread));
52
tmp->status = GF_THREAD_STATUS_STOP;
56
DWORD WINAPI RunThread(void *ptr)
59
GF_Thread *t = (GF_Thread *)ptr;
61
/* Signal the caller */
62
if (! t->_signal) goto exit;
64
t->status = GF_THREAD_STATUS_RUN;
66
gf_sema_notify(t->_signal, 1);
68
ret = t->Run(t->args);
71
t->status = GF_THREAD_STATUS_DEAD;
75
GF_Err gf_th_run(GF_Thread *t, u32 (*Run)(void *param), void *param)
78
if (!t || t->Run || t->_signal) return GF_BAD_PARAM;
81
t->_signal = gf_sema_new(1, 0);
83
t->threadH = CreateThread(NULL, t->stackSize, &(RunThread), (void *)t, 0, &id);
84
if (t->threadH == NULL) {
85
t->status = GF_THREAD_STATUS_DEAD;
88
/*wait for the child function to call us - do NOT return bedfore, otherwise the thread status would
90
gf_sema_wait(t->_signal);
91
gf_sema_del(t->_signal);
97
/* Stops a thread. If Destroy is not 0, thread is destroyed DANGEROUS as no cleanup */
98
void Thread_Stop(GF_Thread *t, Bool Destroy)
100
if (gf_th_status(t) == GF_THREAD_STATUS_RUN) {
103
TerminateThread(t->threadH, dw);
106
WaitForSingleObject(t->threadH, INFINITE);
109
t->status = GF_THREAD_STATUS_DEAD;
112
void gf_th_stop(GF_Thread *t)
117
void gf_th_del(GF_Thread *t)
120
if (t->threadH) CloseHandle(t->threadH);
124
/*damn WinCE, threading scheduling is just a pain*/
125
void gf_th_set_priority(GF_Thread *t, s32 priority)
127
// SetThreadPriority(t ? t->threadH : GetCurrentThread(), priority);
130
u32 gf_th_status(GF_Thread *t)
139
return ((u32) GetCurrentThreadId());
143
/*********************************************************************
144
OS-Specific Mutex Object
145
**********************************************************************/
149
/* We filter recursive calls (1 thread calling Lock several times in a row only locks
150
ONCE the mutex. Holder is the current ThreadID of the mutex holder*/
151
u32 Holder, HolderCount;
155
GF_Mutex *gf_mx_new()
157
GF_Mutex *tmp = malloc(sizeof(GF_Mutex));
158
if (!tmp) return NULL;
159
memset(tmp, 0, sizeof(GF_Mutex));
161
tmp->hMutex = CreateMutex(NULL, FALSE, NULL);
169
void gf_mx_del(GF_Mutex *mx)
171
CloseHandle(mx->hMutex);
175
void gf_mx_v(GF_Mutex *mx)
181
if (caller != mx->Holder) return;
183
assert(mx->HolderCount > 0);
184
mx->HolderCount -= 1;
186
if (mx->HolderCount == 0) {
187
ReleaseMutex(mx->hMutex);
192
u32 gf_mx_p(GF_Mutex *mx)
198
if (caller == mx->Holder) {
199
mx->HolderCount += 1;
203
switch (WaitForSingleObject(mx->hMutex, INFINITE)) {
214
Bool gf_mx_try_lock(GF_Mutex *mx)
219
if (caller == mx->Holder) {
220
mx->HolderCount += 1;
224
/*wait for 1 ms (I can't figure out from MS doc if 0 timeout only "tests the state" or also lock the mutex ... */
225
switch (WaitForSingleObject(mx->hMutex, 1)) {
237
/*********************************************************************
238
OS-Specific Semaphore Object
239
**********************************************************************/
240
struct __tag_semaphore
246
GF_Semaphore *gf_sema_new(u32 MaxCount, u32 InitCount)
248
GF_Semaphore *tmp = malloc(sizeof(GF_Semaphore));
252
if (!tmp) return NULL;
254
tmp->hSemaphore = CreateSemaphore(NULL, InitCount, MaxCount, NULL);
255
if (!tmp->hSemaphore) {
262
void gf_sema_del(GF_Semaphore *sm)
264
CloseHandle(sm->hSemaphore);
268
u32 gf_sema_notify(GF_Semaphore *sm, u32 NbRelease)
274
ReleaseSemaphore(sm->hSemaphore, NbRelease, &prevCount);
278
void gf_sema_wait(GF_Semaphore *sm)
280
WaitForSingleObject(sm->hSemaphore, INFINITE);
283
Bool gf_sema_wait_for(GF_Semaphore *sm, u32 TimeOut)
285
if (WaitForSingleObject(sm->hSemaphore, TimeOut) == WAIT_TIMEOUT) return 0;