Exemplo n.º 1
0
static void tick_timer (int now, void* data)
{
	struct timer* timer = (struct timer*)data;
	const int old_interval = timer->interval;

	/* Compute and store the lateness, updating the total */
	const int lateness = Sys_Milliseconds() - now;
	timer->total_lateness -= timer->recent_lateness[timer->next_lateness];
	timer->recent_lateness[timer->next_lateness] = lateness;
	timer->total_lateness += lateness;
	timer->next_lateness++;
	timer->next_lateness %= TIMER_LATENESS_HISTORY;

	/* Is it time to check the mean yet? */
	timer->next_check--;
	if (timer->next_check <= 0) {
		const int mean = timer->total_lateness / TIMER_LATENESS_HISTORY;

		/* We use a saturating counter to damp the adjustment */

		/* When we stay above the high water mark, increase the interval */
		if (mean > TIMER_LATENESS_HIGH)
			timer->checks_high = std::min(TIMER_CHECK_LAG, timer->checks_high + 1);
		else
			timer->checks_high = std::max(0, timer->checks_high - 1);

		if (timer->checks_high > TIMER_CHECK_LAG)
			timer->interval += 2;

		/* When we stay below the low water mark, decrease the interval */
		if (mean < TIMER_LATENESS_LOW)
			timer->checks_low = std::min(TIMER_CHECK_LAG, timer->checks_high + 1);
		else
			timer->checks_low = std::max(0, timer->checks_low - 1);

		if (timer->checks_low > TIMER_CHECK_LAG)
			timer->interval -= 1;

		/* Note that we slow the timer more quickly than we speed it up,
		 * so it should tend to settle down in the vicinity of the low
		 * water mark */

		timer->next_check = TIMER_CHECK_INTERVAL;
	}

	timer->interval = std::max(timer->interval, 1000 / timer->min_freq->integer);

	if (timer->interval != old_interval)
		Com_DPrintf(DEBUG_ENGINE, "Adjusted timer on %s to interval %d\n", timer->min_freq->name, timer->interval);

	try {
		timer->func(now, timer->data);
	} catch (comDrop_t const&) {
	}

	/* We correct for the lateness of this frame. We do not correct for
	 * the time consumed by this frame - that's billed to the lateness
	 * of future frames (so that the automagic slowdown can work) */
	Schedule_Event(now + lateness + timer->interval, &tick_timer, nullptr, nullptr, timer);
}
Exemplo n.º 2
0
static void testScheduler (void)
{
	scheduleEvent_t *one, *two, *three, *four, *five, *e;

	three = Schedule_Event(4, NULL, NULL, NULL, "three");
	CU_ASSERT_EQUAL_FATAL(three->next, NULL);

	four = Schedule_Event(4, NULL, NULL, NULL, "four");
	CU_ASSERT_EQUAL_FATAL(three->next, four);
	CU_ASSERT_EQUAL_FATAL(four->next, NULL);

	five = Schedule_Event(4, NULL, NULL, NULL, "five");
	CU_ASSERT_EQUAL_FATAL(three->next, four);
	CU_ASSERT_EQUAL_FATAL(four->next, five);
	CU_ASSERT_EQUAL_FATAL(five->next, NULL);

	one = Schedule_Event(3, NULL, delayCheck, NULL, "one");
	CU_ASSERT_EQUAL_FATAL(one->next, three);
	CU_ASSERT_EQUAL_FATAL(three->next, four);
	CU_ASSERT_EQUAL_FATAL(four->next, five);
	CU_ASSERT_EQUAL_FATAL(five->next, NULL);

	two = Schedule_Event(3, NULL, NULL, NULL, "two");
	CU_ASSERT_EQUAL_FATAL(one->next, two);
	CU_ASSERT_EQUAL_FATAL(two->next, three);
	CU_ASSERT_EQUAL_FATAL(three->next, four);
	CU_ASSERT_EQUAL_FATAL(four->next, five);
	CU_ASSERT_EQUAL_FATAL(five->next, NULL);

	e = Dequeue_Event(1);
	CU_ASSERT_EQUAL(e, NULL);
	e = Dequeue_Event(2);
	CU_ASSERT_EQUAL(e, NULL);
	/* one is delayed via check function - so we get the 2nd event at the first dequeue here */
	e = Dequeue_Event(3);
	CU_ASSERT_EQUAL_FATAL(e, two);
	/* now we are ready for the 1st event */
	e = Dequeue_Event(5);
	CU_ASSERT_EQUAL_FATAL(e, one);
	/* the remaining events are in order */
	e = Dequeue_Event(5);
	CU_ASSERT_EQUAL_FATAL(e, three);
	e = Dequeue_Event(5);
	CU_ASSERT_EQUAL_FATAL(e, four);
	e = Dequeue_Event(5);
	CU_ASSERT_EQUAL_FATAL(e, five);
}
Exemplo n.º 3
0
static void testBlocked (void)
{
	std::string s_one("one");
	std::string s_two("two");
	std::string s_three("three");
	std::string s_four("three");

	const int delay = 10;

	event_func* f_oneFour = (event_func*)0xCAFED00D;
	event_func* f_twoThree = (event_func*)0xB16B00B5;

	ScheduleEventPtr one = Schedule_Event(3, f_oneFour, delayCheckBlocked, nullptr, static_cast<void*>(&s_one));
	one->delayFollowing = delay;
	ScheduleEventPtr two = Schedule_Event(4 + delay, f_twoThree, nullptr, nullptr, static_cast<void*>(&s_two));
	two->delayFollowing = delay;
	ScheduleEventPtr three = Schedule_Event(5 + delay, f_twoThree, nullptr, nullptr, static_cast<void*>(&s_three));
	three->delayFollowing = delay;
	ScheduleEventPtr four = Schedule_Event(5, f_oneFour, delayCheckBlocked, nullptr, static_cast<void*>(&s_four));
	four->delayFollowing = delay;

	ScheduleEventPtr e = Dequeue_Event(1);
	CU_ASSERT_FALSE(e);
	e = Dequeue_Event(2);
	CU_ASSERT_FALSE(e);
	e = Dequeue_Event(3);
	CU_ASSERT_FALSE(e);
	e = Dequeue_Event(5);
	CU_ASSERT_FALSE(e);

	delayCheckBlockedVal = true;

	e = Dequeue_Event(5);
	CU_ASSERT_FALSE(e);
	e = Dequeue_Event(5 + delay);
	CU_ASSERT_EQUAL_FATAL(e, one);
	e = Dequeue_Event(4 + delay);
	CU_ASSERT_EQUAL_FATAL(e, two);
	e = Dequeue_Event(4 + delay);
	CU_ASSERT_FALSE(e);
	e = Dequeue_Event(5 + delay);
	CU_ASSERT_EQUAL_FATAL(e, three);
	e = Dequeue_Event(5 + delay);
	CU_ASSERT_EQUAL_FATAL(e, four);
}
Exemplo n.º 4
0
static void testScheduler (void)
{
	std::string s_one("one");
	std::string s_two("two");
	std::string s_three("three");
	std::string s_four("four");
	std::string s_five("five");

	ScheduleEventPtr one = Schedule_Event(3, nullptr, nullptr, nullptr, static_cast<void*>(&s_one));
	ScheduleEventPtr two = Schedule_Event(3, nullptr, nullptr, nullptr, static_cast<void*>(&s_two));
	ScheduleEventPtr three = Schedule_Event(4, nullptr, nullptr, nullptr, static_cast<void*>(&s_three));
	ScheduleEventPtr four = Schedule_Event(4, nullptr, nullptr, nullptr, static_cast<void*>(&s_four));
	ScheduleEventPtr five = Schedule_Event(5, nullptr, nullptr, nullptr, static_cast<void*>(&s_five));

	CU_ASSERT_EQUAL(Dequeue_Event(1000), one);
	CU_ASSERT_EQUAL(Dequeue_Event(1000), two);
	CU_ASSERT_EQUAL(Dequeue_Event(1000), three);
	CU_ASSERT_EQUAL(Dequeue_Event(1000), four);
	CU_ASSERT_EQUAL(Dequeue_Event(1000), five);
	CU_ASSERT_FALSE(Dequeue_Event(1000));
}
Exemplo n.º 5
0
static void Schedule_Timer (cvar_t* freq, event_func* func, event_check_func* check, void* data)
{
	struct timer* const timer = Mem_PoolAllocType(struct timer, com_genericPool);
	timer->min_freq = freq;
	timer->interval = 1000 / freq->integer;
	timer->next_lateness = 0;
	timer->total_lateness = 0;
	timer->next_check = TIMER_CHECK_INTERVAL;
	timer->checks_high = 0;
	timer->checks_low = 0;
	timer->func = func;
	timer->data = data;
	for (int i = 0; i < TIMER_LATENESS_HISTORY; i++)
		timer->recent_lateness[i] = 0;

	Schedule_Event(Sys_Milliseconds() + timer->interval, &tick_timer, check, nullptr, timer);
}
Exemplo n.º 6
-1
static void testSchedulerCheck (void)
{
	std::string s_one("one");
	std::string s_two("two");
	std::string s_three("three");
	std::string s_four("four");
	std::string s_five("five");

	ScheduleEventPtr three = Schedule_Event(4, nullptr, nullptr, nullptr, static_cast<void*>(&s_three));
	ScheduleEventPtr four = Schedule_Event(4, nullptr, nullptr, nullptr, static_cast<void*>(&s_four));
	ScheduleEventPtr five = Schedule_Event(4, nullptr, nullptr, nullptr, static_cast<void*>(&s_five));
	ScheduleEventPtr one = Schedule_Event(3, nullptr, delayCheck, nullptr, static_cast<void*>(&s_one));
	ScheduleEventPtr two = Schedule_Event(3, nullptr, nullptr, nullptr, static_cast<void*>(&s_two));

	ScheduleEventPtr e = Dequeue_Event(1);
	CU_ASSERT_FALSE(e);
	e = Dequeue_Event(2);
	CU_ASSERT_FALSE(e);
	/* one is delayed via check function - so we get the 2nd event at the first dequeue here */
	e = Dequeue_Event(3);
	CU_ASSERT_EQUAL_FATAL(e, two);
	/* now we are ready for the 1st event */
	e = Dequeue_Event(5);
	CU_ASSERT_EQUAL_FATAL(e, one);
	/* the remaining events are in order */
	e = Dequeue_Event(5);
	CU_ASSERT_EQUAL_FATAL(e, three);
	e = Dequeue_Event(5);
	CU_ASSERT_EQUAL_FATAL(e, four);
	e = Dequeue_Event(5);
	CU_ASSERT_EQUAL_FATAL(e, five);
}