Imported Upstream version 1.1.0
[platform/upstream/iotivity.git] / extlibs / timer / timer.c
1 //******************************************************************
2 //
3 // Copyright 2014 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21
22
23 #define _BSD_SOURCE
24
25 #ifndef WITH_ARDUINO
26 #include <pthread.h>
27 #include <unistd.h>
28 #include <memory.h>
29 #include <stdlib.h>
30 #endif
31
32 #include <string.h>
33 #include <stdio.h>
34
35 #include "timer.h"
36
37 #define SECOND (1)
38
39 #define TIMEOUTS 10
40
41 #define TIMEOUT_USED   1
42 #define TIMEOUT_UNUSED  2
43
44 #ifndef WITH_ARDUINO
45 pthread_t thread_id = 0; // 0: initial thread id (meaningless)
46 #endif
47
48 struct timelist_t
49 {
50     int timeout_state;
51     time_t timeout_seconds;
52     time_t timeout_time;
53     void (*cb)();
54 } timeout_list[TIMEOUTS];
55
56 /*
57  * Return the number of seconds between before and after, (after - before).
58  * This must be async-signal safe, so it cannot use difftime().
59  */
60 time_t timespec_diff(const time_t after, const time_t before)
61 {
62     return after - before;
63 }
64
65 /*
66  * Add positive seconds to a timespec, nothing if seconds is negative.
67  */
68 void timespec_add(time_t * to, const time_t seconds)
69 {
70     if (to && seconds > 0)
71     {
72         (*to) += seconds;
73     }
74 }
75
76 #ifndef WITH_ARDUINO
77
78 long int getSeconds(struct tm* tp)
79 {
80     long int nInterval = 0;
81
82     nInterval = (tp->tm_hour * SECS_PER_HOUR);
83     nInterval += (tp->tm_min * SECS_PER_MIN);
84     nInterval += (tp->tm_sec * SECOND);
85
86     printf("%ld", nInterval);
87
88     return nInterval;
89 }
90
91 long int getRelativeSecondsOfDayofweek(int ia, int ib)
92 {
93     if( ia > ib )
94         return (((long int)(7 - (ib - ia))) * SECS_PER_DAY);
95
96     return (((long int)((ib - ia))) * SECS_PER_DAY);
97 }
98
99 long int getRelativeIntervalOfWeek(struct tm* tp)
100 {
101     time_t current_time;
102     struct tm* current, *midnight;
103     time_t delayed_time = 0;
104
105     time(&current_time);
106     current = localtime(&current_time);
107
108     if(current == NULL)
109     {
110         printf("ERROR; Getting local time fails\n");
111         return 0;
112     }
113
114     midnight = (struct tm* )malloc(sizeof(struct tm));
115
116     if(midnight == NULL)
117     {
118         printf("ERROR; Memory allocation fails\n");
119         return 0;
120     }
121
122     memcpy(midnight, current, sizeof(struct tm));
123
124     midnight->tm_hour = 0;
125     midnight->tm_min = 0;
126     midnight->tm_sec = 0;
127
128     // Seconds.
129     // Seconds from midnight.
130     delayed_time = current_time - mktime(midnight);
131     delayed_time = getRelativeSecondsOfDayofweek(current->tm_wday, tp->tm_wday) - delayed_time;
132     delayed_time = delayed_time + getSeconds(tp);
133
134     free(midnight);
135
136     return delayed_time;
137 }
138
139 long int getSecondsFromAbsTime(struct tm* tp)
140 {
141    time_t current_time;
142    time_t delayed_time = 0;
143
144    time(&current_time);
145    localtime(&current_time);
146
147    delayed_time = mktime(tp) - current_time;
148
149    return delayed_time;
150 }
151
152 time_t registerTimer(const time_t seconds, int *id, void *cb)
153 {
154     time_t now, then;
155     time_t next;
156     int i, idx;
157
158     if (0 == thread_id)
159     {
160         initThread();
161     }
162
163     if (seconds <= 0)
164         return -1 ;
165
166     // get the current time
167     time(&now);
168
169     for (idx = 0; idx < TIMEOUTS; ++idx)
170         if (!((timeout_list[idx].timeout_state & TIMEOUT_USED) & TIMEOUT_USED))
171             break;
172
173     if (TIMEOUTS == idx) // reach to end of timer list
174         return -1;
175
176     // idx th timeout will be used.
177     // Reset and set state of the timer
178     timeout_list[idx].timeout_state = 0;
179     timeout_list[idx].timeout_state |= TIMEOUT_USED;
180
181     // calculate when the timeout should fire
182     then = now;
183     timespec_add(&then, seconds);
184
185     timeout_list[idx].timeout_time = then;
186     timeout_list[idx].timeout_seconds = seconds;
187
188     // printf( "\nbefore timeout_list[idx].cb = %X\n", timeout_list[idx].cb);
189     timeout_list[idx].cb = cb;
190     // printf( " after timeout_list[idx].cb = %X\n", timeout_list[idx].cb);
191
192     // How long till the next timeout?
193     next = seconds;
194     for (i = 0; i < TIMEOUTS; i++)
195     {
196         if ((timeout_list[i].timeout_state & (TIMEOUT_USED | TIMEOUT_UNUSED)) == TIMEOUT_USED)
197         {
198             const time_t secs = timespec_diff(timeout_list[i].timeout_time, now);
199
200             if (secs >= 0 && secs < next)
201                 next = secs;
202         }
203     }
204
205     *id = idx;
206     /* Return the timeout number. */
207     return timeout_list[idx].timeout_time;
208 }
209
210 void unregisterTimer(int idx)
211 {
212     if( 0 <= idx && idx < TIMEOUTS)
213         timeout_list[idx].timeout_state = TIMEOUT_UNUSED;
214 }
215
216 void checkTimeout()
217 {
218     time_t now;
219     int i;
220
221     time(&now);
222
223     /* Check all timeouts that are used and armed, but not passed yet. */
224     for (i = 0; i < TIMEOUTS; i++)
225     {
226         if ((timeout_list[i].timeout_state & (TIMEOUT_USED | TIMEOUT_UNUSED)) == TIMEOUT_USED)
227         {
228             const time_t seconds = timespec_diff(timeout_list[i].timeout_time, now);
229
230             if (seconds <= 0)
231             {
232                 /* timeout [i] fires! */
233                 timeout_list[i].timeout_state = TIMEOUT_UNUSED;
234                 if (timeout_list[i].cb)
235                 {
236                     timeout_list[i].cb();
237                 }
238             }
239         }
240     }
241 }
242
243 void *loop(void *threadid)
244 {
245     while (1)
246     {
247         sleep(SECOND);
248         checkTimeout();
249     }
250
251     return NULL ;
252 }
253
254 int initThread()
255 {
256     int res;
257     long t = 0;
258
259     res = pthread_create(&thread_id, NULL, loop, (void *) t);
260
261     if (res)
262     {
263         printf("ERROR; return code from pthread_create() is %d\n", res);
264         return -1;
265     }
266
267     return 0;
268 }
269 #else   // WITH_ARDUINO
270 time_t timeToSecondsFromNow(tmElements_t *t_then)
271 {
272     time_t t, then;
273
274     t = now();
275     then = makeTime((*t_then));
276
277     return (time_t) (then - t);
278 }
279
280 time_t registerTimer(const time_t seconds, int *id,  void (*cb)())
281 {
282     time_t t, then;
283     time_t next;
284     int i, idx;
285
286     if (seconds <= 0)
287     return -1;
288
289     // get the current time
290     t = now();
291
292     for (idx = 0; idx < TIMEOUTS; ++idx)
293     if (!((timeout_list[idx].timeout_state & TIMEOUT_USED) & TIMEOUT_USED))
294     break;
295
296     if (TIMEOUTS == idx)// reach to end of timer list
297     return -1;
298
299     // idx th timeout will be used.
300     // Reset and set state of the timer
301     timeout_list[idx].timeout_state = 0;
302     timeout_list[idx].timeout_state |= TIMEOUT_USED;
303
304     // calculate when the timeout should fire
305     then = t;
306     timespec_add(&then, seconds);
307
308     timeout_list[idx].timeout_time = then;
309     timeout_list[idx].timeout_seconds = seconds;
310
311     // printf( "\nbefore timeout_list[idx].cb = %X\n", timeout_list[idx].cb);
312     timeout_list[idx].cb = cb;
313     // printf( " after timeout_list[idx].cb = %X\n", timeout_list[idx].cb);
314
315     // How long till the next timeout?
316     next = seconds;
317     for (i = 0; i < TIMEOUTS; i++)
318     {
319         if ((timeout_list[i].timeout_state & (TIMEOUT_USED | TIMEOUT_UNUSED))
320                 == TIMEOUT_USED)
321         {
322             const time_t secs = timespec_diff(timeout_list[i].timeout_time,
323                     t);
324
325             if (secs >= 0 && secs < next)
326             next = secs;
327         }
328     }
329
330     *id = idx;
331     /* Return the timeout number. */
332     return timeout_list[idx].timeout_time;
333 }
334
335 void unregisterTimer(int idx)
336 {
337     if( 0 <= idx && idx < TIMEOUTS)
338         timeout_list[idx].timeout_state = TIMEOUT_UNUSED;
339 }
340
341 void checkTimeout()
342 {
343     time_t t;
344     int i;
345
346     t = now();
347
348     /* Check all timeouts that are used and armed, but not passed yet. */
349     for (i = 0; i < TIMEOUTS; i++)
350     {
351         if ((timeout_list[i].timeout_state & (TIMEOUT_USED | TIMEOUT_UNUSED))
352                 == TIMEOUT_USED)
353         {
354             const time_t seconds = timespec_diff(timeout_list[i].timeout_time,
355                     t);
356
357             if (seconds <= 0)
358             {
359                 /* timeout [i] fires! */
360                 timeout_list[i].timeout_state = TIMEOUT_UNUSED;
361                 if (timeout_list[i].cb)
362                 {
363                     timeout_list[i].cb();
364                 }
365             }
366         }
367     }
368 }
369
370 #endif