Imported Upstream version 1.0.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     midnight = (struct tm* )malloc(sizeof(struct tm));
108
109     if(midnight == NULL)
110     {
111         printf("ERROR; Memory allocation fails\n");
112         return 0;
113     }
114
115     memcpy(midnight, current, sizeof(struct tm));
116
117     midnight->tm_hour = 0;
118     midnight->tm_min = 0;
119     midnight->tm_sec = 0;
120
121     // Seconds.
122     // Seconds from midnight.
123     delayed_time = current_time - mktime(midnight);
124     delayed_time = getRelativeSecondsOfDayofweek(current->tm_wday, tp->tm_wday) - delayed_time;
125     delayed_time = delayed_time + getSeconds(tp);
126
127     free(midnight);
128
129     return delayed_time;
130 }
131
132 long int getSecondsFromAbsTime(struct tm* tp)
133 {
134    time_t current_time;
135    time_t delayed_time = 0;
136
137    time(&current_time);
138    localtime(&current_time);
139
140    delayed_time = mktime(tp) - current_time;
141
142    return delayed_time;
143 }
144
145 time_t registerTimer(const time_t seconds, int *id, void *cb)
146 {
147     time_t now, then;
148     time_t next;
149     int i, idx;
150
151     if (0 == thread_id)
152     {
153         initThread();
154     }
155
156     if (seconds <= 0)
157         return -1 ;
158
159     // get the current time
160     time(&now);
161
162     for (idx = 0; idx < TIMEOUTS; ++idx)
163         if (!((timeout_list[idx].timeout_state & TIMEOUT_USED) & TIMEOUT_USED))
164             break;
165
166     if (TIMEOUTS == idx) // reach to end of timer list
167         return -1;
168
169     // idx th timeout will be used.
170     // Reset and set state of the timer
171     timeout_list[idx].timeout_state = 0;
172     timeout_list[idx].timeout_state |= TIMEOUT_USED;
173
174     // calculate when the timeout should fire
175     then = now;
176     timespec_add(&then, seconds);
177
178     timeout_list[idx].timeout_time = then;
179     timeout_list[idx].timeout_seconds = seconds;
180
181     // printf( "\nbefore timeout_list[idx].cb = %X\n", timeout_list[idx].cb);
182     timeout_list[idx].cb = cb;
183     // printf( " after timeout_list[idx].cb = %X\n", timeout_list[idx].cb);
184
185     // How long till the next timeout?
186     next = seconds;
187     for (i = 0; i < TIMEOUTS; i++)
188     {
189         if ((timeout_list[i].timeout_state & (TIMEOUT_USED | TIMEOUT_UNUSED)) == TIMEOUT_USED)
190         {
191             const time_t secs = timespec_diff(timeout_list[i].timeout_time, now);
192
193             if (secs >= 0 && secs < next)
194                 next = secs;
195         }
196     }
197
198     *id = idx;
199     /* Return the timeout number. */
200     return timeout_list[idx].timeout_time;
201 }
202
203 void unregisterTimer(int idx)
204 {
205     if( 0 <= idx && idx < TIMEOUTS)
206         timeout_list[idx].timeout_state = TIMEOUT_UNUSED;
207 }
208
209 void checkTimeout()
210 {
211     time_t now;
212     int i;
213
214     time(&now);
215
216     /* Check all timeouts that are used and armed, but not passed yet. */
217     for (i = 0; i < TIMEOUTS; i++)
218     {
219         if ((timeout_list[i].timeout_state & (TIMEOUT_USED | TIMEOUT_UNUSED)) == TIMEOUT_USED)
220         {
221             const time_t seconds = timespec_diff(timeout_list[i].timeout_time, now);
222
223             if (seconds <= 0)
224             {
225                 /* timeout [i] fires! */
226                 timeout_list[i].timeout_state = TIMEOUT_UNUSED;
227                 if (timeout_list[i].cb)
228                 {
229                     timeout_list[i].cb();
230                 }
231             }
232         }
233     }
234 }
235
236 void *loop(void *threadid)
237 {
238     while (1)
239     {
240         sleep(SECOND);
241         checkTimeout();
242     }
243
244     return NULL ;
245 }
246
247 int initThread()
248 {
249     int res;
250     long t = 0;
251
252     res = pthread_create(&thread_id, NULL, loop, (void *) t);
253
254     if (res)
255     {
256         printf("ERROR; return code from pthread_create() is %d\n", res);
257         return -1;
258     }
259
260     return 0;
261 }
262 #else   // WITH_ARDUINO
263 time_t timeToSecondsFromNow(tmElements_t *t_then)
264 {
265     time_t t, then;
266
267     t = now();
268     then = makeTime((*t_then));
269
270     return (time_t) (then - t);
271 }
272
273 time_t registerTimer(const time_t seconds, int *id,  void (*cb)())
274 {
275     time_t t, then;
276     time_t next;
277     int i, idx;
278
279     if (seconds <= 0)
280     return -1;
281
282     // get the current time
283     t = now();
284
285     for (idx = 0; idx < TIMEOUTS; ++idx)
286     if (!((timeout_list[idx].timeout_state & TIMEOUT_USED) & TIMEOUT_USED))
287     break;
288
289     if (TIMEOUTS == idx)// reach to end of timer list
290     return -1;
291
292     // idx th timeout will be used.
293     // Reset and set state of the timer
294     timeout_list[idx].timeout_state = 0;
295     timeout_list[idx].timeout_state |= TIMEOUT_USED;
296
297     // calculate when the timeout should fire
298     then = t;
299     timespec_add(&then, seconds);
300
301     timeout_list[idx].timeout_time = then;
302     timeout_list[idx].timeout_seconds = seconds;
303
304     // printf( "\nbefore timeout_list[idx].cb = %X\n", timeout_list[idx].cb);
305     timeout_list[idx].cb = cb;
306     // printf( " after timeout_list[idx].cb = %X\n", timeout_list[idx].cb);
307
308     // How long till the next timeout?
309     next = seconds;
310     for (i = 0; i < TIMEOUTS; i++)
311     {
312         if ((timeout_list[i].timeout_state & (TIMEOUT_USED | TIMEOUT_UNUSED))
313                 == TIMEOUT_USED)
314         {
315             const time_t secs = timespec_diff(timeout_list[i].timeout_time,
316                     t);
317
318             if (secs >= 0 && secs < next)
319             next = secs;
320         }
321     }
322
323     *id = idx;
324     /* Return the timeout number. */
325     return timeout_list[idx].timeout_time;
326 }
327
328 void unregisterTimer(int idx)
329 {
330     if( 0 <= idx && idx < TIMEOUTS)
331         timeout_list[idx].timeout_state = TIMEOUT_UNUSED;
332 }
333
334 void checkTimeout()
335 {
336     time_t t;
337     int i;
338
339     t = now();
340
341     /* Check all timeouts that are used and armed, but not passed yet. */
342     for (i = 0; i < TIMEOUTS; i++)
343     {
344         if ((timeout_list[i].timeout_state & (TIMEOUT_USED | TIMEOUT_UNUSED))
345                 == TIMEOUT_USED)
346         {
347             const time_t seconds = timespec_diff(timeout_list[i].timeout_time,
348                     t);
349
350             if (seconds <= 0)
351             {
352                 /* timeout [i] fires! */
353                 timeout_list[i].timeout_state = TIMEOUT_UNUSED;
354                 if (timeout_list[i].cb)
355                 {
356                     timeout_list[i].cb();
357                 }
358             }
359         }
360     }
361 }
362
363 #endif