Timerlib Integrated with Wheel Timer

This commit is contained in:
Abhishek Sagar
2020-10-14 22:58:55 -07:00
parent 804e15eadc
commit f64c44275c
5 changed files with 147 additions and 83 deletions

View File

@@ -5,10 +5,7 @@
#include <unistd.h> #include <unistd.h>
#include <time.h> #include <time.h>
#include <assert.h> #include <assert.h>
#include "timerlib.h"
#define TH_JOINABLE 1
#define TH_DETACHED 0
int int
insert_wt_elem_in_slot(void *data1, void *data2){ insert_wt_elem_in_slot(void *data1, void *data2){
@@ -25,25 +22,6 @@ insert_wt_elem_in_slot(void *data1, void *data2){
return 0; return 0;
} }
wheel_timer_t*
init_wheel_timer(int wheel_size, int clock_tic_interval){
wheel_timer_t *wt = calloc(1, sizeof(wheel_timer_t) +
(wheel_size * sizeof(slotlist_t)));
wt->clock_tic_interval = clock_tic_interval;
wt->wheel_size = wheel_size;
memset(&(wt->wheel_thread), 0, sizeof(wheel_timer_t));
int i = 0;
for(; i < wheel_size; i++){
init_glthread(WT_SLOTLIST_HEAD(wt, i));
pthread_mutex_init(WT_SLOTLIST_MUTEX(wt, i), NULL);
}
wt->no_of_wt_elem = 0;
return wt;
}
static void static void
process_wt_reschedule_slotlist(wheel_timer_t *wt){ process_wt_reschedule_slotlist(wheel_timer_t *wt){
@@ -100,9 +78,8 @@ process_wt_reschedule_slotlist(wheel_timer_t *wt){
WT_UNLOCK_SLOT_LIST(WT_GET_RESCHD_SLOTLIST(wt)); WT_UNLOCK_SLOT_LIST(WT_GET_RESCHD_SLOTLIST(wt));
} }
static void
static void * wheel_fn(Timer_t *timer, void *arg){
wheel_fn(void *arg){
wheel_timer_t *wt = (wheel_timer_t *)arg; wheel_timer_t *wt = (wheel_timer_t *)arg;
wheel_timer_elem_t *wt_elem = NULL; wheel_timer_elem_t *wt_elem = NULL;
@@ -110,16 +87,12 @@ wheel_fn(void *arg){
slotlist_t *slot_list = NULL; slotlist_t *slot_list = NULL;
glthread_t *curr; glthread_t *curr;
while(1){
wt->current_clock_tic++; wt->current_clock_tic++;
if(wt->current_clock_tic == wt->wheel_size){ if(wt->current_clock_tic == wt->wheel_size){
wt->current_clock_tic = 0; wt->current_clock_tic = 0;
wt->current_cycle_no++; wt->current_cycle_no++;
} }
sleep(wt->clock_tic_interval);
slot_list = WT_SLOTLIST(wt, wt->current_clock_tic); slot_list = WT_SLOTLIST(wt, wt->current_clock_tic);
absolute_slot_no = GET_WT_CURRENT_ABS_SLOT_NO(wt); absolute_slot_no = GET_WT_CURRENT_ABS_SLOT_NO(wt);
@@ -155,10 +128,36 @@ wheel_fn(void *arg){
break; break;
} ITERATE_GLTHREAD_END(slot_list, curr) } ITERATE_GLTHREAD_END(slot_list, curr)
process_wt_reschedule_slotlist(wt); process_wt_reschedule_slotlist(wt);
}
return NULL;
} }
wheel_timer_t*
init_wheel_timer(int wheel_size, int clock_tic_interval){
wheel_timer_t *wt = calloc(1, sizeof(wheel_timer_t) +
(wheel_size * sizeof(slotlist_t)));
wt->clock_tic_interval = clock_tic_interval;
wt->wheel_size = wheel_size;
wt->wheel_thread = setup_timer(wheel_fn,
wt->clock_tic_interval * 1000,
wt->clock_tic_interval * 1000,
0,
(void *)wt,
false);
int i = 0;
for(; i < wheel_size; i++){
init_glthread(WT_SLOTLIST_HEAD(wt, i));
pthread_mutex_init(WT_SLOTLIST_MUTEX(wt, i), NULL);
}
wt->no_of_wt_elem = 0;
return wt;
}
static void static void
_wt_elem_reschedule(wheel_timer_t *wt, _wt_elem_reschedule(wheel_timer_t *wt,
wheel_timer_elem_t *wt_elem, wheel_timer_elem_t *wt_elem,
@@ -179,12 +178,14 @@ _wt_elem_reschedule(wheel_timer_t *wt,
case WTELEM_DELETE: case WTELEM_DELETE:
wt_elem->new_time_interval = new_time_interval; wt_elem->new_time_interval = new_time_interval;
pause_timer(wt->wheel_thread);
WT_LOCK_SLOT_LIST(WT_GET_RESCHD_SLOTLIST(wt)); WT_LOCK_SLOT_LIST(WT_GET_RESCHD_SLOTLIST(wt));
wt_elem->opcode = opcode; wt_elem->opcode = opcode;
remove_glthread(&wt_elem->reschedule_glue); remove_glthread(&wt_elem->reschedule_glue);
glthread_add_next(WT_GET_RESCHD_SLOTLIST_HEAD(wt), glthread_add_next(WT_GET_RESCHD_SLOTLIST_HEAD(wt),
&wt_elem->reschedule_glue); &wt_elem->reschedule_glue);
WT_UNLOCK_SLOT_LIST(WT_GET_RESCHD_SLOTLIST(wt)); WT_UNLOCK_SLOT_LIST(WT_GET_RESCHD_SLOTLIST(wt));
resume_timer(wt->wheel_thread);
break; break;
default: default:
assert(0); assert(0);
@@ -300,11 +301,7 @@ print_wheel_timer(wheel_timer_t *wt){
void void
start_wheel_timer(wheel_timer_t *wt){ start_wheel_timer(wheel_timer_t *wt){
if (pthread_create(&wt->wheel_thread, NULL, wheel_fn, (void*)wt)) start_timer(wt->wheel_thread);
{
printf("Wheel Timer Thread initialization failed, exiting ... \n");
exit(0);
}
} }
void void
@@ -336,3 +333,11 @@ hrs_min_sec_format(unsigned int seconds){
return time_f; return time_f;
} }
void
cancel_wheel_timer(wheel_timer_t *wt){
if(wt->wheel_thread){
cancel_timer(wt->wheel_thread);
}
}

View File

@@ -2,6 +2,7 @@
#define __WHEEL_TIMER__ #define __WHEEL_TIMER__
#include <pthread.h> #include <pthread.h>
#include "timerlib.h"
#include "gluethread/glthread.h" #include "gluethread/glthread.h"
typedef struct _wheel_timer_elem_t wheel_timer_elem_t; typedef struct _wheel_timer_elem_t wheel_timer_elem_t;
@@ -45,7 +46,7 @@ typedef struct _wheel_timer_t {
int clock_tic_interval; int clock_tic_interval;
int wheel_size; int wheel_size;
int current_cycle_no; int current_cycle_no;
pthread_t wheel_thread; Timer_t *wheel_thread;
slotlist_t reschd_list; slotlist_t reschd_list;
unsigned int no_of_wt_elem; unsigned int no_of_wt_elem;
slotlist_t slotlist[0]; slotlist_t slotlist[0];

View File

@@ -0,0 +1,53 @@
#include <stdio.h>
#include "WheelTimer.h"
#include <string.h>
#define WHEEL_SIZE 10
#define WHEEL_TIMER_CLOCK_TIC_INTERVAL 1
/* Application routine to be (indirectly) invoked by Wheel timer.
* It could be of any prototype*/
void
print_hello(char *S){
printf("%s\n", S);
}
/* But Only routines (Events) which have prototype : void *(fn)(void *arg, int arg_size)
* could be registered with wheel timer. Therefore, we need to encapsulate
* the actual routine print_hello() to be invoked inside the routine of
* void *(fn)(void *arg, int arg_size) prototype. It is the wrapper which will be registered
* with wheel timer and invoked by wheel timer. We will unwrap the argument and invoke the actual
* appln routine with correct arguments. This technique is called 'Masking of routines'*/
void wrapper_print_hello(void *arg, int arg_size){
char *S = (char *)arg;
print_hello(S);
}
int
main(int argc, char **argv){
/*create a wheel timer object*/
wheel_timer_t *wt = init_wheel_timer(WHEEL_SIZE, WHEEL_TIMER_CLOCK_TIC_INTERVAL);
/*start the wheel timer thread*/
start_wheel_timer(wt);
/*Now Wheel timer has started running in a separte thread.
* Register the events to be triggered with Wheel timer now.*/
wheel_timer_elem_t * wt_elem =
register_app_event(wt, wrapper_print_hello, "MyString",
strlen("MyString"),
5, /*wrapper_print_hello fn will be called after every 5 seconds*/
1); /*1 indefinitely, 0 only once : call for wrapper_print_hello*/
wt_elem =
register_app_event(wt, wrapper_print_hello, "Udemy",
strlen("Udemy"),
3, /*wrapper_print_hello fn will be called after every 5 seconds*/
1); /*1 indefinitely, 0 only once : call for wrapper_print_hello*/
/*stop the main program from gettin terminated, otherwise wheel timer
* thread we created will also get terminated*/
scanf("\n");
return 0;
}

View File

@@ -3,3 +3,7 @@ rm *exe
gcc -g -c timerlib.c -o timerlib.o gcc -g -c timerlib.c -o timerlib.o
gcc -g -c timerlib_test.c -o timerlib_test.o gcc -g -c timerlib_test.c -o timerlib_test.o
gcc -g timerlib.o timerlib_test.o -o exe -lrt gcc -g timerlib.o timerlib_test.o -o exe -lrt
gcc -g -c WheelTimer.c -o WheelTimer.o
gcc -g -c WheelTimerDemo.c -o WheelTimerDemo.o
gcc -g -c gluethread/glthread.c -o gluethread/glthread.o
gcc -g WheelTimerDemo.o WheelTimer.o timerlib.o gluethread/glthread.o -o WheelTimerDemo.exe -lrt

View File

@@ -183,7 +183,8 @@ cancel_timer(Timer_t *timer){
void void
pause_timer(Timer_t *timer){ pause_timer(Timer_t *timer){
assert(timer->timer_state == TIMER_RUNNING); if ( timer_get_current_state(timer) == TIMER_PAUSED)
return;
timer->time_remaining = timer->time_remaining =
timer_get_time_remaining_in_mill_sec(timer); timer_get_time_remaining_in_mill_sec(timer);