1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
4 * $Id: timeout.c 2096 2001-07-31 01:00:39Z warmenhoven $
6 * Copyright (C) 1998-2001, Denis V. Dmitrienko <denis@null.net> and
7 * Bill Soudan <soudan@kde.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 icq_Timeout
*icq_CurrentTimeout
= NULL
;
30 icq_List
*icq_TimeoutList
= NULL
;
32 void (*icq_SetTimeout
)(long length
);
34 int icq_TimeoutCompare(icq_Timeout
*t1
, icq_Timeout
*t2
)
36 return (t1
->expire_time
- t2
->expire_time
);
39 icq_Timeout
*icq_TimeoutNew(int length
, icq_TimeoutHandler handler
,
42 icq_Timeout
*t
= (icq_Timeout
*)malloc(sizeof(icq_Timeout
));
46 int count
= icq_TimeoutList
->count
;
51 t
->expire_time
= time(NULL
) + length
;
54 icq_ListInsertSorted(icq_TimeoutList
, t
);
57 icq_TimeoutDoNotify();
63 void icq_TimeoutDelete(icq_Timeout
*timeout
)
65 icq_ListRemove(icq_TimeoutList
, timeout
);
67 /* if this was the timeout we were currently waiting on, move on
69 if (icq_CurrentTimeout
== timeout
)
71 icq_CurrentTimeout
= NULL
;
72 icq_TimeoutDoNotify();
78 int _icq_HandleTimeout1(void *p
, va_list data
)
82 time_t current_time
= va_arg(data
, time_t);
83 icq_List
*expired_timeouts
= va_arg(data
, icq_List
*);
86 if (t
->expire_time
<= current_time
)
87 icq_ListEnqueue(expired_timeouts
, t
);
89 /* traversal is complete when we reach an expire time in the future */
95 int _icq_HandleTimeout2(void *p
, va_list data
)
100 /* maybe a previously executed timeout caused us to be deleted, so
101 * make sure we're still around */
102 if (icq_ListFind(icq_TimeoutList
, t
))
103 (t
->handler
)(t
->data
);
105 return 0; /* traverse entire list */
108 int _icq_HandleTimeout3(void *p
, va_list data
)
112 time_t current_time
= va_arg(data
, time_t);
114 if (t
->expire_time
<= current_time
)
117 icq_TimeoutDelete(t
);
119 t
->expire_time
= current_time
+ t
->length
;
122 /* traversal is complete when we reach an expire time in the future */
128 void icq_HandleTimeout()
130 time_t current_time
= time(NULL
);
131 icq_List
*expired_timeouts
= icq_ListNew();
133 icq_CurrentTimeout
= NULL
;
135 /* these three operations must be split up for the case where a
136 * timeout function causes timers to be deleted - this ensures
137 * we don't try to free any timers that have already been removed
138 * or corrupt the list traversal process */
140 /* determine which timeouts that have expired */
141 icq_ListTraverse(icq_TimeoutList
, _icq_HandleTimeout1
, current_time
,
144 /* call handler function for expired timeouts */
145 icq_ListTraverse(expired_timeouts
, _icq_HandleTimeout2
);
147 /* delete any expired timeouts */
148 icq_ListTraverse(icq_TimeoutList
, _icq_HandleTimeout3
, current_time
);
150 /* if there's any timeouts left, notify the library client */
151 if (icq_TimeoutList
->count
)
152 icq_TimeoutDoNotify();
154 icq_ListDelete(expired_timeouts
, NULL
);
157 void icq_TimeoutDoNotify()
159 time_t length
, current_time
= time(NULL
);
161 if (!icq_TimeoutList
->count
)
164 (*icq_SetTimeout
)(0);
168 icq_CurrentTimeout
= (icq_Timeout
*)icq_ListFirst(icq_TimeoutList
);
169 length
= icq_CurrentTimeout
->expire_time
- current_time
;
172 (*icq_SetTimeout
)(length
);