?? rvtimer.c
字號:
maxtimers = RvObjPoolGetMaxitems(&tqueue->pool);
RvLockRelease(&tqueue->lock);
return maxtimers;
}
/* Sets the value for maxtimers (not used by FIXED queues). */
/* Returns RV_TRUE upon success (otherwise RV_FALSE). */
RvBool RvTimerQueueSetMaxtimers(RvTimerQueue *tqueue, RvSize_t maxtimers)
{
RvBool result;
#if defined(RV_NULLCHECK)
if(tqueue == NULL)
return RV_FALSE;
#endif
if(RvLockGet(&tqueue->lock) != RV_OK)
return RV_FALSE;
result = RvObjPoolSetMaxitems(&tqueue->pool, maxtimers);
RvLockRelease(&tqueue->lock);
return result;
}
/* Changes the value for maxtimers (not used by FIXED queues) by an */
/* offset (delta). The direction parameter indicates whether the delta */
/* is an increase or a decrease. Returns RV_TRUE upon success */
/* (otherwise RV_FALSE). */
RvBool RvTimerQueueChangeMaxtimers(RvTimerQueue *tqueue, RvSize_t delta, RvBool direction)
{
RvBool result;
RvSize_t maxtimers;
#if defined(RV_NULLCHECK)
if(tqueue == NULL)
return RV_FALSE;
#endif
#if defined(RV_RANGECHECK)
if((direction != RV_TIMER_VALUE_INCREASE) && (direction != RV_TIMER_VALUE_DECREASE))
return RV_FALSE;
#endif
if(RvLockGet(&tqueue->lock) != RV_OK)
return RV_FALSE;
maxtimers = RvObjPoolGetMaxitems(&tqueue->pool);
if(direction == RV_TIMER_VALUE_DECREASE) {
if(delta > maxtimers) {
/* Can't go negative. */
RvLockRelease(&tqueue->lock);
return RV_FALSE;
}
maxtimers -= delta;
} else maxtimers += delta;
result = RvObjPoolSetMaxitems(&tqueue->pool, maxtimers);
RvLockRelease(&tqueue->lock);
return result;
}
/* Returns current value for mintimers (not used by FIXED). */
RvSize_t RvTimerQueueGetMintimers(RvTimerQueue *tqueue)
{
RvSize_t mintimers;
#if defined(RV_NULLCHECK)
if(tqueue == NULL)
return 0;
#endif
if(RvLockGet(&tqueue->lock) != RV_OK)
return 0;
mintimers = RvObjPoolGetMinitems(&tqueue->pool);
RvLockRelease(&tqueue->lock);
return mintimers;
}
/* Sets the value for mintimers. Returns RV_TRUE upon success */
/* (otherwise RV_FALSE). Note: for FIXED timer queues mintimers */
/* is not normally used and increasing mintimers above the current */
/* timer queue size will increase the memory used by the pool but will */
/* NOT increase the size of the timer queue. Use RvTimerQueueSetSize */
/* to change the size of a FIXED timer queue. */
RvBool RvTimerQueueSetMintimers(RvTimerQueue *tqueue, RvSize_t mintimers)
{
RvBool result;
#if defined(RV_NULLCHECK)
if(tqueue == NULL)
return RV_FALSE;
#endif
if(RvLockGet(&tqueue->lock) != RV_OK)
return RV_FALSE;
result = RvObjPoolSetMinitems(&tqueue->pool, mintimers);
RvLockRelease(&tqueue->lock);
return result;
}
/* Changes the value for mintimers by an offset (delta). The */
/* direction parameter indicates whether the delta is an increase */
/* or a decrease. Returns RV_TRUE upon success (otherwise RV_FALSE). */
/* See RvTimerQueueSetMintimers note about increasing FIXED timer queues. */
RvBool RvTimerQueueChangeMintimers(RvTimerQueue *tqueue, RvSize_t delta, RvBool direction)
{
RvBool result;
RvSize_t mintimers;
#if defined(RV_NULLCHECK)
if(tqueue == NULL)
return RV_FALSE;
#endif
#if defined(RV_RANGECHECK)
if((direction != RV_TIMER_VALUE_INCREASE) && (direction != RV_TIMER_VALUE_DECREASE))
return RV_FALSE;
#endif
if(RvLockGet(&tqueue->lock) != RV_OK)
return RV_FALSE;
mintimers = RvObjPoolGetMinitems(&tqueue->pool);
if(direction == RV_TIMER_VALUE_DECREASE) {
if(delta > mintimers) {
/* Can't go negative. */
RvLockRelease(&tqueue->lock);
return RV_FALSE;
}
mintimers -= delta;
} else mintimers += delta;
result = RvObjPoolSetMinitems(&tqueue->pool, mintimers);
RvLockRelease(&tqueue->lock);
return result;
}
/* Returns current value for freelevel (only used by DYNAMIC queues) */
RvSize_t RvTimerQueueGetFreelevel(RvTimerQueue *tqueue)
{
RvSize_t freelevel;
#if defined(RV_NULLCHECK)
if(tqueue == NULL)
return 0;
#endif
if(RvLockGet(&tqueue->lock) != RV_OK)
return 0;
freelevel = RvObjPoolGetFreelevel(&tqueue->pool);
RvLockRelease(&tqueue->lock);
return freelevel;
}
/* Sets new value for freelevel. Return RV_TRUE if successful (otherwise */
/* return RV_FALSE). Use only by DYNAMIC queues. */
RvBool RvTimerQueueSetFreelevel(RvTimerQueue *tqueue, RvSize_t freelevel)
{
RvBool result;
#if defined(RV_NULLCHECK)
if(tqueue == NULL)
return RV_FALSE;
#endif
if(RvLockGet(&tqueue->lock) != RV_OK)
return RV_FALSE;
result = RvObjPoolSetFreelevel(&tqueue->pool, freelevel);
RvLockRelease(&tqueue->lock);
return result;
}
/* Returns number of nanoseconds until next event in nextevent */
/* parameter. Negative number indicates that the event is overdue. */
/* If the queue is empty a warning is returned and nextevent is untouched. */
RVCOREAPI RvStatus RVCALLCONV RvTimerQueueNextEvent(RvTimerQueue *tqueue, RvInt64 *nextevent)
{
RvStatus result;
RvInt64 curtime;
RvTimerEvent *event;
#if defined(RV_NULLCHECK)
if(tqueue == NULL)
return RvTimerErrorCode(RV_ERROR_NULLPTR);
#endif
curtime = RvTimestampGet();
result = RvLockGet(&tqueue->lock);
if(result != RV_OK)
return result;
event = (RvTimerEvent *)RvPQueuePeek(&tqueue->pqueue);
if(event != NULL) {
*nextevent = event->triggertime - curtime;
} else result = RvTimerErrorCode(RV_TIMER_WARNING_QUEUEEMPTY);
RvLockRelease(&tqueue->lock);
return result;
}
/* Destruct a timer queue. This must only be called by a single task */
/* and no calls to any timer function should be in progress. */
RVCOREAPI RvStatus RVCALLCONV RvTimerQueueDestruct(RvTimerQueue *tqueue)
{
RvStatus result;
RvTimerEvent *event;
#if defined(RV_NULLCHECK)
if(tqueue == NULL)
return RvTimerErrorCode(RV_ERROR_NULLPTR);
#endif
RvTimerQueueStop(tqueue); /* Doesn't hurt to make sure. */
result = RvLockGet(&tqueue->lock);
if(result != RV_OK)
return result;
/* Return all events back to pool. */
for(;;) {
event = (RvTimerEvent *)RvPQueueGet(&tqueue->pqueue);
if(event == NULL)
break;
RvObjPoolReleaseItem(&tqueue->pool, event);
}
RvPQueueDestruct(&tqueue->pqueue);
if(RvObjPoolDestruct(&tqueue->pool) != RV_TRUE)
result = RvTimerErrorCode(RV_TIMER_ERROR_POOL);
RvSemaphoreDestruct(&tqueue->wait);
RvLockDestruct(&tqueue->lock);
return result;
}
/* Create individual event for pool. */
static void *RvTimerEventConstruct(void *objptr, void *data)
{
RvStatus status;
RvTimerEvent *timerevent;
timerevent = (RvTimerEvent *)objptr;
status = RvSemaphoreConstruct(&timerevent->wait, 0);
if(status != RV_OK)
return NULL;
timerevent->waitcount = 0; /* Should always stay in sync with semaphore */
timerevent->tqueue = (RvTimerQueue *)data; /* Never changes. */
return objptr;
}
/* Destroy individual event for pool. */
static void RvTimerEventDestruct(void *objptr, void *data)
{
RV_UNUSED_ARG(data);
RvSemaphoreDestruct(&((RvTimerEvent *)objptr)->wait);
}
/* Allocate memory page for event pool and Priority Queue. */
static void *RvTimerMemAlloc(RvSize_t size, void *data)
{
void *result;
RvStatus status;
status = RvMemoryAlloc((RvMemory *)data, &result, size);
if(status != RV_OK)
return NULL;
return result;
}
/* Free memory page for event pool and Priority Queue. */
static void RvTimerMemFree(void *ptr, void *data)
{
RV_UNUSED_ARG(data);
RvMemoryFree(ptr);
}
/* For Priority queue, return RV_TRUE if ptr1 higher priority than ptr2. */
static RvBool RvTimerPQueueItemCmp(void *ptr1, void *ptr2)
{
if(((RvTimerEvent *)ptr1)->triggertime < ((RvTimerEvent *)ptr2)->triggertime)
return RV_TRUE;
return RV_FALSE;
}
/* For Priority Queue, save index of specified item (used for deletion). */
static void RvTimerPQueueNewIndex(void *item, RvSize_t index)
{
((RvTimerEvent *)item)->index = index;
}
/* Add an event to the timer queue specified by tqueue. The timertype is ONESHOT or PERIODIC and */
/* delay specificies the number of nanoseconds to delay before triggering the callback function. */
/* The userdata is simply passed to the callback function. Upon successfull completion of RvTimerStart, */
/* the timer structure will contain an identifier which can be used to cancel that timer. There is */
/* no construct or destruct on the timer structure and it is not required to be maintained for */
/* the event to occur. It is only used for cancelling the timer. If it is NULL, then the timer can */
/* not be cancelled. Note: The minimum time for a timer and the resolution is based on the */
/* timestamp driver and on the rate at which the timer queue is checked. */
RVCOREAPI RvStatus RVCALLCONV RvTimerStart(RvTimer *timer, RvTimerQueue *tqueue, RvInt timertype, RvInt64 delay, RvTimerFunc callback, void *userdata)
{
RvStatus result;
RvInt64 starttime;
RvTimerEvent *event;
#if defined(RV_NULLCHECK)
if((tqueue == NULL) || (callback == NULL))
return RvTimerErrorCode(RV_ERROR_NULLPTR);
#endif
#if defined(RV_RANGECHECK)
if((timertype != RV_TIMER_TYPE_ONESHOT) && (timertype != RV_TIMER_TYPE_PERIODIC))
return RvTimerErrorCode(RV_ERROR_OUTOFRANGE);
#endif
/* Get start time as soon as possible for best accuracy. */
starttime = RvTimestampGet();
result = RvLockGet(&tqueue->lock);
if(result != RV_OK)
return result;
/* Get a timer event from the pool. */
event = (RvTimerEvent *)RvObjPoolGetItem(&tqueue->pool);
if(event == NULL) {
RvLockRelease(&tqueue->lock);
return RvTimerErrorCode(RV_TIMER_ERROR_QUEUEFULL);
}
/* Initialize event; tqueue, the wait semaphore, and waitcount are already set. */
event->timertype = timertype;
event->state = RV_TIMER_EVENTSTATE_QUEUED;
tqueue->idcounter += RvUintConst(1);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -