/* -*- c -*-
** Copyright (C) 2000 by Kevin L. Mitchell <klmitch@mit.edu>
**
** 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
**
** @(#)$Id: timer.h.top,v 1.5 2000/12/10 15:00:20 klmitch Exp $
*/
#ifndef __include_timer_h__
#define __include_timer_h__

#ifndef __defined__s_ul__
typedef unsigned long	_s_ul;
#define __defined__s_ul__
#endif
#ifndef __defined__s_us__
typedef unsigned short	_s_us;
#define __defined__s_us__
#endif

typedef struct _timer		timer;
typedef struct _timer_val	timer_val;

/* called with the timer and the current time */
typedef void (*timer_cb)(timer *, const timer_val *);

struct _timer {
  _s_ul		t_magic;	/* magic number */
  timer	       *t_next;		/* timer linked list */
  timer	      **t_prev_p;	/* what points to us */
  _s_us		t_flag;		/* what kind of timer we are */
  timer_val	t_time;		/* timer value when added */
  timer_val	t_call;		/* next time timer is called (absolute) */
  timer_cb	t_callback;	/* callback to call when timer expires */
  void	       *t_arg;		/* extra argument to call callback with */
};

#define TIMER_STRUCT_MAGIC 0x73535ee8

/* timer_verify(timer *atimer)
 *
 * Verifies that the timer passed in is actually a valid timer.  Returns
 * a boolean value.  NOTE THAT THIS MACRO EVALUATES ITS ARGUMENT TWICE!
 */
#define timer_verify(tim)	((tim) && (tim)->t_magic == TIMER_STRUCT_MAGIC)

/* timer_flag_get(timer *atimer)
 *
 * Returns the set of flags for the given timer.
 */
#define timer_flag_get(tim)	((tim)->t_flag)

/* timer_time_get(timer *atimer)
 *
 * Returns a pointer to the timer_val structure which contains the time
 * that was initially passed in the call to timer_add().
 */
#define timer_time_get(tim)	(&(tim)->t_time)

/* timer_call_get(timer *atimer)
 *
 * Returns a pointer to the timer_val structure which contains the time
 * at which this timer will get called.
 */
#define timer_call_get(tim)	(&(tim)->t_call)

/* timer_arg_set(timer *atimer)
 *
 * Returns the extra argument that was set when the timer was initialized
 * or that was later set by timer_arg_set().
 */
#define timer_arg_get(tim)	((tim)->t_arg)

/* timer_arg_set(timer *atimer)
 *
 * Sets the value of the extra argument in the timer.
 */
#define timer_arg_set(tim, arg)	((tim)->t_arg = (arg))

struct _timer_val {
  long		t_sec;		/* seconds; -1 means deactivated */
  long		t_nsec;		/* nanoseconds (will be rounded) */
};

#define TIMER_INTERVAL	0x0001	/* timer is relative to right now */
#define TIMER_ABSOLUTE	0x0002	/* timer specifies an absolute time */
#define TIMER_REPEAT	0x0004	/* timer should be repeated (interval only) */
#define TIMER_ACTIVE	0x0008	/* timer is active and on the queue */

#define TIMER_TYPE_MASK	(TIMER_INTERVAL | TIMER_ABSOLUTE | TIMER_REPEAT)

/* timer_init(timer *atimer, timer_cb callback, void *arg)
 *
 * Initializes a timer with the given callback function and extra argument.
 * Note that the extra argument can be set at any time with the
 * timer_arg_set() macro, but the callback function can only be reset by
 * reinitializing the structure.
 */
_s_ul timer_init(timer *atimer, timer_cb callback, void *arg);

/* timer_add(timer *atimer, timer_val *time, _s_us type)
 *
 * Adds an initialized timer to the queue of timers; it will be called at
 * the time specified in the time argument, under the control of the type
 * argument.  If TIMER_REPEAT is not specified, the timer will be deleted
 * from the timer list prior to issuing the callback, to permit timer_add()
 * to be called on this timer again.  If TIMER_REPEAT is specified, the
 * callback function is permitted to call timer_del() to remove the timer
 * from the list; if it does not, the timer will be readded for execution
 * at the specified interval, as if timer_add() had been called with the
 * same arguments at the end of the callback function.  TIMER_REPEAT may
 * not be used with TIMER_ABSOLUTE.
 */
_s_ul timer_add(timer *atimer, timer_val *time, _s_us type);

/* timer_del(timer *atimer)
 *
 * Removes a timer from the list of timers.
 */
_s_ul timer_del(timer *atimer);

/* timer_time(timer_val *time)
 *
 * Places the current time, as a timer_val, into the structure pointed to
 * by the time argument.
 */
_s_ul timer_time(timer_val *time);

/* _timer_next(timer_val *next, int relative)
 *
 * Returns a pointer to a timer_val that contains the next time the timer
 * queue needs to be run.  If the relative argument is 1, this will be
 * relative to the current time; otherwise, it will be an absolute time.
 */
_s_ul timer_next(timer_val *next, int relative);

/* _timer_run(void)
 *
 * This function is used to run through the timer queue, calling the
 * callback functions as appropriate.
 */
_s_ul timer_run(void);

/* begin timer_err.h */

