⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_thread.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005 *					All rights reserved * *  This file is part of GPAC / common tools sub-project * *  GPAC is free software; you can redistribute it and/or modify *  it under the terms of the GNU Lesser General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. *    *  GPAC is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU Lesser General Public License for more details. *    *  You should have received a copy of the GNU Lesser General Public *  License along with this library; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  * */#include <gpac/thread.h>#if defined(WIN32) || defined(_WIN32_WCE)/*win32 threads*/#include <windows.h>typedef HANDLE TH_HANDLE;#else/*pthreads*/#include <sched.h>#include <pthread.h>#include <semaphore.h>typedef pthread_t TH_HANDLE ;#endif/*********************************************************************						OS-Specific Thread Object**********************************************************************/struct __tag_thread{	u32 status;	TH_HANDLE threadH;	u32 stackSize;	/* the thread procedure */	u32 (*Run)(void *param);	void *args;	/* lock for signal */	GF_Semaphore *_signal;};GF_Thread *gf_th_new(){	GF_Thread *tmp = malloc(sizeof(GF_Thread));	memset(tmp, 0, sizeof(GF_Thread));	tmp->status = GF_THREAD_STATUS_STOP;	return tmp;}#ifdef WIN32DWORD WINAPI RunThread(void *ptr){	DWORD ret = 0;#elsevoid *RunThread(void *ptr){	u32 ret = 0;#endif	GF_Thread *t = (GF_Thread *)ptr;	/* Signal the caller */	if (! t->_signal) goto exit;	t->status = GF_THREAD_STATUS_RUN;		gf_sema_notify(t->_signal, 1);	/* Run our thread */	ret = t->Run(t->args);exit:	t->status = GF_THREAD_STATUS_DEAD;	t->Run = NULL;#ifdef WIN32	CloseHandle(t->threadH);	t->threadH = NULL;	return ret;#else	pthread_exit((void *)0);	return (void *)ret;#endif}GF_Err gf_th_run(GF_Thread *t, u32 (*Run)(void *param), void *param){#ifdef WIN32	DWORD id;#else	pthread_attr_t att;#endif	if (!t || t->Run || t->_signal) return GF_BAD_PARAM;	t->Run = Run;	t->args = param;	t->_signal = gf_sema_new(1, 0);#ifdef WIN32	t->threadH = CreateThread(NULL,  t->stackSize, &(RunThread), (void *)t, 0, &id);	if (t->threadH == NULL) {#else	if ( pthread_attr_init(&att) != 0 ) return GF_IO_ERR;	pthread_attr_setdetachstate(&att, PTHREAD_CREATE_JOINABLE);	if ( pthread_create(&t->threadH, &att, RunThread, t) != 0 ) {#endif		t->status = GF_THREAD_STATUS_DEAD;		return GF_IO_ERR;	}	/*wait for the child function to call us - do NOT return before, otherwise the thread status would	be unknown*/ 		gf_sema_wait(t->_signal);	gf_sema_del(t->_signal);	t->_signal = NULL;	return GF_OK;}/* Stops a thread. If Destroy is not 0, thread is destroyed DANGEROUS as no cleanup */void Thread_Stop(GF_Thread *t, Bool Destroy){	if (gf_th_status(t) == GF_THREAD_STATUS_RUN) {#ifdef WIN32		if (Destroy) {			DWORD dw = 1;			TerminateThread(t->threadH, dw);			t->threadH = NULL;		} else {			WaitForSingleObject(t->threadH, INFINITE);					}#else		if (Destroy) {			pthread_cancel(t->threadH);			t->threadH = 0;		} else {			/*gracefully wait for Run to finish*/			pthread_join(t->threadH, NULL);					}#endif	}	t->status = GF_THREAD_STATUS_DEAD;}void gf_th_stop(GF_Thread *t){	Thread_Stop(t, 0);}void gf_th_del(GF_Thread *t){	Thread_Stop(t, 0);#ifdef WIN32	if (t->threadH) CloseHandle(t->threadH);#endif	free(t);}void gf_th_set_priority(GF_Thread *t, s32 priority){#ifdef WIN32	/*!! in WinCE, changin thread priority is extremely dangerous, it may freeze threads randomly !!*/#ifndef _WIN32_WCE	SetThreadPriority(t ? t->threadH : GetCurrentThread(), priority);#endif#else	struct sched_param s_par;	if (!t) return;	/* consider this as real-time priority */	if (priority > 200) {		s_par.sched_priority = priority - 200;		pthread_setschedparam(t->threadH, SCHED_RR, &s_par);	} else {		s_par.sched_priority = priority;		pthread_setschedparam(t->threadH, SCHED_OTHER, &s_par);	}#endif}u32 gf_th_status(GF_Thread *t){	if (!t) return 0;	return t->status;}u32 gf_th_id(){#ifdef WIN32	return ((u32) GetCurrentThreadId());#else	return ((u32) pthread_self());#endif}/*********************************************************************						OS-Specific Mutex Object**********************************************************************/struct __tag_mutex{#ifdef WIN32	HANDLE hMutex;#else	pthread_mutex_t hMutex;#endif	/* We filter recursive calls (1 thread calling Lock several times in a row only locks	ONCE the mutex. Holder is the current ThreadID of the mutex holder*/	u32 Holder, HolderCount;};GF_Mutex *gf_mx_new(){#ifndef WIN32	pthread_mutexattr_t attr;#endif	GF_Mutex *tmp = malloc(sizeof(GF_Mutex));	if (!tmp) return NULL;	memset(tmp, 0, sizeof(GF_Mutex));	#ifdef WIN32	tmp->hMutex = CreateMutex(NULL, FALSE, NULL);	if (!tmp->hMutex) {#else	pthread_mutexattr_init(&attr);	if ( pthread_mutex_init(&tmp->hMutex, &attr) != 0 ) {#endif		free(tmp);		return NULL;	}	return tmp;}void gf_mx_del(GF_Mutex *mx){#ifdef WIN32	CloseHandle(mx->hMutex);#else	pthread_mutex_destroy(&mx->hMutex);#endif	free(mx);}void gf_mx_v(GF_Mutex *mx){	u32 caller;	if (!mx) return;	caller = gf_th_id();	/*only if we own*/	assert(caller == mx->Holder);	if (caller != mx->Holder) return;	assert(mx->HolderCount > 0);	mx->HolderCount -= 1;	if (mx->HolderCount == 0) {		mx->Holder = 0;#ifdef WIN32		ReleaseMutex(mx->hMutex);#else		pthread_mutex_unlock(&mx->hMutex);#endif	}}u32 gf_mx_p(GF_Mutex *mx){	u32 caller;	if (!mx) return 0;	caller = gf_th_id();	if (caller == mx->Holder) {		mx->HolderCount += 1;		return 1;	}#ifdef WIN32	switch (WaitForSingleObject(mx->hMutex, INFINITE)) {	case WAIT_ABANDONED:	case WAIT_TIMEOUT:		return 0;	default:		mx->HolderCount = 1;		mx->Holder = caller;		return 1;	}#else	if (pthread_mutex_lock(&mx->hMutex) == 0 ) {		mx->Holder = caller;		mx->HolderCount = 1;		return 1;	}	assert(0);	return 0;#endif}Bool gf_mx_try_lock(GF_Mutex *mx){	u32 caller;	if (!mx) return 0;	caller = gf_th_id();	if (caller == mx->Holder) {		mx->HolderCount += 1;		return 1;	}#ifdef WIN32	/*wait for 1 ms (I can't figure out from MS doc if 0 timeout only "tests the state" or also lock the mutex ... */	switch (WaitForSingleObject(mx->hMutex, 1)) {	case WAIT_ABANDONED:	case WAIT_TIMEOUT:		return 0;	default:		mx->HolderCount = 1;		mx->Holder = caller;		return 1;	}#else	if (pthread_mutex_trylock(&mx->hMutex) == 0 ) {		mx->Holder = caller;		mx->HolderCount = 1;		return 1;	}	return 0;#endif}/*********************************************************************						OS-Specific Semaphore Object**********************************************************************/struct __tag_semaphore{#ifdef WIN32	HANDLE hSemaphore;#else	sem_t *hSemaphore;	sem_t SemaData;#if defined(__DARWIN__) || defined(__APPLE__)	const char *SemName;#endif#endif};GF_Semaphore *gf_sema_new(u32 MaxCount, u32 InitCount){	GF_Semaphore *tmp = malloc(sizeof(GF_Semaphore));	if (!tmp) return NULL;#if defined(WIN32)	tmp->hSemaphore = CreateSemaphore(NULL, InitCount, MaxCount, NULL);#elif defined(__DARWIN__) || defined(__APPLE__)	/* sem_init isn't supported on Mac OS X 10.3 & 10.4; it returns ENOSYS	To get around this, a NAMED semaphore needs to be used	sem_t *sem_open(const char *name, int oflag, ...);	http://users.evitech.fi/~hannuvl/ke04/reaaliaika_ohj/memmap_named_semaphores.c	*/	{		char semaName[40];		sprintf(semaName,"GPAC_SEM%d", (u32) tmp);		tmp->SemName = strdup(semaName);	}	tmp->hSemaphore = sem_open(tmp->SemName, O_CREAT, S_IRUSR|S_IWUSR, InitCount);#else	if (sem_init(&tmp->SemaData, 0, InitCount) < 0 ) {		free(tmp);		return NULL;	}	tmp->hSemaphore = &tmp->SemaData;#endif	if (!tmp->hSemaphore) {		free(tmp);		return NULL;	}	return tmp;}void gf_sema_del(GF_Semaphore *sm){#if defined(WIN32)	CloseHandle(sm->hSemaphore);#elif defined(__DARWIN__) || defined(__APPLE__)	sem_t *sema = sem_open(sm->SemName, 0);	sem_destroy(sema);	free(sm->SemName);#else	sem_destroy(sm->hSemaphore);#endif	free(sm);}u32 gf_sema_notify(GF_Semaphore *sm, u32 NbRelease){	u32 prevCount;#ifndef WIN32	sem_t *hSem;#endif	if (!sm) return 0;#if defined(WIN32)	ReleaseSemaphore(sm->hSemaphore, NbRelease, (LPLONG) &prevCount);#else#if defined(__DARWIN__) || defined(__APPLE__)	hSem = sem_open(sm->SemName, 0);#else	hSem = sm->hSemaphore;#endif	sem_getvalue(hSem, (s32 *) &prevCount);	while (NbRelease) {		if (sem_post(hSem) < 0) return 0;		NbRelease -= 1;	}#endif	return (u32) prevCount;}void gf_sema_wait(GF_Semaphore *sm){#ifdef WIN32	WaitForSingleObject(sm->hSemaphore, INFINITE);#else	sem_t *hSem;#if defined(__DARWIN__) || defined(__APPLE__)	hSem = sem_open(sm->SemName, 0);#else	hSem = sm->hSemaphore;#endif	sem_wait(hSem);#endif}Bool gf_sema_wait_for(GF_Semaphore *sm, u32 TimeOut){#ifdef WIN32	if (WaitForSingleObject(sm->hSemaphore, TimeOut) == WAIT_TIMEOUT) return 0;	return 1;#else	sem_t *hSem;#if defined(__DARWIN__) || defined(__APPLE__)	hSem = sem_open(sm->SemName, 0);#else	hSem = sm->hSemaphore;#endif	if (!TimeOut) {		if (!sem_trywait(hSem)) return 1;		return 0;	}	TimeOut += gf_sys_clock();	do {		if (!sem_trywait(hSem)) return 1;		gf_sleep(1);		} while (gf_sys_clock() < TimeOut);	return 0;#endif}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -