/***************************************************************************
* *
* 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. *
* *
***************************************************************************
* timer.cc
* (c) Murat Deligonul 2002
*/
#include "autoconf.h"
#include "timer.h"
#include "linkedlist.h"
#include "debug.h"
/**
* This a simple implementation of interval timers ..
*/
list<timer> timer::timers;
int timer::poll_interval = 0;
time_t timer::counter = 0;
timer::timer(int _int, int _opt, int _id)
{
DEBUG("timer::timer() -- %p started at %d, [interval: %d options: %d]\n",
this, counter, _int, _opt);
assert(_int != 0);
interval = _int;
id = _id;
options = _opt;
epoch = counter;
}
timer::~timer()
{
DEBUG("timer::~timer() -- %p\n", this);
}
/**
* Add this timer to the active timers list.
* Figure out the poll interval and return
* Never call from a timer_proc
*/
int timer::enable(timer * t)
{
DEBUG("timer::enable() -- %p\n", t);
timers.add(t);
poll_interval = calc_interval();
return get_poll_interval();
}
/**
* Remove from the active timers list
* Never call from a timer_proc
* FIXME: current we do not re-calculate the poll-interval after a disable
*
*/
int timer::disable(timer * t)
{
DEBUG("timer::disable() -- %p\n", t);
timers.remove(t);
// poll_interval = calc_interval();
return get_poll_interval();
}
/**
* Figure out what interval to poll the timers
* (with the gcd algorithm) */
int timer::calc_interval()
{
if (!timers.size())
return 0;
list_iterator<timer> i(&timers);
int * array = new int[timers.size()];
int idx = 0;
while (i.has_next())
{
timer * t = i.next();
array[idx++] = t->interval;
}
int r = gcd(array, idx);
delete[] array;
return r;
}
/**
* Recursively compute greatest common divisor
* of two ints
*/
int timer::gcd(int i, int j)
{
if (j > i)
{
int t = i;
i = j;
j = t;
}
int r = i % j;
if (!r)
return j;
return gcd(j, r);
}
/**
* Find the GCD of an array of int
*/
int timer::gcd(int * array, int num)
{
if (num < 2)
return array[0];
int r = gcd(array[0], array[1]);
for (int i = 2; i < num; ++i)
r = gcd(r, array[i]);
return r;
}
/**
* Poll the timers
*/
int timer::poll(time_t realtime)
{
list_iterator<timer> i(&timers);
counter += poll_interval;
DEBUG("timer::poll() @ time index %lu [real: %lu]\n",
counter, realtime);
while (i.has_next())
{
/**
* Call the handler:
* Check for < 0 return value, and remove that
* timer if necessary */
timer * t = i.next();
if (!((counter - t->epoch) % t->interval) )
if ( (t->timer_proc(realtime) < 0) ||
(t->options & TIMER_ONESHOT))
i.remove();
}
return 1;
}
int generic_timer::timer_proc(time_t t)
{
DEBUG("generic_timer()::timer_proc() -- %p\n", this);
return callback(t, get_id(), data);
}
syntax highlighted by Code2HTML, v. 0.9.1