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

📄 rvtimermgr.c

📁 h.248协议源码
💻 C
字号:
#if (0)
******************************************************************************
Filename    :
Description :
******************************************************************************
                Copyright (c) 2001 RADVision Inc.
************************************************************************
NOTICE:
This document contains information that is proprietary to RADVision LTD.
No part of this publication may be reproduced in any form whatsoever 
without written prior approval by RADVision LTD..

RADVision LTD. reserves the right to revise this publication and make 
changes without obligation to notify any person of such revisions or 
changes.
******************************************************************************
$Revision:$
$Date:$
$Author: S. Cipolli$
******************************************************************************
#endif

#include <assert.h>
#include <limits.h>
#include "rvplatform.h"
#include "rvtypes.h"
#include "rvlog.h"
#include "rvtime.h"
#include "rvtimermgr.h"

#if defined(RV_IO_ANSI) && defined(RV_TIMERSTATS_ON)
#include <stdio.h>
#endif

void rvTimerPtrSwap(RvTimer** a, RvTimer** b) {
	size_t pos;
	RvTimer* t = *a;
	*a = *b;
	*b = t;
	pos = (*a)->pos;
	(*a)->pos = (*b)->pos;
	(*b)->pos = pos;
}

#define rvTimerMgrHeapDestruct(_h)			(rvPtrVectorDestruct(_h))
#define rvTimerMgrHeapAt(_h, _pos)			(*(RvTimer**)rvPtrVectorAt((_h), (_pos)))
#define rvTimerMgrHeapTop(_h)				(rvTimerMgrHeapAt((_h), 0))
#define rvTimerMgrHeapSize(_h)				(rvPtrVectorSize(_h))
#define rvTimerMgrHeapParent(_h, _pos)		(((_pos) - 1) / 2)
#define rvTimerMgrHeapLeftChild(_h, _pos)	(((_pos) * 2) + 1)
#define rvTimerMgrHeapRightChild(_h, _pos)	(((_pos) * 2) + 2)
#define rvTimerMgrHeapHasLeftChild(_h, _pos)\
  (rvTimerMgrHeapLeftChild((_h), (_pos)) < rvTimerMgrHeapSize(_h))
#define rvTimerMgrHeapHasRightChild(_h, _pos)\
  (rvTimerMgrHeapRightChild((_h), (_pos)) < rvTimerMgrHeapSize(_h))
#define rvTimerMgrHeapFirstLeaf(_h)			(rvTimerMgrHeapSize(_h) / 2)
#define rvTimerMgrHeapGetKey(_h, _pos)		(rvTimerMgrHeapAt((_h), (_pos))->absolute)
#define rvTimerMgrHeapSwap(_h, _a, _b)		\
  rvTimerPtrSwap((RvTimer**)rvPtrVectorAt((_h), (_a)), \
  (RvTimer**)rvPtrVectorAt((_h), (_b)))

static void rvTimerMgrHeapSift(RvTimerMgrHeap *h, size_t pos) {
	size_t firstLeaf;

	if (pos >= rvTimerMgrHeapSize(h))
		return;

	firstLeaf = rvTimerMgrHeapFirstLeaf(h);

	while (pos < firstLeaf)
	{
		size_t j = rvTimerMgrHeapLeftChild(h, pos);
		if ((j + 1) < rvTimerMgrHeapSize(h) &&	rvTimerMgrHeapGetKey(h, j+1) < rvTimerMgrHeapGetKey(h, j))
			++j;
		if (rvTimerMgrHeapGetKey(h, pos) <= rvTimerMgrHeapGetKey(h, j))
			return;
		rvTimerMgrHeapSwap(h, pos, j);
		pos = j;
	}
}

static RvTimerMgrHeap* rvTimerMgrHeapConstruct(RvTimerMgrHeap* h, RvAlloc* a) {
	rvPtrVectorConstruct(h, a);
	rvVectorReserve(RvVoidPtr)(h, 1024);
	return h;
}

