a15421ad2d325ba5c4dfe7081f82df58c21e6497
[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 "ootypes.h"
21 #include "ooDateTime.h"
22 #include "ooTimer.h"
23 #include "ootrace.h"
24
25 #define USECS_IN_SECS 1000000
26 #define NSECS_IN_USECS 1000
27
28 #ifndef MICROSEC
29 #define MICROSEC USECS_IN_SECS
30 #endif
31
32 /**
33  * This is a timer list used by test application chansetup only. 
34  */
35
36 DList g_TimerList;
37
38 OOTimer* ooTimerCreate 
39 (OOCTXT* pctxt, DList *pList, OOTimerCbFunc cb, OOUINT32 deltaSecs, void *data, 
40  OOBOOL reRegister)
41 {
42    OOTimer* pTimer = (OOTimer*) memAlloc (pctxt, sizeof(OOTimer));
43    if (0 == pTimer) return 0;
44
45    memset (pTimer, 0, (sizeof(OOTimer)));
46    pTimer->timeoutCB = cb;
47    pTimer->cbData = data;
48    pTimer->reRegister = reRegister;
49    pTimer->timeout.tv_sec  = deltaSecs;
50    pTimer->timeout.tv_usec = 0;
51
52    /* Compute the absolute time at which this timer should expire */
53
54    ooTimerComputeExpireTime (pTimer);
55
56    /* Insert this timer into the complete list */
57    if(pList)
58       ooTimerInsertEntry (pctxt, pList, pTimer);
59    else
60       ooTimerInsertEntry (pctxt, &g_TimerList, pTimer);
61
62    return pTimer;
63 }
64
65 void ooTimerComputeExpireTime (OOTimer* pTimer)
66 {
67    struct timeval tv;
68    ooGetTimeOfDay (&tv, 0);
69
70    /* Compute delta time to expiration */
71
72    pTimer->expireTime.tv_usec = tv.tv_usec + pTimer->timeout.tv_usec;
73    pTimer->expireTime.tv_sec  = tv.tv_sec  + pTimer->timeout.tv_sec;
74
75    while (pTimer->expireTime.tv_usec >= MICROSEC) {
76       pTimer->expireTime.tv_usec -= MICROSEC;
77       pTimer->expireTime.tv_sec++;
78    }
79 }
80
81 void ooTimerDelete (OOCTXT* pctxt, DList *pList, OOTimer* pTimer)
82 {
83    dListFindAndRemove (pctxt, pList, pTimer);
84    memFreePtr (pctxt, pTimer);
85 }
86
87 OOBOOL ooTimerExpired (OOTimer* pTimer)
88 {
89    struct timeval tvstr;
90    ooGetTimeOfDay (&tvstr, 0);
91
92    if (tvstr.tv_sec > pTimer->expireTime.tv_sec)
93       return TRUE;
94
95    if ((tvstr.tv_sec == pTimer->expireTime.tv_sec) &&
96        (tvstr.tv_usec > pTimer->expireTime.tv_usec))
97       return TRUE;
98
99    return FALSE;
100 }
101
102 void ooTimerFireExpired (OOCTXT* pctxt, DList *pList)
103 {
104    OOTimer* pTimer;
105    int ret = OO_OK;
106
107    while (pList->count > 0) {
108       pTimer = (OOTimer*) pList->head->data;
109
110       if (ooTimerExpired (pTimer)) {
111          /*
112           * Re-register before calling callback function in case it is
113           * a long duration callback.                                   
114           */
115          if (pTimer->reRegister) ooTimerReset (pctxt, pList, pTimer);
116
117          ret = (*pTimer->timeoutCB)(pTimer->cbData);
118
119          if (!pTimer->reRegister) {
120             ooTimerDelete (pctxt, pList, pTimer);
121          }
122       }
123       else break;
124    }
125
126    return (void)ret;
127 }
128
129 int ooTimerInsertEntry (OOCTXT* pctxt, DList *pList, OOTimer* pTimer)
130 {  DListNode* pNode;
131    OOTimer* p;
132    int i = 0;
133
134    for (pNode = pList->head; pNode != 0; pNode = pNode->next) {
135       p = (OOTimer*) pNode->data;
136       if (pTimer->expireTime.tv_sec  <  p->expireTime.tv_sec) break;
137       if (pTimer->expireTime.tv_sec  == p->expireTime.tv_sec &&
138           pTimer->expireTime.tv_usec <= p->expireTime.tv_usec) break;
139       i++;
140    }
141
142    dListInsertBefore (pctxt, pList, pNode, pTimer);
143
144    return i;
145 }
146
147 struct timeval* ooTimerNextTimeout (DList *pList, struct timeval* ptimeout)
148 {
149    OOTimer* ptimer;
150    struct timeval tvstr;
151
152    if (pList->count == 0) return 0;
153    ptimer = (OOTimer*) pList->head->data;
154
155    ooGetTimeOfDay (&tvstr, 0);
156
157    ptimeout->tv_sec = 
158       OOMAX ((int) 0, (int) (ptimer->expireTime.tv_sec - tvstr.tv_sec));   
159
160    ptimeout->tv_usec = ptimer->expireTime.tv_usec - tvstr.tv_usec;
161
162    while (ptimeout->tv_usec < 0) {
163       ptimeout->tv_sec--;
164       ptimeout->tv_usec += USECS_IN_SECS;
165    }
166
167    if (ptimeout->tv_sec < 0)
168       ptimeout->tv_sec = ptimeout->tv_usec = 0;
169
170    return (ptimeout);
171 }
172
173 /* 
174  * Reregister a timer entry.  This function is responsible for moving
175  * the current pointer in the timer list to the next element to be
176  * processed..
177  */
178 void ooTimerReset (OOCTXT* pctxt, DList *pList, OOTimer* pTimer)
179 {
180    if (pTimer->reRegister) {
181       dListFindAndRemove (pctxt, pList, pTimer);
182       ooTimerComputeExpireTime (pTimer);
183       ooTimerInsertEntry (pctxt, pList, pTimer);
184    }
185    else
186       ooTimerDelete (pctxt, pList, pTimer);
187 }
188
189 int ooCompareTimeouts(struct timeval *to1, struct timeval *to2)
190 {
191
192    if(to1->tv_sec > to2->tv_sec)   return 1;
193    if(to1->tv_sec < to2->tv_sec)   return -1;
194
195    if(to1->tv_usec > to2->tv_usec)   return 1;
196    if(to1->tv_usec < to2->tv_usec)   return -1;
197
198    return 0;
199 }