* $Id$
 * timer related functions (public interface)
 * Copyright (C) 2001-2003 FhG Fokus
 * This file is part of ser, a free SIP server.
 * ser 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
 * For a license to use the ser software under conditions
 * other than those described here, or to purchase support for this
 * software, please contact iptel.org by e-mail at the following addresses:
 *    info@iptel.org
 * ser is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * 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
/* History:
 * --------
 *  2005-07-27  complete re-design/re-implemnetation (andrei)

#ifndef timer_h
#define timer_h

#define USE_SLOW_TIMER /* use another process to run the timer handlers 
						  marked "slow" */
/*#define TIMER_DEBUG -- compile with -DTIMER_DEBUG*/

#include "clist.h"
#include "dprint.h"

#include <sys/types.h>

typedef unsigned short slow_idx_t; /* type fot the slow index */
extern pid_t slow_timer_pid;

typedef unsigned int ticks_t;/* type used to keep the ticks (must be 32 bits)*/
typedef signed   int s_ticks_t; /* signed ticks type */

/* deprecated, old, kept for compatibility */
typedef void (timer_function)(unsigned int ticks, void* param);
/* deprecated, old, kept for compatibility 
	get_ticks()*TIMER_TICK used to be the time in s
	for new code, use get_ticks_raw() and one of the macros defined in
	time_ticks.h (.e.g TICKS_TO_S(tick) to convert to s or ms )*/
#define TIMER_TICK 1 /* 1 s, kept for compatibility */

struct timer_ln; /* forward decl */
/* new 
 * params:
 *         - handle pointer to the corresponding struct timer_ln
 * return: 0 if the timer is one shot, new expire interval if not, -1
 *         if periodic
 * e.g.:   - a periodic timer would return: (ticks_t)(-1) or
 *            ((struct timer_ln*)handle)->initial_timeout
 *         - a timer which wants to expire again in x ms would return:
 *             (x * TICKS_HZ + 999)/1000
typedef ticks_t (timer_handler_f)(ticks_t t, struct timer_ln* tl,
									void* data);

/* timer flags */
#define F_TIMER_FAST	1
#define F_TIMER_ON_SLOW_LIST	0x100
#define F_TIMER_ACTIVE	0x200 /* timer is running or has run and expired
								 (one shot) */
#define F_TIMER_DELETED	0x400 

struct timer_ln{ /* timer_link already used in tm */
	struct timer_ln* next;
	struct timer_ln* prev;
	ticks_t expire; 
	ticks_t initial_timeout;
	void* data;
	timer_handler_f* f; 
	volatile unsigned short flags;
	volatile slow_idx_t slow_idx;
	unsigned short reserved;
	unsigned int expires_no; /* timer handler calls */
	const char* add_file;
	const char* add_func;
	unsigned add_line;
	unsigned add_calls;
	const char* del_file;
	const char* del_func;
	unsigned del_line;
	unsigned int del_calls;
	unsigned int init; /* how many times was init/re-init */

void timer_main(); /* timer main loop, never exists */

int init_timer();
int arm_timer();
void destroy_timer();

int arm_slow_timer();
void slow_timer_main();

struct timer_ln* timer_alloc();
void timer_free(struct timer_ln* t);

/* use for a deleted/expired timer that you want to add again */
#define timer_reinit(tl) \
	do{ \
		(tl)->flags&=~((unsigned short)(F_TIMER_ON_SLOW_LIST | \
		(tl)->init++; \
/* use for a deleted/expired timer that you want to add again */
#define timer_reinit(tl) \
	(tl)->flags&=~((unsigned short)(F_TIMER_ON_SLOW_LIST | \

#define timer_init(tl, fun, param, flgs) \
	do{ \
		memset((tl), 0, sizeof(struct timer_ln)); \
		(tl)->f=(fun); \
		(tl)->data=(param); \
		(tl)->flags=(flgs); \
		timer_reinit(tl); \

int timer_add_safe(struct timer_ln *tl, ticks_t delta, 
					const char*, const char*, unsigned);
void timer_del_safe(struct timer_ln *tl,
					const char*, const char*, unsigned);
#define timer_add(tl, d) \
	timer_add_safe((tl), (d), __FILE__, __FUNCTION__, __LINE__)
#define timer_del(tl) \
	timer_del_safe((tl), __FILE__, __FUNCTION__, __LINE__)
int timer_add_safe(struct timer_ln *tl, ticks_t delta);
void timer_del_safe(struct timer_ln *tl);
#define timer_add timer_add_safe
#define timer_del timer_del_safe

void timer_allow_del();

/* old timer compatibility functions & structure */

struct sr_timer{
	struct timer_ln tl;
	int id;
	timer_function* timer_f;
	void* t_param;

/*register a periodic timer;
 * ret: <0 on error*/
int register_timer(timer_function f, void* param, unsigned int interval);
ticks_t get_ticks();
ticks_t get_ticks_raw();