static void rvTimerMgrHeapPush(RvTimerMgrHeap *h, RvTimer *t) {
	size_t pos = rvPtrVectorSize(h);
	rvPtrVectorPushBack(h, t);
	t->pos = pos;

	while (pos != 0) {
		size_t parent = rvTimerMgrHeapParent(h, pos);
		if (rvTimerMgrHeapGetKey(h, pos) >= rvTimerMgrHeapGetKey(h, parent))
			break;

		rvTimerMgrHeapSwap(h, pos, parent);
		pos = parent;
	}
}

static RvTimer* rvTimerMgrHeapPop(RvTimerMgrHeap* h) {
	RvTimer *t;

	assert(rvTimerMgrHeapSize(h) > 0);

	rvTimerMgrHeapSwap(h, 0, rvTimerMgrHeapSize(h) - 1);

	t = (RvTimer *)rvPtrVectorBack(h);
	assert(t->pos < rvTimerMgrHeapSize(h));

	t->pos = ~0; /* Mark as removed */
	rvPtrVectorPopBack(h);

	if (rvTimerMgrHeapSize(h) != 0)
		rvTimerMgrHeapSift(h, 0);

	return t;
}

static RvTimer *rvTimerMgrHeapRemoveAt(RvTimerMgrHeap *h, size_t pos) {
	RvTimer *t;

	assert((pos < rvTimerMgrHeapSize(h)) || (pos == (~0)));

	if (pos >= rvTimerMgrHeapSize(h)) 
		return NULL;

	rvTimerMgrHeapSwap(h, pos, rvTimerMgrHeapSize(h) - 1);

	t = (RvTimer *)rvPtrVectorBack(h);
	t->pos = ~0; /* Mark as removed */
	rvPtrVectorPopBack(h);

	while (pos != 0) {
		size_t parent = rvTimerMgrHeapParent(h, pos);

		if (rvTimerMgrHeapGetKey(h, pos) >= rvTimerMgrHeapGetKey(h, parent))
			break;

		rvTimerMgrHeapSwap(h, pos, parent);
		pos = parent;
	}

	if (rvTimerMgrHeapSize(h) != 0) 
		rvTimerMgrHeapSift(h, pos);

	return t;
}

#if 0
static RvBool rvTimerMgrHeapVerify(RvTimerMgrHeap *h, size_t pos) {

	/* If timer's pos is not where the timer actually is... fail */
	if (rvTimerMgrHeapAt(h, pos)->pos != pos) 
		return rvFalse;

	if (rvTimerMgrHeapHasLeftChild(h, pos)) {
		size_t left = rvTimerMgrHeapLeftChild(h, pos);
		RvTimer* leftTimer = rvTimerMgrHeapAt(h, left);
		
		/* If the timer's key is not in the right place in the heap... fail */
		if (rvTimerMgrHeapGetKey(h, pos) > rvTimerMgrHeapGetKey(h, left))
			return rvFalse;

		if (!rvTimerMgrHeapVerify(h, left))
			return rvFalse;
	}
		
	if (rvTimerMgrHeapHasRightChild(h, pos)) {		
		size_t right = rvTimerMgrHeapRightChild(h, pos);		
		RvTimer* rightTimer = rvTimerMgrHeapAt(h, right);
		
		/* If the timer's key is not in the right place in the heap... fail */
		if (rvTimerMgrHeapGetKey(h, pos) > rvTimerMgrHeapGetKey(h, right))
			return rvFalse;

		if (!rvTimerMgrHeapVerify(h, right))
			return rvFalse;
	}

	return rvTrue;
}

#endif

#if defined(RV_TIMERSTATS_ON)
static void rvTimerMgrCollectStats(RvTimerMgr* tm, RvTimer* t) {
	RvHrtime actual, delta;

	t->finished = rvTimeGetHrtime();
	actual = rvTimeHrSubtract(t->finished, t->started);
	delta = rvTimeHrSubtract(actual, t->absolute);
	tm->totalDelta = rvTimeHrAdd(tm->totalDelta, delta);
	tm->count++;

#if !defined(RV_IO_NONE)
	if (delta < 0)
		printf("Negative delta\n");
#if defined(RV_OS_WIN32)
	printf("Timer %p { abs=%I64d, actual=%I64d, delta=%I64d, avgDelta=%I64d }\n",
		   t, t->absolute, actual, delta, (tm->totalDelta / (RvHrtime)tm->count));
#else
	/* Using %lld does not currently work on embedded systems. */
	printf("Timer %p { abs=%lld, actual=%lld, delta=%lld, avgDelta=%lld }\n",
		   t, t->absolute, actual, delta, (tm->totalDelta / (RvHrtime)tm->count));
#endif
#endif

}
#endif

