aboutsummaryrefslogtreecommitdiffstats
path: root/addons/ooh323c/src/ooTimer.c
blob: 9e7f7227a8ee9167eec8b0d0a7754d5a9e0237b0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/*
 * Copyright (C) 2004-2005 by Objective Systems, Inc.
 *
 * This software is furnished under an open source license and may be 
 * used and copied only in accordance with the terms of this license. 
 * The text of the license may generally be found in the root 
 * directory of this installation in the LICENSE.txt file.  It 
 * can also be viewed online at the following URL:
 *
 *   http://www.obj-sys.com/open/license.html
 *
 * Any redistributions of this file including modified versions must 
 * maintain this copyright notice.
 *
 *****************************************************************************/

#include "asterisk.h"
#include "asterisk/lock.h"

#include "ooDateTime.h"
#include "ooTimer.h"
#include "ootrace.h"

#define USECS_IN_SECS 1000000
#define NSECS_IN_USECS 1000

#ifndef MICROSEC
#define MICROSEC USECS_IN_SECS
#endif

/**
 * This is a timer list used by test application chansetup only. 
 */

DList g_TimerList;

OOTimer* ooTimerCreate 
(OOCTXT* pctxt, DList *pList, OOTimerCbFunc cb, OOUINT32 deltaSecs, void *data, 
 OOBOOL reRegister)
{
   OOTimer* pTimer = (OOTimer*) memAlloc (pctxt, sizeof(OOTimer));
   if (0 == pTimer) return 0;

   memset (pTimer, 0, (sizeof(OOTimer)));
   pTimer->timeoutCB = cb;
   pTimer->cbData = data;
   pTimer->reRegister = reRegister;
   pTimer->timeout.tv_sec  = deltaSecs;
   pTimer->timeout.tv_usec = 0;

   /* Compute the absolute time at which this timer should expire */

   ooTimerComputeExpireTime (pTimer);

   /* Insert this timer into the complete list */
   if(pList)
      ooTimerInsertEntry (pctxt, pList, pTimer);
   else
      ooTimerInsertEntry (pctxt, &g_TimerList, pTimer);

   return pTimer;
}

void ooTimerComputeExpireTime (OOTimer* pTimer)
{
   struct timeval tv;
   ooGetTimeOfDay (&tv, 0);

   /* Compute delta time to expiration */

   pTimer->expireTime.tv_usec = tv.tv_usec + pTimer->timeout.tv_usec;
   pTimer->expireTime.tv_sec  = tv.tv_sec  + pTimer->timeout.tv_sec;

   while (pTimer->expireTime.tv_usec >= MICROSEC) {
      pTimer->expireTime.tv_usec -= MICROSEC;
      pTimer->expireTime.tv_sec++;
   }
}

void ooTimerDelete (OOCTXT* pctxt, DList *pList, OOTimer* pTimer)
{
   dListFindAndRemove (pList, pTimer);
   memFreePtr (pctxt, pTimer);
}

OOBOOL ooTimerExpired (OOTimer* pTimer)
{
   struct timeval tvstr;
   ooGetTimeOfDay (&tvstr, 0);

   if (tvstr.tv_sec > pTimer->expireTime.tv_sec)
      return TRUE;

   if ((tvstr.tv_sec == pTimer->expireTime.tv_sec) &&
       (tvstr.tv_usec > pTimer->expireTime.tv_usec))
      return TRUE;

   return FALSE;
}

void ooTimerFireExpired (OOCTXT* pctxt, DList *pList)
{
   OOTimer* pTimer;
   int stat;

   while (pList->count > 0) {
      pTimer = (OOTimer*) pList->head->data;

      if (ooTimerExpired (pTimer)) {
         /*
          * Re-register before calling callback function in case it is
          * a long duration callback.                                   
          */
         if (pTimer->reRegister) ooTimerReset (pctxt, pList, pTimer);

         stat = (*pTimer->timeoutCB)(pTimer->cbData);

         if (0 != stat || !pTimer->reRegister) {
            ooTimerDelete (pctxt, pList, pTimer);
         }
      }
      else break;
   }
}

int ooTimerInsertEntry (OOCTXT* pctxt, DList *pList, OOTimer* pTimer)
{  DListNode* pNode;
   OOTimer* p;
   int i = 0;

   for (pNode = pList->head; pNode != 0; pNode = pNode->next) {
      p = (OOTimer*) pNode->data;
      if (pTimer->expireTime.tv_sec  <  p->expireTime.tv_sec) break;
      if (pTimer->expireTime.tv_sec  == p->expireTime.tv_sec &&
          pTimer->expireTime.tv_usec <= p->expireTime.tv_usec) break;
      i++;
   }

   dListInsertBefore (pctxt, pList, pNode, pTimer);

   return i;
}

struct timeval* ooTimerNextTimeout (DList *pList, struct timeval* ptimeout)
{
   OOTimer* ptimer;
   struct timeval tvstr;

   if (pList->count == 0) return 0;
   ptimer = (OOTimer*) pList->head->data;

   ooGetTimeOfDay (&tvstr, 0);

   ptimeout->tv_sec = 
      OOMAX ((int) 0, (int) (ptimer->expireTime.tv_sec - tvstr.tv_sec));   

   ptimeout->tv_usec = ptimer->expireTime.tv_usec - tvstr.tv_usec;

   while (ptimeout->tv_usec < 0) {
      ptimeout->tv_sec--;
      ptimeout->tv_usec += USECS_IN_SECS;
   }

   if (ptimeout->tv_sec < 0)
      ptimeout->tv_sec = ptimeout->tv_usec = 0;

   return (ptimeout);
}

/* 
 * Reregister a timer entry.  This function is responsible for moving
 * the current pointer in the timer list to the next element to be
 * processed..
 */
void ooTimerReset (OOCTXT* pctxt, DList *pList, OOTimer* pTimer)
{
   if (pTimer->reRegister) {
      dListFindAndRemove (pList, pTimer);
      ooTimerComputeExpireTime (pTimer);
      ooTimerInsertEntry (pctxt, pList, pTimer);
   }
   else
      ooTimerDelete (pctxt, pList, pTimer);
}

int ooCompareTimeouts(struct timeval *to1, struct timeval *to2)
{

   if(to1->tv_sec > to2->tv_sec)   return 1;
   if(to1->tv_sec < to2->tv_sec)   return -1;

   if(to1->tv_usec > to2->tv_usec)   return 1;
   if(to1->tv_usec < to2->tv_usec)   return -1;

   return 0;
}