Final fix memleaks in GkClient codes, same for Timer codes.
[asterisk/asterisk.git] / addons / ooh323c / src / ooTimer.c
1 /*
2  * Copyright (C) 2004-2005 by Objective Systems, Inc.
3  *
4  * This software is furnished under an open source license and may be 
5  * used and copied only in accordance with the terms of this license. 
6  * The text of the license may generally be found in the root 
7  * directory of this installation in the LICENSE.txt file.  It 
8  * can also be viewed online at the following URL:
9  *
10  *   http://www.obj-sys.com/open/license.html
11  *
12  * Any redistributions of this file including modified versions must 
13  * maintain this copyright notice.
14  *
15  *****************************************************************************/
16
17 #include "asterisk.h"
18 #include "asterisk/lock.h"
19
20 #include "ooDateTime.h"
21 #include "ooTimer.h"
22 #include "ootrace.h"
23
24 #define USECS_IN_SECS 1000000
25 #define NSECS_IN_USECS 1000
26
27 #ifndef MICROSEC
28 #define MICROSEC USECS_IN_SECS
29 #endif
30
31 /**
32  * This is a timer list used by test application chansetup only. 
33  */
34
35 DList g_TimerList;
36
37 OOTimer* ooTimerCreate 
38 (OOCTXT* pctxt, DList *pList, OOTimerCbFunc cb, OOUINT32 deltaSecs, void *data, 
39  OOBOOL reRegister)
40 {
41    OOTimer* pTimer = (OOTimer*) memAlloc (pctxt, sizeof(OOTimer));
42    if (0 == pTimer) return 0;
43
44    memset (pTimer, 0, (sizeof(OOTimer)));
45    pTimer->timeoutCB = cb;
46    pTimer->cbData = data;
47    pTimer->reRegister = reRegister;
48    pTimer->timeout.tv_sec  = deltaSecs;
49    pTimer->timeout.tv_usec = 0;
50
51    /* Compute the absolute time at which this timer should expire */
52
53    ooTimerComputeExpireTime (pTimer);
54
55    /* Insert this timer into the complete list */
56    if(pList)
57       ooTimerInsertEntry (pctxt, pList, pTimer);
58    else
59       ooTimerInsertEntry (pctxt, &g_TimerList, pTimer);
60
61    return pTimer;
62 }
63
64 void ooTimerComputeExpireTime (OOTimer* pTimer)
65 {
66    struct timeval tv;
67    ooGetTimeOfDay (&tv, 0);
68
69    /* Compute delta time to expiration */
70
71    pTimer->expireTime.tv_usec = tv.tv_usec + pTimer->timeout.tv_usec;
72    pTimer->expireTime.tv_sec  = tv.tv_sec  + pTimer->timeout.tv_sec;
73
74    while (pTimer->expireTime.tv_usec >= MICROSEC) {
75       pTimer->expireTime.tv_usec -= MICROSEC;
76       pTimer->expireTime.tv_sec++;
77    }
78 }
79
80 void ooTimerDelete (OOCTXT* pctxt, DList *pList, OOTimer* pTimer)
81 {
82    dListFindAndRemove (pctxt, pList, pTimer);
83    memFreePtr (pctxt, pTimer);
84 }
85
86 OOBOOL ooTimerExpired (OOTimer* pTimer)
87 {
88    struct timeval tvstr;
89    ooGetTimeOfDay (&tvstr, 0);
90
91    if (tvstr.tv_sec > pTimer->expireTime.tv_sec)
92       return TRUE;
93
94    if ((tvstr.tv_sec == pTimer->expireTime.tv_sec) &&
95        (tvstr.tv_usec > pTimer->expireTime.tv_usec))
96       return TRUE;
97
98    return FALSE;
99 }
100
101 void ooTimerFireExpired (OOCTXT* pctxt, DList *pList)
102 {
103    OOTimer* pTimer;
104    int stat;
105
106    while (pList->count > 0) {
107       pTimer = (OOTimer*) pList->head->data;
108
109       if (ooTimerExpired (pTimer)) {
110          /*
111           * Re-register before calling callback function in case it is
112           * a long duration callback.                                   
113           */
114          if (pTimer->reRegister) ooTimerReset (pctxt, pList, pTimer);
115
116          stat = (*pTimer->timeoutCB)(pTimer->cbData);
117
118          if (!pTimer->reRegister) {
119             ooTimerDelete (pctxt, pList, pTimer);
120          }
121       }
122       else break;
123    }
124 }
125
126 int ooTimerInsertEntry (OOCTXT* pctxt, DList *pList, OOTimer* pTimer)
127 {  DListNode* pNode;
128    OOTimer* p;
129    int i = 0;
130
131    for (pNode = pList->head; pNode != 0; pNode = pNode->next) {
132       p = (OOTimer*) pNode->data;
133       if (pTimer->expireTime.tv_sec  <  p->expireTime.tv_sec) break;
134       if (pTimer->expireTime.tv_sec  == p->expireTime.tv_sec &&
135           pTimer->expireTime.tv_usec <= p->expireTime.tv_usec) break;
136       i++;
137    }
138
139    dListInsertBefore (pctxt, pList, pNode, pTimer);
140
141    return i;
142 }
143
144 struct timeval* ooTimerNextTimeout (DList *pList, struct timeval* ptimeout)
145 {
146    OOTimer* ptimer;
147    struct timeval tvstr;
148
149    if (pList->count == 0) return 0;
150    ptimer = (OOTimer*) pList->head->data;
151
152    ooGetTimeOfDay (&tvstr, 0);
153
154    ptimeout->tv_sec = 
155       OOMAX ((int) 0, (int) (ptimer->expireTime.tv_sec - tvstr.tv_sec));   
156
157    ptimeout->tv_usec = ptimer->expireTime.tv_usec - tvstr.tv_usec;
158
159    while (ptimeout->tv_usec < 0) {
160       ptimeout->tv_sec--;
161       ptimeout->tv_usec += USECS_IN_SECS;
162    }
163
164    if (ptimeout->tv_sec < 0)
165       ptimeout->tv_sec = ptimeout->tv_usec = 0;
166
167    return (ptimeout);
168 }
169
170 /* 
171  * Reregister a timer entry.  This function is responsible for moving
172  * the current pointer in the timer list to the next element to be
173  * processed..
174  */
175 void ooTimerReset (OOCTXT* pctxt, DList *pList, OOTimer* pTimer)
176 {
177    if (pTimer->reRegister) {
178       dListFindAndRemove (pctxt, pList, pTimer);
179       ooTimerComputeExpireTime (pTimer);
180       ooTimerInsertEntry (pctxt, pList, pTimer);
181    }
182    else
183       ooTimerDelete (pctxt, pList, pTimer);
184 }
185
186 int ooCompareTimeouts(struct timeval *to1, struct timeval *to2)
187 {
188
189    if(to1->tv_sec > to2->tv_sec)   return 1;
190    if(to1->tv_sec < to2->tv_sec)   return -1;
191
192    if(to1->tv_usec > to2->tv_usec)   return 1;
193    if(to1->tv_usec < to2->tv_usec)   return -1;
194
195    return 0;
196 }