static void rvTimerMgrTrigger(RvTimer* e) {
	RvTimer* t;

	/* Trigger expired timers */
	while (e != 0) {

		/* Pop expired timer off list */
		t = e; 
		e = t->next;

		/* Trigger timer function */
		t->func(t, t->data);
	}
}

static void rvTimerMgrProcess(RvTimerMgr* tm) {
	RvHrtime currentTime;
	RvTimer* t;
	RvTimer* e = 0;

	rvMutexLock_(&tm->mutex);

	/* Get current */
	currentTime = rvTimeGetHrtime();

	/* Build list of expired timers */
	while (rvTimerMgrHeapSize(&tm->heap) != 0) {
		t = rvTimerMgrHeapTop(&tm->heap);
		if (t->absolute <= currentTime) {
			t->next = e;
			e = t;
			rvTimerMgrHeapPop(&tm->heap);
			t->state = RV_TIMER_STATE_DEAD;
		} else 
			break;
	}

	rvMutexUnlock_(&tm->mutex);

	/* Trigger expired timers */
	rvTimerMgrTrigger(e);
}

static void rvTimerMgrThread(RvThread_* th, void* data) {
	RvTimerMgr* tm = (RvTimerMgr*)data;
	rvLogEnter(&rvLog, "rvTimerMgrThread");

	while (tm->state == RV_TIMERMGRSTATE_ALIVE) {
		rvThreadSleep_(tm->period);
		rvTimerMgrProcess(tm);
	}

	rvLogLeave(&rvLog, "rvTimerMgrThread");
}

static void rvTimerMgrStartTimeBase(RvTimerMgr* tm) {
	rvThreadConstruct_(&tm->thread, "Timer Mgr", RV_PRIORITYVALUE_MAX,
	  RV_STACKSIZE_TIMERMGR, rvTimerMgrThread, tm);
	rvThreadStart_(&tm->thread);
}

static void rvTimerMgrAdd_(RvTimerMgr* tm, RvTimer* t, RvHrtime nanosec) {
	rvLogEnter(&rvLog, "rvTimerMgrAdd");
	
	/* Lazy initialization of time-base thread */
	if (tm->state == RV_TIMERMGRSTATE_UNBORN) {
		tm->state = RV_TIMERMGRSTATE_ALIVE;
		rvTimerMgrStartTimeBase(tm);
	}	

#if defined(RV_HACK_AVOIDDUPTIMERS)
	{
		size_t pos;
		if ((pos = rvTimerMgrFind(tm, t)) != ~0) {
			rvLogWarning(&rvLog, "rvTimerMgrAdd: Duplicate timer found. Old timer removed");
			rvTimerMgrHeapRemoveAt(&tm->heap, pos);
			t->state = RV_TIMER_STATE_DEAD;
		}
	}
#endif

	assert(t->state != RV_TIMER_STATE_ALIVE && t->pos == (~0));

	/* Mark as "alive" */
	t->state = RV_TIMER_STATE_ALIVE;
	t->absolute = nanosec;

	/* Assign a unique (non-zero) identifier to the timer */
	t->id = (++(tm->id)) ? tm->id : ++(tm->id);

	/* Add it to the heap */
	rvTimerMgrHeapPush(&tm->heap, t);

	rvLogLeave(&rvLog, "rvTimerMgrAdd_");
}

static RvBool rvTimerMgrRemove_(RvTimerMgr* tm, RvTimer* t) {
	RvBool r = rvFalse; 

	rvLogEnter(&rvLog, "rvTimerMgrRemove_");

	/* If timer was started ... stop it */
	if (t->state == RV_TIMER_STATE_ALIVE) {
		assert(t == rvTimerMgrHeapAt(&tm->heap, t->pos));
		if (rvTimerMgrHeapRemoveAt(&tm->heap, t->pos) != NULL) {
			t->state = RV_TIMER_STATE_DEAD;
			r = rvTrue;
		}
	}
	
	rvLogLeave(&rvLog, "rvTimerMgrRemove_");

	return r;
}

