代码拉取完成,页面将自动刷新
/*******************************************************************************************
* Copyright (c) 2006-7 Laboratorio di Sistemi di Elaborazione e Bioingegneria Informatica *
* Universita' Campus BioMedico - Italy *
* *
* This program is free software; you can redistribute it and/or modify it under the terms *
* of the GNU General Public License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This program 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License along with this *
* program; if not, write to the: *
* Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, *
* MA 02111-1307, USA. *
* *
* --------------------------------------------------------------------------------------- *
* Project: Capwap *
* *
* Author : Ludovico Rossi (ludo@bluepixysw.com) *
* Del Moro Andrea (andrea_delmoro@libero.it) *
* Giovannini Federica (giovannini.federica@gmail.com) *
* Massimo Vellucci (m.vellucci@unicampus.it) *
* Mauro Bisson (mauro.bis@gmail.com) *
*******************************************************************************************/
#include "CWCommon.h"
#include <stdio.h>
#include <time.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#define CW_USE_THREAD_TIMERS
#ifdef DMALLOC
#include "../dmalloc-5.5.0/dmalloc.h"
#endif
CW_THREAD_RETURN_TYPE CWThreadManageTimers(void *arg);
// Creates a thread that will execute a given function with a given parameter
CWBool CWCreateThread(CWThread * newThread, CW_THREAD_FUNCTION threadFunc, void *arg)
{
if (newThread == NULL)
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
CWDebugLog("Create Thread\n");
if (pthread_create(newThread, NULL, threadFunc, arg) != 0) {
return CWErrorRaise(CW_ERROR_NEED_RESOURCE,
"Can't create thread (maybe there are too many other threads)");
}
return CW_TRUE;
}
// Creates a thread condition (wrapper for pthread_cond_init)
CWBool CWCreateThreadCondition(CWThreadCondition * theCondition)
{
if (theCondition == NULL)
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
switch (pthread_cond_init(theCondition, NULL)) {
case 0: // success
break;
case ENOMEM:
return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);
default:
return CWErrorRaise(CW_ERROR_GENERAL, "Can't create thread condition");
}
return CW_TRUE;
}
// Frees a thread condition (wrapper for pthread_cond_destroy)
void CWDestroyThreadCondition(CWThreadCondition * theCondition)
{
if (theCondition == NULL)
return;
pthread_cond_destroy(theCondition);
}
// Wait for a thread condition (wrapper for pthread_cond_wait)
CWBool CWWaitThreadCondition(CWThreadCondition * theCondition, CWThreadMutex * theMutex)
{
if (theCondition == NULL || theMutex == NULL)
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
switch (pthread_cond_wait(theCondition, theMutex)) {
case 0: // success
break;
case ETIMEDOUT:
return CWErrorRaise(CW_ERROR_TIME_EXPIRED, NULL);
default:
return CWErrorRaise(CW_ERROR_GENERAL, "Error waiting on thread condition");
}
return CW_TRUE;
}
// Wait for a thread condition (wrapper for pthread_cond_wait)
CWBool CWWaitThreadConditionTimeout(CWThreadCondition * theCondition, CWThreadMutex * theMutex,
struct timespec * pTimeout)
{
if (theCondition == NULL || theMutex == NULL)
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
switch (pthread_cond_timedwait(theCondition, theMutex, pTimeout)) {
case 0: // success
break;
case ETIMEDOUT:
return CWErrorRaise(CW_ERROR_TIME_EXPIRED, NULL);
default:
return CWErrorRaise(CW_ERROR_GENERAL, "Error waiting on thread condition");
}
return CW_TRUE;
}
// Signal a thread condition (wrapper for pthread_cond_signal)
void CWSignalThreadCondition(CWThreadCondition * theCondition)
{
if (theCondition == NULL)
return;
pthread_cond_signal(theCondition);
}
// Creates a thread mutex (wrapper for pthread_mutex_init)
CWBool CWCreateThreadMutex(CWThreadMutex * theMutex)
{
if (theMutex == NULL)
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
switch (pthread_mutex_init(theMutex, NULL)) {
case 0: // success
break;
case ENOMEM:
return CWErrorRaise(CW_ERROR_OUT_OF_MEMORY, NULL);
default:
return CWErrorRaise(CW_ERROR_GENERAL, "Can't create thread mutex");
}
return CW_TRUE;
}
// Free a thread mutex (wrapper for pthread_mutex_destroy)
void CWDestroyThreadMutex(CWThreadMutex * theMutex)
{
if (theMutex == NULL)
return;
pthread_mutex_destroy(theMutex);
}
// locks a mutex among threads at the specified address (blocking)
CWBool CWThreadMutexLock(CWThreadMutex * theMutex)
{
if (theMutex == NULL)
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
if (pthread_mutex_lock(theMutex) != 0) {
return CWErrorRaise(CW_ERROR_GENERAL, "Can't lock thread mutex");
}
/*
fprintf(stdout, "Mutex %p locked by %p.\n", theMutex, pthread_self());
fflush(stdout);
*/
return CW_TRUE;
}
// locks a mutex among threads at the specified address (non-blocking).
// CW_TRUE if lock was acquired, CW_FALSE otherwise
CWBool CWThreadMutexTryLock(CWThreadMutex * theMutex)
{
if (theMutex == NULL) {
return CW_FALSE;
}
if (pthread_mutex_trylock(theMutex) == EBUSY)
return CW_FALSE;
else
return CW_TRUE;
}
// unlocks a mutex among threads at the specified address
void CWThreadMutexUnlock(CWThreadMutex * theMutex)
{
if (theMutex == NULL)
return;
pthread_mutex_unlock(theMutex);
/*
fprintf(stdout, "Mutex %p UNlocked by %p.\n", theMutex, pthread_self());
fflush(stdout);
*/
}
// creates a semaphore
CWBool CWThreadCreateSem(CWThreadSem * semPtr, int value)
{
if (semPtr == NULL)
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
// we use named semaphore on platforms that support only them (e.g. Mac OS X)
#ifdef CW_USE_NAMED_SEMAPHORES
{
static int semCount = 0;
char name[32];
snprintf(name, 32, "/CWSem-%d-%4.4d", getpid(), semCount++);
if ((semPtr->semPtr = sem_open(name, O_CREAT, 0600, value)) == (sem_t *) SEM_FAILED) {
CWErrorRaiseSystemError(CW_ERROR_GENERAL);
} else {
sem_unlink(name);
}
}
#else
if (sem_init(semPtr, 0, value) < 0) {
CWErrorRaiseSystemError(CW_ERROR_GENERAL);
}
#endif
return CW_TRUE;
}
// destroy a semaphore
void CWThreadDestroySem(CWThreadSem * semPtr)
{
#ifdef CW_USE_NAMED_SEMAPHORES
if (semPtr == NULL || semPtr->semPtr == NULL)
return;
#else
if (semPtr == NULL)
return;
#endif
#ifdef CW_USE_NAMED_SEMAPHORES
sem_close(semPtr->semPtr);
#else
sem_destroy(semPtr);
#endif
}
// perform wait on a semaphore
CWBool CWThreadSemWait(CWThreadSem * semPtr)
{
#ifdef CW_USE_NAMED_SEMAPHORES
if (semPtr == NULL || semPtr->semPtr == NULL)
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
#else
if (semPtr == NULL)
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
#endif
//CWDebugLog("Sem Wait");
#ifdef CW_USE_NAMED_SEMAPHORES
while (sem_wait(semPtr->semPtr) < 0) {
#else
while (sem_wait(semPtr) < 0) {
#endif
if (errno == EINTR)
continue;
else {
CWErrorRaiseSystemError(CW_ERROR_GENERAL);
}
}
return CW_TRUE;
}
// perform post on a semaphore
CWBool CWThreadSemPost(CWThreadSem * semPtr)
{
#ifdef CW_USE_NAMED_SEMAPHORES
if (semPtr == NULL || semPtr->semPtr == NULL)
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
#else
if (semPtr == NULL)
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
#endif
#ifdef CW_USE_NAMED_SEMAPHORES
if (sem_post(semPtr->semPtr) < 0) {
#else
if (sem_post(semPtr) < 0) {
#endif
CWErrorRaiseSystemError(CW_ERROR_GENERAL);
}
return CW_TRUE;
}
// get the value of a semaphore
CWBool CWThreadSemGetValue(CWThreadSem * semPtr, int *valuePtr)
{
#ifdef CW_USE_NAMED_SEMAPHORES
if (valuePtr == NULL || semPtr == NULL || semPtr->semPtr == NULL)
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
#else
if (valuePtr == NULL || semPtr == NULL)
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
#endif
#ifdef CW_USE_NAMED_SEMAPHORES
if (sem_getvalue(semPtr->semPtr, valuePtr) < 0) { // note: broken on Mac OS X? Btw we don't need it
CWErrorRaiseSystemError(CW_ERROR_GENERAL);
}
#else
if (sem_getvalue(semPtr, valuePtr) < 0) {
CWErrorRaiseSystemError(CW_ERROR_GENERAL);
}
#endif
if (*valuePtr < 0) {
*valuePtr = 0;
}
return CW_TRUE;
}
sem_t *CWThreadGetSemT(CWThreadSem * semPtr)
{
#ifdef CW_USE_NAMED_SEMAPHORES
return (semPtr->semPtr);
#else
return semPtr;
#endif
}
// creates a semaphore that can be used with CWThreadTimedSemWait(). This type of semaphore
// is different from CWThreadSemaphore to support platforms that don't have sem_timedwait() (e.g. Mac OS X)
CWBool CWThreadCreateTimedSem(CWThreadTimedSem * semPtr, int value)
{
#ifdef HAVE_SEM_TIMEDWAIT
return CWThreadCreateSem(semPtr, value);
#else
// if we don't have sem_timedwait(), the timed semaphore is a pair of unix domain sockets.
// We write a dummy packet on a socket (client) when we want to post, and select() with timer on the other socket
// when we want to wait.
struct sockaddr_un serverAddr, clientAddr;
int i;
if (semPtr == NULL)
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
if ((((*semPtr)[0] = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0) || (((*semPtr)[1] = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0)) { // create a pair of datagram unix domain socket
close((*semPtr)[0]);
CWErrorRaiseSystemError(CW_ERROR_CREATING);
}
CW_ZERO_MEMORY(&serverAddr, sizeof(serverAddr));
serverAddr.sun_family = AF_LOCAL;
if (tmpnam((char *)&(serverAddr.sun_path)) == NULL) {
CWErrorRaiseSystemError(CW_ERROR_CREATING);
}
CW_ZERO_MEMORY(&clientAddr, sizeof(clientAddr));
clientAddr.sun_family = AF_LOCAL;
if (tmpnam((char *)&(clientAddr.sun_path)) == NULL) {
CWErrorRaiseSystemError(CW_ERROR_CREATING);
}
if ((bind((*semPtr)[0], (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) || (bind((*semPtr)[1], (struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0) || (connect((*semPtr)[1], (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) || // connect each socket to the other
(connect((*semPtr)[0], (struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0)
) {
close((*semPtr)[0]);
close((*semPtr)[1]);
CWErrorRaiseSystemError(CW_ERROR_CREATING);
}
for (i = 0; i < value; i++) {
if (!CWThreadTimedSemPost(semPtr))
return CW_FALSE;
}
return CW_TRUE;
#endif
}
// CW_TRUE if the semaphore has zero value, CW_FALSE otherwise
CWBool CWThreadTimedSemIsZero(CWThreadTimedSem * semPtr)
{
#ifdef HAVE_SEM_TIMEDWAIT
int value;
if (!CWThreadSemGetValue(semPtr, &value))
return CW_FALSE;
return (value == 0) ? CW_TRUE : CW_FALSE;
#else
fd_set fset;
int r;
struct timeval timeout;
if (semPtr == NULL)
return CW_FALSE;
FD_ZERO(&fset);
FD_SET((*semPtr)[0], &fset);
FD_SET((*semPtr)[1], &fset);
timeout.tv_sec = 0; // poll
timeout.tv_usec = 0;
while ((r = select(max((*semPtr)[1], (*semPtr)[0]) + 1, &fset, NULL, NULL, &timeout)) < 0) {
if (errno == EINTR) {
timeout.tv_sec = 0;
timeout.tv_usec = 0;
continue;
}
CWErrorRaiseSystemError(CW_ERROR_GENERAL);
}
return (r == 0) ? CW_TRUE : CW_FALSE;
#endif
}
CWBool CWThreadTimedSemSetValue(CWThreadTimedSem * semPtr, int value)
{
#ifdef HAVE_SEM_TIMEDWAIT
// note: we can implement this, but our implemntation does't really need it in case
// of a system semaphore. This is useful for our Unix Domain Socket Hack
return CW_TRUE;
//return CWErrorRaise(CW_ERROR_NEED_RESOURCE, "Operation Not Supported");
#else
fd_set fset;
int r, i;
struct timeval timeout;
if (semPtr == NULL)
return CW_FALSE;
FD_ZERO(&fset);
FD_SET((*semPtr)[0], &fset);
FD_SET((*semPtr)[1], &fset);
timeout.tv_sec = 0; // poll
timeout.tv_usec = 0;
// first, remove all the pending packets
CW_REPEAT_FOREVER {
char dummy;
while ((r = select(max((*semPtr)[1], (*semPtr)[0]) + 1, &fset, NULL, NULL, &timeout)) < 0) {
if (errno == EINTR) {
timeout.tv_sec = 0;
timeout.tv_usec = 0;
continue;
}
CWErrorRaiseSystemError(CW_ERROR_GENERAL);
}
if (r == 0)
break;
if (FD_ISSET((*semPtr)[0], &fset)) {
while (read((*semPtr)[0], &dummy, 1) < 0) {
if (errno == EINTR)
continue;
CWErrorRaiseSystemError(CW_ERROR_GENERAL);
}
}
if (FD_ISSET((*semPtr)[1], &fset)) {
while (read((*semPtr)[1], &dummy, 1) < 0) {
if (errno == EINTR)
continue;
CWErrorRaiseSystemError(CW_ERROR_GENERAL);
}
}
}
// second, send n packets, where n is the value we want to set for the semaphore
for (i = 0; i < value; i++) {
if (!CWThreadTimedSemPost(semPtr))
return CW_FALSE;
}
return CW_TRUE;
#endif
}
void CWThreadDestroyTimedSem(CWThreadTimedSem * semPtr)
{
#ifdef HAVE_SEM_TIMEDWAIT
CWThreadDestroySem(semPtr);
#else
if (semPtr == NULL)
return;
close((*semPtr)[0]);
close((*semPtr)[1]);
#endif
}
CWBool CWThreadTimedSemWait(CWThreadTimedSem * semPtr, time_t sec, time_t nsec)
{
#ifdef HAVE_SEM_TIMEDWAIT
struct timespec timeout;
time_t t;
#ifdef CW_USE_NAMED_SEMAPHORES
if (semPtr == NULL || semPtr->semPtr == NULL)
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
#else
if (semPtr == NULL)
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
#endif
CWDebugLog("Sem Timed Wait");
time(&t);
timeout.tv_sec = t + sec;
timeout.tv_nsec = nsec;
#ifdef CW_USE_NAMED_SEMAPHORES
while (sem_timedwait(semPtr->semPtr, &timeout) < 0) {
#else
while (sem_timedwait(semPtr, &timeout) < 0) {
#endif
if (errno == EINTR) {
continue;
} else if (errno == ETIMEDOUT) {
CWDebugLog("sem_timedwait expired");
return CWErrorRaise(CW_ERROR_TIME_EXPIRED, NULL);
} else {
CWErrorRaiseSystemError(CW_ERROR_GENERAL);
}
}
#else
fd_set fset;
int r;
struct timeval timeout;
char dummy;
if (semPtr == NULL)
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
CWDebugLog("Timed Sem Wait");
FD_ZERO(&fset);
FD_SET((*semPtr)[0], &fset);
timeout.tv_sec = sec;
timeout.tv_usec = nsec / 1000;
CWDebugLog("Timed Sem Wait Before Select");
while ((r = select(((*semPtr)[0]) + 1, &fset, NULL, NULL, &timeout)) <= 0) {
CWDebugLog("Timed Sem Wait Select error");
if (r == 0) {
CWDebugLog("Timed Sem Wait Timeout");
return CWErrorRaise(CW_ERROR_TIME_EXPIRED, NULL);
} else if (errno == EINTR) {
timeout.tv_sec = sec;
timeout.tv_usec = nsec / 1000;
continue;
}
CWErrorRaiseSystemError(CW_ERROR_GENERAL);
}
CWDebugLog("Timed Sem Wait After Select");
// ready to read
while (read((*semPtr)[0], &dummy, 1) < 0) {
if (errno == EINTR)
continue;
CWErrorRaiseSystemError(CW_ERROR_GENERAL);
}
// send ack (three-way handshake)
while (send((*semPtr)[0], &dummy, 1, 0) < 0) {
if (errno == EINTR)
continue;
CWErrorRaiseSystemError(CW_ERROR_SENDING);
}
timeout.tv_sec = 2;
timeout.tv_usec = 0;
CWDebugLog("Timed Sem Wait Before Select 2");
while ((r = select(((*semPtr)[0]) + 1, &fset, NULL, NULL, &timeout)) <= 0) {
CWDebugLog("Timed Sem Wait Select error 2");
if (r == 0) {
CWDebugLog("Timed Sem Wait Timeout 2");
return CWErrorRaise(CW_ERROR_TIME_EXPIRED, NULL);
} else if (errno == EINTR) {
timeout.tv_sec = 2;
timeout.tv_usec = 0;
continue;
}
CWErrorRaiseSystemError(CW_ERROR_GENERAL);
}
CWDebugLog("Timed Sem Wait After Select 2");
// read ack
while (read((*semPtr)[0], &dummy, 1) < 0) {
if (errno == EINTR)
continue;
CWErrorRaiseSystemError(CW_ERROR_GENERAL);
}
#endif
CWDebugLog("End of Timed Sem Wait");
return CW_TRUE;
}
CWBool CWThreadTimedSemPost(CWThreadTimedSem * semPtr)
{
#ifdef HAVE_SEM_TIMEDWAIT
return CWThreadSemPost(semPtr);
#else
char dummy = 'D';
fd_set fset;
int r;
struct timeval timeout;
if (semPtr == NULL)
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
CWDebugLog("Timed Sem Post");
while (send((*semPtr)[1], &dummy, 1, 0) < 0) {
if (errno == EINTR)
continue;
CWErrorRaiseSystemError(CW_ERROR_SENDING);
}
// read ack (three-way handshake)
FD_ZERO(&fset);
FD_SET((*semPtr)[1], &fset);
timeout.tv_sec = 2;
timeout.tv_usec = 0;
CWDebugLog("Timed Sem Post Before Select");
while ((r = select(((*semPtr)[1]) + 1, &fset, NULL, NULL, &timeout)) <= 0) {
CWDebugLog("Timed Sem Post Select Error");
if (r == 0) { // timeout, server is not responding
// note: this is not an error in a traditional semaphore, btw it's an error
// according to our logic
CWDebugLog("Timed Sem Post Timeout");
return CWErrorRaise(CW_ERROR_GENERAL, "Nobody is Waiting on this Sem");
} else if (errno == EINTR) {
timeout.tv_sec = 2;
timeout.tv_usec = 0;
continue;
}
CWErrorRaiseSystemError(CW_ERROR_GENERAL);
}
CWDebugLog("Timed Sem Post After Select");
while (read((*semPtr)[1], &dummy, 1) < 0) {
if (errno == EINTR)
continue;
CWErrorRaiseSystemError(CW_ERROR_GENERAL);
}
// send ack
while (send((*semPtr)[1], &dummy, 1, 0) < 0) {
if (errno == EINTR)
continue;
CWErrorRaiseSystemError(CW_ERROR_SENDING);
}
CWDebugLog("End of Sem Post");
return CW_TRUE;
#endif
}
// wrappers for pthread_key_*()
CWBool CWThreadCreateSpecific(CWThreadSpecific * specPtr, void (*destructor) (void *))
{
if (specPtr == NULL)
return CW_FALSE; // NULL destructor is allowed
if (pthread_key_create(specPtr, destructor) != 0) {
CWDebugLog("Error pthread key create");
return CW_FALSE;
}
return CW_TRUE;
}
void CWThreadDestroySpecific(CWThreadSpecific * specPtr)
{
if (specPtr == NULL)
return;
pthread_key_delete(*specPtr);
}
void *CWThreadGetSpecific(CWThreadSpecific * specPtr)
{
if (specPtr == NULL)
return NULL;
return pthread_getspecific(*specPtr);
}
CWBool CWThreadSetSpecific(CWThreadSpecific * specPtr, void *valPtr)
{
if (specPtr == NULL || valPtr == NULL)
return CW_FALSE;
switch (pthread_setspecific(*specPtr, valPtr)) {
case 0: // success
break;
case ENOMEM:
return CW_FALSE;
default:
return CW_FALSE;
}
return CW_TRUE;
}
// terminate the calling thread
void CWExitThread()
{
printf("\n*** Exit Thread ***\n");
pthread_exit((void *)0);
}
void CWThreadSetSignals(int how, int num, ...)
{
sigset_t mask;
va_list args;
sigemptyset(&mask);
va_start(args, num);
for (; num > 0; num--) {
sigaddset(&mask, va_arg(args, int));
}
CWThreadSigMask(how, &mask, NULL);
va_end(args);
}
// timers
typedef struct {
CWThread *requestedThreadPtr;
int signalToRaise;
} CWThreadTimerArg;
struct {
CWThreadSem requestServiceSem;
CWThreadMutex requestServiceMutex;
CWThreadSem serviceProvidedSem;
int requestedSec;
enum {
CW_TIMER_REQUEST,
CW_TIMER_CANCEL,
CW_TIMER_NONE
} requestedOp;
CWThread *requestedThreadPtr;
int signalToRaise;
CWBool error;
CWTimerID timerID;
} gTimersData;
void CWHandleTimer(CWTimerArg arg)
{
CWThreadTimerArg *a = (CWThreadTimerArg *) arg;
CWThread requestedThreadPtr = *(a->requestedThreadPtr);
int signalToRaise = a->signalToRaise;
CWThreadSendSignal(requestedThreadPtr, signalToRaise);
CWDebugLog("Timer Expired, Sent Signal(%d) to Thread: %08x", signalToRaise, requestedThreadPtr);
CW_FREE_OBJECT(a->requestedThreadPtr);
CW_FREE_OBJECT(a);
return;
}
CWBool CWTimerRequest(int sec, CWThread * threadPtr, CWTimerID * idPtr, int signalToRaise)
{
CWThreadTimerArg *arg;
CWDebugLog("Timer Request");
if (sec < 0 || threadPtr == NULL || idPtr == NULL)
return CWErrorRaise(CW_ERROR_WRONG_ARG, NULL);
CW_CREATE_OBJECT_ERR(arg, CWThreadTimerArg, return CW_FALSE;
);
CW_CREATE_OBJECT_ERR(arg->requestedThreadPtr, CWThread, CW_FREE_OBJECT(arg);
return CW_FALSE;
);
CW_COPY_MEMORY(arg->requestedThreadPtr, threadPtr, sizeof(CWThread));
arg->signalToRaise = signalToRaise;
CWDebugLog("Timer Request: thread(%08x), signal(%d)", *(arg->requestedThreadPtr), arg->signalToRaise);
if ((*idPtr = timer_add(sec, 0, &CWHandleTimer, arg)) == -1) {
return CW_FALSE;
}
return CW_TRUE;
}
void CWTimerFreeArg(CWTimerArg arg)
{
CWThreadTimerArg *a = (CWThreadTimerArg *) arg;
/* LE-03-02-2010.01 */
if (a == NULL)
return;
CW_FREE_OBJECT(a->requestedThreadPtr);
CW_FREE_OBJECT(a);
return;
}
CWBool CWTimerCancel(CWTimerID * idPtr)
{
timer_rem(*idPtr, CWTimerFreeArg);
return CW_TRUE;
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。