Timer lib Dev

This commit is contained in:
Abhishek Sagar
2020-10-13 06:36:25 -07:00
parent bb256bf9c8
commit f2859d2b8f
4 changed files with 168 additions and 23 deletions

View File

@@ -0,0 +1,5 @@
rm *o
rm *exe
gcc -g -c timerlib.c -o timerlib.o
gcc -g -c timerlib_test.c -o timerlib_test.o
gcc -g timerlib.o timerlib_test.o -o exe -lrt

View File

@@ -23,7 +23,7 @@
#include <errno.h> #include <errno.h>
#include "timerlib.h" #include "timerlib.h"
static unsigned long unsigned long
timespec_to_millisec( timespec_to_millisec(
struct timespec *time){ struct timespec *time){
@@ -34,7 +34,7 @@ timespec_to_millisec(
return milli_sec; return milli_sec;
} }
static void void
timer_fill_itimerspec(struct timespec *ts, timer_fill_itimerspec(struct timespec *ts,
unsigned long msec) { unsigned long msec) {
@@ -54,13 +54,23 @@ static void
timer_callback_wrapper(union sigval arg){ timer_callback_wrapper(union sigval arg){
Timer_t *timer = (Timer_t *)(arg.sival_ptr); Timer_t *timer = (Timer_t *)(arg.sival_ptr);
timer->invocation_counter++; timer->invocation_counter++;
if(timer->thresdhold && if(timer->thresdhold &&
(timer->invocation_counter > timer->thresdhold)){ (timer->invocation_counter > timer->thresdhold)){
cancel_timer(timer); cancel_timer(timer);
return; return;
} }
(timer->cb)(timer, timer->user_arg); (timer->cb)(timer, timer->user_arg);
if(timer->exponential_backoff){
assert(timer->exp_back_off_time);
reschedule_timer(timer,
timer->exp_back_off_time *= 2, 0);
}
} }
@@ -72,8 +82,8 @@ setup_timer(
unsigned long exp_timer, /* First expiration time interval in msec */ unsigned long exp_timer, /* First expiration time interval in msec */
unsigned long sec_exp_timer, /* Subsequent expiration time interval in msec */ unsigned long sec_exp_timer, /* Subsequent expiration time interval in msec */
uint32_t threshold, /* Max no of expirations, 0 for infinite*/ uint32_t threshold, /* Max no of expirations, 0 for infinite*/
void *user_arg){ /* Arg to timer callback */ void *user_arg, /* Arg to timer callback */
bool exponential_backoff){ /* Is Timer Exp backoff*/
Timer_t *timer = calloc(1, sizeof(Timer_t)); Timer_t *timer = calloc(1, sizeof(Timer_t));
timer->posix_timer = calloc(1, sizeof(timer_t)); timer->posix_timer = calloc(1, sizeof(timer_t));
@@ -84,6 +94,7 @@ setup_timer(
timer->cb = timer_cb; timer->cb = timer_cb;
timer->thresdhold = threshold; timer->thresdhold = threshold;
timer->timer_state = TIMER_INIT; timer->timer_state = TIMER_INIT;
timer->exponential_backoff = exponential_backoff;
/* Sanity checks */ /* Sanity checks */
assert(timer->cb); /* Mandatory */ assert(timer->cb); /* Mandatory */
@@ -102,8 +113,15 @@ setup_timer(
assert(rc >= 0); assert(rc >= 0);
timer_fill_itimerspec(&timer->ts.it_value, timer->exp_timer); timer_fill_itimerspec(&timer->ts.it_value, timer->exp_timer);
timer_fill_itimerspec(&timer->ts.it_interval, timer->sec_exp_timer);
if(!timer->exponential_backoff){
timer_fill_itimerspec(&timer->ts.it_interval, timer->sec_exp_timer);
timer->exp_back_off_time = 0;
}
else{
timer->exp_back_off_time = timespec_to_millisec(&timer->ts.it_value);
timer_fill_itimerspec(&timer->ts.it_interval, 0);
}
return timer; return timer;
} }
@@ -142,6 +160,7 @@ cancel_timer(Timer_t *timer){
timer_fill_itimerspec(&timer->ts.it_value, 0); timer_fill_itimerspec(&timer->ts.it_value, 0);
timer_fill_itimerspec(&timer->ts.it_interval, 0); timer_fill_itimerspec(&timer->ts.it_interval, 0);
timer->time_remaining = 0; timer->time_remaining = 0;
timer->invocation_counter = 0;
start_timer(timer); start_timer(timer);
timer->timer_state = TIMER_CANCELLED; timer->timer_state = TIMER_CANCELLED;
} }
@@ -156,9 +175,7 @@ pause_timer(Timer_t *timer){
timer_get_time_remaining_in_mill_sec(timer); timer_get_time_remaining_in_mill_sec(timer);
timer_fill_itimerspec(&timer->ts.it_value, 0); timer_fill_itimerspec(&timer->ts.it_value, 0);
timer_fill_itimerspec(&timer->ts.it_interval, 0);
/* Do not reset the interval */
//timer_fill_itimerspec(&timer->ts.it_interval, 0);
start_timer(timer); start_timer(timer);
@@ -172,9 +189,9 @@ resume_timer(Timer_t *timer){
assert(timer->timer_state == TIMER_PAUSED); assert(timer->timer_state == TIMER_PAUSED);
timer_fill_itimerspec(&timer->ts.it_value, timer->time_remaining); timer_fill_itimerspec(&timer->ts.it_value, timer->time_remaining);
timer_fill_itimerspec(&timer->ts.it_interval, timer->sec_exp_timer);
timer->time_remaining = 0; timer->time_remaining = 0;
start_timer(timer); start_timer(timer);
timer->timer_state = TIMER_RUNNING;
} }
unsigned long unsigned long
@@ -207,40 +224,61 @@ timer_get_time_remaining_in_mill_sec(Timer_t *timer){
void void
restart_timer(Timer_t *timer){ restart_timer(Timer_t *timer){
if(timer->timer_state != TIMER_PAUSED || assert(timer->timer_state != TIMER_DELETED);
timer->timer_state != TIMER_RUNNING) {
assert(0);
}
cancel_timer(timer); cancel_timer(timer);
timer_fill_itimerspec(&timer->ts.it_value, timer->exp_timer); timer_fill_itimerspec(&timer->ts.it_value, timer->exp_timer);
if(!timer->exponential_backoff)
timer_fill_itimerspec(&timer->ts.it_interval, timer->sec_exp_timer); timer_fill_itimerspec(&timer->ts.it_interval, timer->sec_exp_timer);
else
timer_fill_itimerspec(&timer->ts.it_interval, 0);
timer->invocation_counter = 0; timer->invocation_counter = 0;
timer->time_remaining = 0; timer->time_remaining = 0;
timer->exp_back_off_time = timer->exp_timer;
start_timer(timer); start_timer(timer);
} }
int void
reschedule_timer(Timer_t *timer, reschedule_timer(Timer_t *timer,
unsigned long exp_ti, unsigned long exp_ti,
unsigned long sec_exp_ti){ unsigned long sec_exp_ti){
uint32_t invocation_counter;
if(timer->timer_state == TIMER_DELETED) assert(0); if(timer->timer_state == TIMER_DELETED) assert(0);
invocation_counter = timer->invocation_counter;
if(timer->timer_state != TIMER_CANCELLED) { if(timer->timer_state != TIMER_CANCELLED) {
cancel_timer(timer); cancel_timer(timer);
} }
timer->exp_timer = exp_ti; timer->invocation_counter = invocation_counter;
timer->sec_exp_timer = sec_exp_ti;
timer->invocation_counter = 0;
timer_fill_itimerspec(&timer->ts.it_value, exp_ti); timer_fill_itimerspec(&timer->ts.it_value, exp_ti);
timer_fill_itimerspec(&timer->ts.it_interval, sec_exp_ti);
if(!timer->exponential_backoff){
timer_fill_itimerspec(&timer->ts.it_interval, sec_exp_ti);
}
else{
timer_fill_itimerspec(&timer->ts.it_interval, 0);
timer->exp_back_off_time = exp_ti;
}
timer->time_remaining = 0; timer->time_remaining = 0;
start_timer(timer); start_timer(timer);
timer->timer_state = TIMER_RUNNING; }
void
print_timer(Timer_t *timer){
printf("Counter = %u, time remaining = %lu, state = %d\n",
timer->invocation_counter,
timer_get_time_remaining_in_mill_sec(timer),
timer_get_current_state(timer));
} }

View File

@@ -24,6 +24,7 @@
#include <unistd.h> #include <unistd.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
typedef enum{ typedef enum{
@@ -43,12 +44,14 @@ typedef struct Timer_{
unsigned long sec_exp_timer; /* in milli-sec */ unsigned long sec_exp_timer; /* in milli-sec */
uint32_t thresdhold; /* No of times to invoke the timer callback */ uint32_t thresdhold; /* No of times to invoke the timer callback */
void (*cb)(struct Timer_ *, void *); /* Timer Callback */ void (*cb)(struct Timer_ *, void *); /* Timer Callback */
bool exponential_backoff;
/* place holder value to store /* place holder value to store
* dynamic attributes of timer */ * dynamic attributes of timer */
unsigned long time_remaining; /* Time left for paused timer for next expiration */ unsigned long time_remaining; /* Time left for paused timer for next expiration */
uint32_t invocation_counter; uint32_t invocation_counter;
struct itimerspec ts; struct itimerspec ts;
unsigned long exp_back_off_time;
TIMER_STATE_T timer_state; TIMER_STATE_T timer_state;
} Timer_t; } Timer_t;
@@ -65,7 +68,24 @@ setup_timer(
/* Max no of expirations, 0 for infinite*/ /* Max no of expirations, 0 for infinite*/
uint32_t, uint32_t,
/* Arg to timer callback */ /* Arg to timer callback */
void *); void *,
/* Is timer Exp back off */
bool);
static inline void
timer_delete_user_data(Timer_t *timer){
if(timer->user_arg) {
free(timer->user_arg);
timer->user_arg = NULL;
}
}
static inline TIMER_STATE_T
timer_get_current_state(Timer_t *timer){
return timer->timer_state;
}
void void
start_timer(Timer_t *timer); start_timer(Timer_t *timer);
@@ -92,8 +112,19 @@ timer_get_time_remaining_in_mill_sec(Timer_t *timer);
void void
restart_timer(Timer_t *timer); restart_timer(Timer_t *timer);
int void
reschedule_timer(Timer_t *timer, reschedule_timer(Timer_t *timer,
unsigned long exp_ti, unsigned long exp_ti,
unsigned long sec_exp_ti); unsigned long sec_exp_ti);
void
print_timer(Timer_t *timer);
unsigned long
timespec_to_millisec(
struct timespec *time);
void
timer_fill_itimerspec(struct timespec *ts,
unsigned long msec);
#endif /* __TIMER_WRAP__ */ #endif /* __TIMER_WRAP__ */

View File

@@ -0,0 +1,71 @@
#include <stdio.h>
#include "timerlib.h"
static void
app_cb(Timer_t *timer, void *user_data){
time_t t;
time(&t);
printf("%s ",ctime(&t));
printf("%s() invoked ... name = %s, counter = %u, Threshold = %u, next fire time = %lu\n",
__FUNCTION__, (char *)user_data, timer->invocation_counter,
timer->thresdhold, timespec_to_millisec(&timer->ts.it_value));
}
int
main(int argc, char **argv){
char *name = "Abhishek";
Timer_t *timer = setup_timer(app_cb, 1000 , 1000, 4, name, true);
start_timer(timer);
printf("1. Pause Timer\n");
printf("2. Resume Timer\n");
printf("3. Restart timer\n");
printf("4. Reschedule timer\n");
printf("5. Delete timer\n");
printf("6. Cancel Timer\n");
printf("7. Get Remaining Time\n");
printf("8. Print Timer State\n");
int choice;
choice = 0;
while(1){
scanf("%d", &choice);
switch(choice){
case 1:
pause_timer(timer);
break;
case 2:
resume_timer(timer);
break;
case 3:
restart_timer(timer);
break;
case 4:
reschedule_timer(timer,
timer->exp_timer,
timer->sec_exp_timer);
break;
case 5:
delete_timer(timer);
break;
case 6:
cancel_timer(timer);
break;
case 7:
printf("Rem Time = %lu\n", timer_get_time_remaining_in_mill_sec(timer));
break;
case 8:
print_timer(timer);
break;
deafault: ;
}
}
pause();
return 0;
}