/* Useful for debugging timer problems */
static size_t rvTimerMgrFind_(RvTimerMgr* tm, RvTimer* t) {
	size_t pos;	
	for (pos = 0; pos < rvTimerMgrSize(tm); ++pos)
		if (rvTimerMgrHeapAt(&tm->heap, pos) == t)
			return pos;
	return ~0;
}

/* Public: */
RvTimerMgr* rvTimerMgrConstructA(RvTimerMgr* tm, unsigned int period, 
  RvAlloc* a) {
	rvLogEnter(&rvLog, "rvTimerMgrConstruct");

	/* Construct members */
	rvMutexConstruct_(&tm->mutex);
	rvTimerMgrHeapConstruct(&tm->heap, a);
	tm->id = 0;
	tm->period = period;
	tm->state = RV_TIMERMGRSTATE_UNBORN;

#if defined(RV_TIMERSTATS_ON)
	tm->totalDelta = (rvHrtime)0;
	tm->count = 0;
#endif	

	rvLogLeave(&rvLog, "rvTimerMgrConstruct");

	return tm;
}

void rvTimerMgrDestruct(RvTimerMgr* tm) {
	rvLogEnter(&rvLog, "rvTimerMgrDestruct");
	if (tm->state == RV_TIMERMGRSTATE_ALIVE) {
		tm->state = RV_TIMERMGRSTATE_DEAD;
		rvThreadDestruct_(&tm->thread); 
	}
	rvTimerMgrHeapDestruct(&tm->heap);
	rvMutexDestruct_(&tm->mutex);
	rvLogLeave(&rvLog, "rvTimerMgrDestruct");
}

size_t rvTimerMgrSize(const RvTimerMgr* tm) {
	return rvTimerMgrHeapSize(&tm->heap);
}

RvBool rvTimerMgrAdd(RvTimerMgr* tm, RvTimer* t) {
	RvBool r = rvTrue;
	rvLogEnter(&rvLog, "rvTimerMgrAdd");
	rvMutexLock_(&tm->mutex);
	if (t->state == RV_TIMER_STATE_UNBORN)
		rvTimerMgrAdd_(tm, t, rvTimeHrAdd(t->relative, rvTimeGetHrtime()));
	else
		r = rvFalse;
	rvMutexUnlock_(&tm->mutex);
	rvLogLeave(&rvLog, "rvTimerMgrAdd");
	return r;
}

RvBool rvTimerMgrRemove(RvTimerMgr* tm, RvTimer* t) {
	RvBool r;
	rvLogEnter(&rvLog, "rvTimerMgrRemove");
	rvMutexLock_(&tm->mutex);
	r = rvTimerMgrRemove_(tm, t);
	rvMutexUnlock_(&tm->mutex);	
	rvLogLeave(&rvLog, "rvTimerMgrRemove");
	return r;
}

RvBool rvTimerMgrReset(RvTimerMgr* tm, RvTimer* t, RvHrtime nanosec) {
	RvBool r;
	
	rvLogEnter(&rvLog, "rvTimerMgrReset");
	rvMutexLock_(&tm->mutex);

	/* Remove the timer is its already alive */
	r = rvTimerMgrRemove_(tm, t);

	/* Add the timer to the timer manager */
	t->relative = nanosec;
	rvTimerMgrAdd_(tm, t, rvTimeHrAdd(t->relative, rvTimeGetHrtime()));

	rvMutexUnlock_(&tm->mutex);
	rvLogLeave(&rvLog, "rvTimerMgrReset");

	return r;
}

/* Useful for debugging timer problems */
size_t rvTimerMgrFind(RvTimerMgr* tm, RvTimer* t) {
	size_t pos;
	rvMutexLock_(&tm->mutex);
	pos = rvTimerMgrFind_(tm, t);
	rvMutexUnlock_(&tm->mutex);
	return pos;
}

⌨️ 快捷键说明

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