Updated base WheelTimer (WheelTimer.c, WheelTimer.h) files to point to

latest WheelTimer code.
This commit is contained in:
Abhishek Sagar
2020-10-28 13:06:25 -07:00
parent 0d5a0dff84
commit 22b740a60d
7 changed files with 723 additions and 145 deletions

View File

@@ -4,141 +4,253 @@
#include <memory.h>
#include <unistd.h>
#include <time.h>
#include "LinkedListApi.h"
#include <assert.h>
#define TH_JOINABLE 1
#define TH_DETACHED 0
extern blocked_pool_t gl_blocked_th_pool;
int
insert_wt_elem_in_slot(void *data1, void *data2){
wheel_timer_elem_t *wt_elem1 = (wheel_timer_elem_t *)data1;
wheel_timer_elem_t *wt_elem2 = (wheel_timer_elem_t *)data2;
if(wt_elem1->execute_cycle_no < wt_elem2->execute_cycle_no)
return -1;
if(wt_elem1->execute_cycle_no > wt_elem2->execute_cycle_no)
return 1;
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(ll_t *));
(wheel_size * sizeof(slotlist_t)));
wt->clock_tic_interval = clock_tic_interval;
wt->wheel_size = wheel_size;
pthread_mutex_init(&wt->wheel_timer_mutex, NULL);
wt->wheel_thread = calloc(1, sizeof(_pthread_t));
pthread_init(wt->wheel_thread, 0, TH_DETACHED);
memset(&(wt->wheel_thread), 0, sizeof(wheel_timer_t));
int i = 0;
for(; i < wheel_size; i++)
wt->slots[i] = init_singly_ll();
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;
}
void
de_register_app_event(wheel_timer_t *wt, wheel_timer_elem_t *wt_elem){
if(!wt_elem) return;
pause_wheel_timer(wt);
wt_elem->is_alive = 0;
resume_wheel_timer(wt);
static void
process_wt_reschedule_slotlist(wheel_timer_t *wt){
glthread_t *curr;
wheel_timer_elem_t *wt_elem;
WT_LOCK_SLOT_LIST(WT_GET_RESCHD_SLOTLIST(wt));
if(WT_IS_SLOTLIST_EMPTY(WT_GET_RESCHD_SLOTLIST(wt))){
WT_UNLOCK_SLOT_LIST(WT_GET_RESCHD_SLOTLIST(wt));
return;
}
ITERATE_GLTHREAD_BEGIN(WT_GET_RESCHD_SLOTLIST_HEAD(wt), curr){
wt_elem = glthread_reschedule_glue_to_wt_elem(curr);
remove_glthread(&wt_elem->glue);
wt_elem->slotlist_head = NULL;
switch(wt_elem->opcode){
case WTELEM_CREATE:
case WTELEM_RESCHED:
{
assert(wt_elem->app_callback);
wt_elem->time_interval = wt_elem->new_time_interval;
int absolute_slot_no = GET_WT_CURRENT_ABS_SLOT_NO(wt);
int next_abs_slot_no = absolute_slot_no +
(wt_elem->time_interval/wt->clock_tic_interval);
int next_cycle_no = next_abs_slot_no / wt->wheel_size;
int next_slot_no = next_abs_slot_no % wt->wheel_size;
wt_elem->execute_cycle_no = next_cycle_no;
wt_elem->slot_no = next_slot_no;
glthread_priority_insert(WT_SLOTLIST_HEAD(wt, wt_elem->slot_no),
&wt_elem->glue,
insert_wt_elem_in_slot,
(unsigned long)&((wheel_timer_elem_t *)0)->glue);
wt_elem->slotlist_head = WT_SLOTLIST(wt, wt_elem->slot_no);
remove_glthread(&wt_elem->reschedule_glue);
wt_elem->N_scheduled++;
if(wt_elem->opcode == WTELEM_CREATE){
wt->no_of_wt_elem++;
}
wt_elem->opcode = WTELEM_SCHEDULED;
}
break;
case WTELEM_DELETE:
remove_glthread(&wt_elem->reschedule_glue);
free_wheel_timer_element(wt_elem);
wt->no_of_wt_elem--;
break;
default:
assert(0);
}
}ITERATE_GLTHREAD_END(WT_GET_RESCHD_SLOTLIST_HEAD(wt), curr)
WT_UNLOCK_SLOT_LIST(WT_GET_RESCHD_SLOTLIST(wt));
}
static void*
static void *
wheel_fn(void *arg){
wheel_timer_t *wt = (wheel_timer_t *)arg;
wheel_timer_elem_t *wt_elem = NULL;
int absolute_slot_no = 0, i =0;
ll_t *slot_list = NULL;
singly_ll_node_t *head = NULL, *next_node = NULL;
slotlist_t *slot_list = NULL;
glthread_t *curr;
while(1){
wt->current_clock_tic++;
wt->current_clock_tic = (wt->current_clock_tic % wt->wheel_size);
if(wt->current_clock_tic == 0)
wt->current_cycle_no++;
wt->current_clock_tic++;
if(wt->current_clock_tic == wt->wheel_size){
wt->current_clock_tic = 0;
wt->current_cycle_no++;
}
sleep(wt->clock_tic_interval);
tentative_wait(wt->wheel_thread, &wt->wheel_timer_mutex);
slot_list = wt->slots[wt->current_clock_tic];
head = GET_HEAD_SINGLY_LL(slot_list);
int node_count = GET_NODE_COUNT_SINGLY_LL(slot_list);
slot_list = WT_SLOTLIST(wt, wt->current_clock_tic);
absolute_slot_no = GET_WT_CURRENT_ABS_SLOT_NO(wt);
printf("Wheel Timer Time = %d : ", absolute_slot_no * wt->clock_tic_interval);
if(!node_count)
printf("\n");
for(i = 0; i < node_count; i++){
next_node = GET_NEXT_NODE_SINGLY_LL(head);
wt_elem = (wheel_timer_elem_t *)head->data;
if(wt_elem->is_alive == 0){
singly_ll_remove_node(slot_list, head);
free_wheel_timer_element(wt_elem);
free(head);
head = next_node;
continue;
}
ITERATE_GLTHREAD_BEGIN(&slot_list->slots, curr){
wt_elem = glthread_to_wt_elem(curr);
/*Check if R == r*/
if(wt->current_cycle_no == wt_elem->execute_cycle_no){
/*Invoke the application event through fn pointer as below*/
wt_elem->app_callback(wt_elem->arg, wt_elem->arg_size);
/* After invocation, check if the event needs to be rescheduled again
* in future*/
if(wt_elem->is_recurrence){
/*relocate*/
int next_abs_slot_no = absolute_slot_no + (wt_elem->time_interval/wt->clock_tic_interval);
/*relocate Or reschedule to the next slot*/
int next_abs_slot_no = absolute_slot_no +
(wt_elem->time_interval/wt->clock_tic_interval);
int next_cycle_no = next_abs_slot_no / wt->wheel_size;
int next_slot_no = next_abs_slot_no % wt->wheel_size;
wt_elem->execute_cycle_no = next_cycle_no;
if(next_slot_no == wt->current_clock_tic){
head = next_node;
continue;
}
singly_ll_remove_node(slot_list, head);
singly_ll_add_node(wt->slots[next_slot_no], head);
}
else{
free_wheel_timer_element((wheel_timer_elem_t *)head->data);
singly_ll_delete_node(slot_list, head);
remove_glthread(&wt_elem->glue);
glthread_priority_insert(WT_SLOTLIST_HEAD(wt, next_slot_no), &wt_elem->glue,
insert_wt_elem_in_slot,
(unsigned long)&((wheel_timer_elem_t *)0)->glue);
wt_elem->slotlist_head = WT_SLOTLIST(wt, next_slot_no);
wt_elem->slot_no = next_slot_no;
wt_elem->N_scheduled++;
}
}
head = next_node;
}
else
break;
} ITERATE_GLTHREAD_END(slot_list, curr)
process_wt_reschedule_slotlist(wt);
}
return NULL;
}
static void
_wt_elem_reschedule(wheel_timer_t *wt,
wheel_timer_elem_t *wt_elem,
int new_time_interval,
wt_opcode_t opcode){
if(wt_elem->opcode == WTELEM_DELETE &&
(opcode == WTELEM_CREATE ||
opcode == WTELEM_RESCHED)){
/* This is a Valid Scenario. A Race condition may arise When WT itself
* invoked a timer expiry callback for a wt_elem, and at the same time
* hello packet also arrived to refresh the same wt_elem.*/
//assert(0);
}
switch(opcode){
case WTELEM_CREATE:
case WTELEM_RESCHED:
case WTELEM_DELETE:
wt_elem->new_time_interval = new_time_interval;
WT_LOCK_SLOT_LIST(WT_GET_RESCHD_SLOTLIST(wt));
wt_elem->opcode = opcode;
remove_glthread(&wt_elem->reschedule_glue);
glthread_add_next(WT_GET_RESCHD_SLOTLIST_HEAD(wt),
&wt_elem->reschedule_glue);
WT_UNLOCK_SLOT_LIST(WT_GET_RESCHD_SLOTLIST(wt));
break;
default:
assert(0);
}
}
wheel_timer_elem_t *
register_app_event(wheel_timer_t *wt,
app_call_back call_back,
void *arg,
int arg_size,
int time_interval,
char is_recursive){
app_call_back call_back,
void *arg,
int arg_size,
int time_interval,
char is_recursive){
if(!wt || !call_back) return NULL;
wheel_timer_elem_t *wt_elem = calloc(1, sizeof(wheel_timer_elem_t));
wt_elem->time_interval = time_interval;
wt_elem->app_callback = call_back;
wt_elem->arg = calloc(1, arg_size);
memcpy(wt_elem->arg, arg, arg_size);
wt_elem->arg_size = arg_size;
if(arg && arg_size){
wt_elem->arg = calloc(1, arg_size);
memcpy(wt_elem->arg, arg, arg_size);
wt_elem->arg_size = arg_size;
}
wt_elem->is_recurrence = is_recursive;
init_glthread(&wt_elem->glue);
init_glthread(&wt_elem->reschedule_glue);
wt_elem->N_scheduled = 0;
_wt_elem_reschedule(wt, wt_elem, time_interval, WTELEM_CREATE);
return wt_elem;
}
/*Stop the Wheel timer Thread here*/
pause_wheel_timer(wt);
void
de_register_app_event(wheel_timer_t *wt, wheel_timer_elem_t *wt_elem){
int wt_absolute_slot = GET_WT_CURRENT_ABS_SLOT_NO(wt);
int registration_next_abs_slot = wt_absolute_slot + (wt_elem->time_interval/wt->clock_tic_interval);
int cycle_no = registration_next_abs_slot / wt->wheel_size;
int slot_no = registration_next_abs_slot % wt->wheel_size;
wt_elem->execute_cycle_no = cycle_no;
wt_elem->is_alive = 1;
singly_ll_add_node_by_val(wt->slots[slot_no], wt_elem);
//printf("Wheel Timer snapshot on New Registration\n");
//print_wheel_timer(wt);
_wt_elem_reschedule(wt, wt_elem, 0, WTELEM_DELETE);
}
resume_wheel_timer(wt);
return wt_elem;
void
wt_elem_reschedule(wheel_timer_t *wt,
wheel_timer_elem_t *wt_elem,
int new_time_interval){
_wt_elem_reschedule(wt, wt_elem, new_time_interval, WTELEM_RESCHED);
}
int
wt_get_remaining_time(wheel_timer_t *wt,
wheel_timer_elem_t *wt_elem){
if(wt_elem->opcode == WTELEM_CREATE ||
wt_elem->opcode == WTELEM_RESCHED){
/* Means : the wt_elem has not been assigned a slot in WT,
* just return the time interval for which it has been scheduled
* in this case*/
return wt_elem->new_time_interval;
}
int wt_elem_absolute_slot = (wt_elem->execute_cycle_no * wt->wheel_size) +
wt_elem->slot_no;
int diff = wt_elem_absolute_slot - GET_WT_CURRENT_ABS_SLOT_NO(wt);
return (diff * wt->clock_tic_interval);
}
void
free_wheel_timer_element(wheel_timer_elem_t *wt_elem){
wt_elem->slotlist_head = NULL;
free(wt_elem->arg);
free(wt_elem);
}
@@ -146,46 +258,49 @@ free_wheel_timer_element(wheel_timer_elem_t *wt_elem){
void
print_wheel_timer(wheel_timer_t *wt){
int i = 0, j = 0;
ll_t* slot_list = NULL;
int i = 0, j = 0;
glthread_t *curr;
glthread_t *slot_list_head = NULL;
wheel_timer_elem_t *wt_elem = NULL;
singly_ll_node_t *head = NULL;
printf("Printing Wheel Timer DS\n");
printf("wt->current_clock_tic = %d\n", wt->current_clock_tic);
printf("wt->clock_tic_interval = %d\n", wt->clock_tic_interval);
printf("wt abs slot no = %d\n", GET_WT_CURRENT_ABS_SLOT_NO(wt));
printf("wt->wheel_size = %d\n", wt->wheel_size);
printf("wt->current_cycle_no = %d\n", wt->current_cycle_no);
printf("wt->wheel_thread = %p\n", wt->wheel_thread);
printf("wt->wheel_thread = %p\n", &wt->wheel_thread);
printf("WT uptime = %s\n", hrs_min_sec_format(WT_UPTIME(wt)));
printf("wt->no_of_wt_elem = %u\n", wt->no_of_wt_elem);
printf("printing slots : \n");
for(; i < wt->wheel_size; i++){
slot_list = wt->slots[i];
printf(" slot_list[%d] : count : %d\n", i, GET_NODE_COUNT_SINGLY_LL(slot_list));
head = GET_HEAD_SINGLY_LL(slot_list);
for(j = 0 ; j < GET_NODE_COUNT_SINGLY_LL(slot_list); j++){
wt_elem = (wheel_timer_elem_t *)head->data;
if(!wt_elem){
printf(" NULL\n");
head = GET_NEXT_NODE_SINGLY_LL(head);
continue;
}
printf(" wt_elem->time_interval = %d\n", wt_elem->time_interval);
slot_list_head = WT_SLOTLIST_HEAD(wt, i);
ITERATE_GLTHREAD_BEGIN(slot_list_head, curr){
wt_elem = glthread_to_wt_elem(curr);
printf(" wt_elem->opcode = %d\n", wt_elem->opcode);
printf(" wt_elem = %p\n", wt_elem);
printf(" wt_elem->time_interval = %d\n", wt_elem->time_interval);
printf(" wt_elem->execute_cycle_no = %d\n", wt_elem->execute_cycle_no);
printf(" wt_elem->slot_no = %d\n", wt_elem->slot_no);
printf(" wt_elem abs slot no = %d\n",
(wt_elem->execute_cycle_no * wt->wheel_size) + wt_elem->slot_no);
printf(" wt_elem->app_callback = %p\n", wt_elem->app_callback);
printf(" wt_elem->arg = %p\n", wt_elem->arg);
printf(" wt_elem->arg = %p\n", wt_elem->arg);
printf(" wt_elem->is_recurrence = %d\n", wt_elem->is_recurrence);
head = GET_NEXT_NODE_SINGLY_LL(head);
}
printf(" wt_elem->N_scheduled = %u\n", wt_elem->N_scheduled);
printf(" Remaining Time to Fire = %d\n",
wt_get_remaining_time(wt, wt_elem));
printf("\n");
} ITERATE_GLTHREAD_END(slot_list_head , curr)
}
}
void
start_wheel_timer(wheel_timer_t *wt){
_pthread_t *thread = wt->wheel_thread;
if (pthread_create(&thread->pthread_handle, &thread->attr, wheel_fn, (void*)wt))
if (pthread_create(&wt->wheel_thread, NULL, wheel_fn, (void*)wt))
{
printf("Wheel Timer Thread initialization failed, exiting ... \n");
exit(0);
@@ -198,21 +313,26 @@ reset_wheel_timer(wheel_timer_t *wt){
wt->current_cycle_no = 0;
}
void
pause_wheel_timer(wheel_timer_t *wt){
send_wait_order(wt->wheel_thread);
char*
hrs_min_sec_format(unsigned int seconds){
static char time_f[16];
unsigned int hrs = 0,
min =0, sec = 0;
if(seconds > 3600){
min = seconds/60;
sec = seconds%60;
hrs = min/60;
min = min%60;
}
else{
min = seconds/60;
sec = seconds%60;
}
memset(time_f, 0, sizeof(time_f));
sprintf(time_f, "%u::%u::%u", hrs, min, sec);
return time_f;
}
void
resume_wheel_timer(wheel_timer_t *wt){
signal_t(wt->wheel_thread);
}
void
wt_elem_reschedule(wheel_timer_elem_t *wt_elem, int new_time_interval){
if(!wt_elem) return;
if(new_time_interval <= 0)
return;
wt_elem->time_interval = new_time_interval;
}

View File

@@ -1,40 +1,110 @@
#ifndef __WHEEL_TIMER__
#define __WHEEL_TIMER__
#include "threadApi.h"
#include <pthread.h>
#include "gluethread/glthread.h"
typedef struct _wheel_timer_elem_t wheel_timer_elem_t;
typedef void (*app_call_back)(void *arg, int sizeof_arg);
typedef struct LL ll_t;
typedef struct slotlist_{
glthread_t slots;
pthread_mutex_t slot_mutex;
}slotlist_t;
typedef enum{
WTELEM_CREATE,
WTELEM_RESCHED,
WTELEM_DELETE,
WTELEM_SCHEDULED,
WTELEM_UNKNOWN
} wt_opcode_t;
struct _wheel_timer_elem_t{
wt_opcode_t opcode;
int time_interval;
int new_time_interval;
int execute_cycle_no;
int slot_no;
app_call_back app_callback;
void *arg;
int arg_size;
char is_recurrence;
/* control param*/
char is_alive;
glthread_t glue;
slotlist_t *slotlist_head;
glthread_t reschedule_glue;
unsigned int N_scheduled;
};
GLTHREAD_TO_STRUCT(glthread_to_wt_elem, wheel_timer_elem_t, glue);
GLTHREAD_TO_STRUCT(glthread_reschedule_glue_to_wt_elem, wheel_timer_elem_t, reschedule_glue);
typedef struct _wheel_timer_t {
int current_clock_tic;
int clock_tic_interval;
int wheel_size;
int current_cycle_no;
_pthread_t *wheel_thread;
pthread_mutex_t wheel_timer_mutex;
ll_t *slots[0];
pthread_t wheel_thread;
slotlist_t reschd_list;
unsigned int no_of_wt_elem;
slotlist_t slotlist[0];
} wheel_timer_t;
#define WT_UPTIME(wt_ptr) \
(GET_WT_CURRENT_ABS_SLOT_NO(wt_ptr) * wt_ptr->clock_tic_interval)
#define WT_SLOTLIST(wt_ptr, index) \
(&(wt_ptr->slotlist[index]))
#define WT_SLOTLIST_HEAD(wt_ptr, index) \
(&(wt_ptr->slotlist[index].slots))
#define WT_SLOTLIST_MUTEX(wt_ptr, index) \
(&(wt_ptr->slotlist[index].slot_mutex))
#define GET_WT_ELEM_SLOT_LIST(wt_elem_ptr) \
(wt_elem_ptr->slotlist_head)
#define WT_LOCK_SLOT_LIST(slotlist_ptr) \
pthread_mutex_lock(&(slotlist_ptr->slot_mutex))
#define WT_UNLOCK_SLOT_LIST(slotlist_ptr) \
pthread_mutex_unlock(&(slotlist_ptr->slot_mutex))
#define WT_LOCK_WTELEM_SLOT_LIST(wt_elem_ptr) \
{ \
slotlist_t *_slotlist = GET_WT_ELEM_SLOT_LIST(wt_elem_ptr); \
if(_slotlist) \
WT_LOCK_SLOT_LIST(_slotlist); \
}
#define WT_UNLOCK_WTELEM_SLOT_LIST(wt_elem_ptr) \
{ \
slotlist_t *_slotlist = GET_WT_ELEM_SLOT_LIST(wt_elem_ptr); \
if(_slotlist) \
WT_UNLOCK_SLOT_LIST(_slotlist); \
}
#define WT_IS_SLOTLIST_EMPTY(slotlist_ptr) \
IS_GLTHREAD_LIST_EMPTY(&(slotlist_ptr->slots))
#define WT_GET_RESCHD_SLOTLIST(wt_ptr) \
(&(wt_ptr->reschd_list))
#define WT_GET_RESCHD_SLOTLIST_HEAD(wt_ptr) \
(&((WT_GET_RESCHD_SLOTLIST(wt_ptr))->slots))
wheel_timer_t*
init_wheel_timer(int wheel_size, int clock_tic_interval);
#define GET_WT_CURRENT_ABS_SLOT_NO(wt) ((wt->current_cycle_no * wt->wheel_size) + wt->current_clock_tic)
void
cleanup_wheel_timer(wheel_timer_t *wt);
int
wt_get_remaining_time(wheel_timer_t *wt,
wheel_timer_elem_t *wt_elem);
/*Gives the absolute slot no since the time WT has started*/
#define GET_WT_CURRENT_ABS_SLOT_NO(wt) ((wt->current_cycle_no * wt->wheel_size) + wt->current_clock_tic)
wheel_timer_elem_t *
register_app_event(wheel_timer_t *wt,
@@ -44,12 +114,13 @@ register_app_event(wheel_timer_t *wt,
int time_interval,
char is_recursive);
void
de_register_app_event(wheel_timer_t *wt, wheel_timer_elem_t *wt_elem);
void
wt_elem_reschedule(wheel_timer_elem_t *wt_elem, int new_time_interval);
wt_elem_reschedule(wheel_timer_t *wt,
wheel_timer_elem_t *wt_elem,
int new_time_interval);
void
free_wheel_timer_element(wheel_timer_elem_t *wt_elem);
@@ -60,16 +131,13 @@ print_wheel_timer(wheel_timer_t *wt);
void
start_wheel_timer(wheel_timer_t *wt);
void
pause_wheel_timer(wheel_timer_t *wt);
void
cancel_wheel_timer(wheel_timer_t *wt);
void
reset_wheel_timer(wheel_timer_t *wt);
void
resume_wheel_timer(wheel_timer_t *wt);
char*
hrs_min_sec_format(unsigned int seconds);
#endif

View File

@@ -0,0 +1,200 @@
/*
* =====================================================================================
*
* Filename: glthread.c
*
* Description: Implementation of glthread Library
*
* Version: 1.0
* Created: Monday 12 March 2018 02:13:36 IST
* Revision: 1.0
* Compiler: gcc
*
* Author: Er. Abhishek Sagar, Networking Developer (AS), sachinites@gmail.com
* Company: Brocade Communications(Jul 2012- Mar 2016), Current : Juniper Networks(Apr 2017 - Present)
*
* This file is part of the SPFComputation distribution (https://github.com/sachinites).
* Copyright (c) 2017 Abhishek Sagar.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* =====================================================================================
*/
#include "glthread.h"
#include <stdlib.h>
void
init_glthread(glthread_t *glthread){
glthread->left = NULL;
glthread->right = NULL;
}
void
glthread_add_next(glthread_t *curr_glthread, glthread_t *new_glthread){
if(!curr_glthread->right){
curr_glthread->right = new_glthread;
new_glthread->left = curr_glthread;
return;
}
glthread_t *temp = curr_glthread->right;
curr_glthread->right = new_glthread;
new_glthread->left = curr_glthread;
new_glthread->right = temp;
temp->left = new_glthread;
}
void
glthread_add_before(glthread_t *curr_glthread, glthread_t *new_glthread){
if(!curr_glthread->left){
new_glthread->left = NULL;
new_glthread->right = curr_glthread;
curr_glthread->left = new_glthread;
return;
}
glthread_t *temp = curr_glthread->left;
temp->right = new_glthread;
new_glthread->left = temp;
new_glthread->right = curr_glthread;
curr_glthread->left = new_glthread;
}
void
remove_glthread(glthread_t *curr_glthread){
if(!curr_glthread->left){
if(curr_glthread->right){
curr_glthread->right->left = NULL;
curr_glthread->right = 0;
return;
}
return;
}
if(!curr_glthread->right){
curr_glthread->left->right = NULL;
curr_glthread->left = NULL;
return;
}
curr_glthread->left->right = curr_glthread->right;
curr_glthread->right->left = curr_glthread->left;
curr_glthread->left = 0;
curr_glthread->right = 0;
}
void
delete_glthread_list(glthread_t *base_glthread){
glthread_t *glthreadptr = NULL;
ITERATE_GLTHREAD_BEGIN(base_glthread, glthreadptr){
remove_glthread(glthreadptr);
} ITERATE_GLTHREAD_END(base_glthread, glthreadptr);
}
void
glthread_add_last(glthread_t *base_glthread, glthread_t *new_glthread){
glthread_t *glthreadptr = NULL,
*prevglthreadptr = NULL;
ITERATE_GLTHREAD_BEGIN(base_glthread, glthreadptr){
prevglthreadptr = glthreadptr;
} ITERATE_GLTHREAD_END(base_glthread, glthreadptr);
if(prevglthreadptr)
glthread_add_next(prevglthreadptr, new_glthread);
else
glthread_add_next(base_glthread, new_glthread);
}
unsigned int
get_glthread_list_count(glthread_t *base_glthread){
unsigned int count = 0;
glthread_t *glthreadptr = NULL;
ITERATE_GLTHREAD_BEGIN(base_glthread, glthreadptr){
count++;
} ITERATE_GLTHREAD_END(base_glthread, glthreadptr);
return count;
}
void
glthread_priority_insert(glthread_t *base_glthread,
glthread_t *glthread,
int (*comp_fn)(void *, void *),
int offset){
glthread_t *curr = NULL,
*prev = NULL;
init_glthread(glthread);
if(IS_GLTHREAD_LIST_EMPTY(base_glthread)){
glthread_add_next(base_glthread, glthread);
return;
}
/* Only one node*/
if(base_glthread->right && !base_glthread->right->right){
if(comp_fn(GLTHREAD_GET_USER_DATA_FROM_OFFSET(base_glthread->right, offset),
GLTHREAD_GET_USER_DATA_FROM_OFFSET(glthread, offset)) == -1){
glthread_add_next(base_glthread->right, glthread);
}
else{
glthread_add_next(base_glthread, glthread);
}
return;
}
if(comp_fn(GLTHREAD_GET_USER_DATA_FROM_OFFSET(glthread, offset),
GLTHREAD_GET_USER_DATA_FROM_OFFSET(base_glthread->right, offset)) == -1){
glthread_add_next(base_glthread, glthread);
return;
}
ITERATE_GLTHREAD_BEGIN(base_glthread, curr){
if(comp_fn(GLTHREAD_GET_USER_DATA_FROM_OFFSET(glthread, offset),
GLTHREAD_GET_USER_DATA_FROM_OFFSET(curr, offset)) != -1){
prev = curr;
continue;
}
glthread_add_next(curr, glthread);
return;
}ITERATE_GLTHREAD_END(base_glthread, curr);
/*Add in the end*/
glthread_add_next(prev, glthread);
}
#if 0
void *
gl_thread_search(glthread_t *base_glthread,
void *(*thread_to_struct_fn)(glthread_t *),
void *key,
int (*comparison_fn)(void *, void *)){
return NULL;
}
#endif

View File

@@ -0,0 +1,104 @@
/*
* =====================================================================================
*
* Filename: glthread.h
*
* Description: This file defines the Data structure and APIs for Glue thread
*
* Version: 1.0
* Created: Monday 12 March 2018 02:01:51 IST
* Revision: 1.0
* Compiler: gcc
*
* Author: Er. Abhishek Sagar, Networking Developer (AS), sachinites@gmail.com
* Company: Brocade Communications(Jul 2012- Mar 2016), Current : Juniper Networks(Apr 2017 - Present)
*
* This file is part of the SPFComputation distribution (https://github.com/sachinites).
* Copyright (c) 2017 Abhishek Sagar.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* =====================================================================================
*/
#ifndef __GLUETHREAD__
#define __GLUETHREAD__
typedef struct _glthread{
struct _glthread *left;
struct _glthread *right;
} glthread_t;
void
glthread_add_next(glthread_t *base_glthread, glthread_t *new_glthread);
void
glthread_add_before(glthread_t *base_glthread, glthread_t *new_glthread);
void
remove_glthread(glthread_t *glthread);
void
init_glthread(glthread_t *glthread);
void
glthread_add_last(glthread_t *base_glthread, glthread_t *new_glthread);
#define IS_GLTHREAD_LIST_EMPTY(glthreadptr) \
((glthreadptr)->right == 0 && (glthreadptr)->left == 0)
#define GLTHREAD_TO_STRUCT(fn_name, structure_name, field_name) \
static inline structure_name * fn_name(glthread_t *glthreadptr){ \
return (structure_name *)((char *)(glthreadptr) - (char *)&(((structure_name *)0)->field_name)); \
}
/* delete safe loop*/
/*Normal continue and break can be used with this loop macro*/
#define BASE(glthreadptr) ((glthreadptr)->right)
#define ITERATE_GLTHREAD_BEGIN(glthreadptrstart, glthreadptr) \
{ \
glthread_t *_glthread_ptr = NULL; \
glthreadptr = BASE(glthreadptrstart); \
for(; glthreadptr!= NULL; glthreadptr = _glthread_ptr){ \
_glthread_ptr = (glthreadptr)->right;
#define ITERATE_GLTHREAD_END(glthreadptrstart, glthreadptr) \
}}
#define GLTHREAD_GET_USER_DATA_FROM_OFFSET(glthreadptr, offset) \
(void *)((char *)(glthreadptr) - offset)
void
delete_glthread_list(glthread_t *base_glthread);
unsigned int
get_glthread_list_count(glthread_t *base_glthread);
void
glthread_priority_insert(glthread_t *base_glthread,
glthread_t *glthread,
int (*comp_fn)(void *, void *),
int offset);
#if 0
void *
gl_thread_search(glthread_t *base_glthread,
void *(*thread_to_struct_fn)(glthread_t *),
void *key,
int (*comparison_fn)(void *, void *));
#endif
#endif /* __GLUETHREAD__ */

View File

@@ -0,0 +1,90 @@
/*
* =====================================================================================
*
* Filename: test.c
*
* Description:
*
* Version: 1.0
* Created: Monday 12 March 2018 02:15:28 IST
* Revision: 1.0
* Compiler: gcc
*
* Author: Er. Abhishek Sagar, Networking Developer (AS), sachinites@gmail.com
* Company: Brocade Communications(Jul 2012- Mar 2016), Current : Juniper Networks(Apr 2017 - Present)
*
* This file is part of the XXX distribution (https://github.com/sachinites).
* Copyright (c) 2017 Abhishek Sagar.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* =====================================================================================
*/
#include "glthread.h"
#include <memory.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct _person{
int age;
int weight;
glthread_t glthread;
} person_t ;
int
senior_citizen(person_t *p1, person_t *p2){
if(p1->age == p2->age) return 0;
if(p1->age < p2->age) return 1;
return -1;
}
#define offset(struct_name, fld_name) \
(unsigned int)&(((struct_name *)0)->fld_name)
GLTHREAD_TO_STRUCT(thread_to_person, person_t, glthread, glthreadptr);
int main(int argc, char **argv){
person_t person[5];
memset(person, 0, sizeof(person_t) * 5);
person[0].age = 1;
person[0].weight = 2;
person[1].age = 3;
person[1].weight = 4;
person[2].age = 5;
person[2].weight = 6;
person[3].age = 7;
person[3].weight = 8;
person[4].age = 9;
person[4].weight = 10;
glthread_t base_glthread;
init_glthread(&base_glthread);
glthread_priority_insert(&base_glthread, &person[4].glthread, senior_citizen, offset(person_t, glthread));
glthread_priority_insert(&base_glthread, &person[3].glthread, senior_citizen, offset(person_t, glthread));
glthread_priority_insert(&base_glthread, &person[2].glthread, senior_citizen, offset(person_t, glthread));
glthread_priority_insert(&base_glthread, &person[1].glthread, senior_citizen, offset(person_t, glthread));
glthread_priority_insert(&base_glthread, &person[0].glthread, senior_citizen, offset(person_t, glthread));
glthread_t *curr = NULL;
ITERATE_GLTHREAD_BEGIN(&base_glthread, curr){
person_t *p = thread_to_person(curr);
printf("Age = %d\n", p->age);
} ITERATE_GLTHREAD_END(&base_glthread, curr);
return 0;
}

View File

@@ -1,15 +1,12 @@
#include "WheelTimer.h"
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include "WheelTimer.h"
#define MAX_NUMBER_APP_THREADS 1
#define WHEEL_SIZE 15
#define WHEEL_TIMER_CLOCK_TIC_INTERVAL 1 // sec
/*Import Library global Variables*/
extern blocked_pool_t gl_blocked_th_pool;
wheel_timer_t *wt;
void
generate_general_query(int vlan){
@@ -77,7 +74,7 @@ main_menu(wheel_timer_t *wt){
int new_time_interval = 0;
printf("Enter new time interval : ");
scanf("%d", &new_time_interval);
wt_elem_reschedule(gq_wt_elem, new_time_interval);
wt_elem_reschedule(wt, gq_wt_elem, new_time_interval);
}
break;
case 11:
@@ -85,7 +82,7 @@ main_menu(wheel_timer_t *wt){
int new_time_interval = 0;
printf("Enter new time interval : ");
scanf("%d", &new_time_interval);
wt_elem_reschedule(pim_hello_wt_elem, new_time_interval);
wt_elem_reschedule(wt, pim_hello_wt_elem, new_time_interval);
}
break;
case 12:
@@ -93,7 +90,7 @@ main_menu(wheel_timer_t *wt){
int new_time_interval = 0;
printf("Enter new time interval : ");
scanf("%d", &new_time_interval);
wt_elem_reschedule(ospf_hello_wt_elem, new_time_interval);
wt_elem_reschedule(wt, ospf_hello_wt_elem, new_time_interval);
}
break;
case 6:
@@ -173,9 +170,7 @@ main_menu(wheel_timer_t *wt){
int
main(int argc, char **argv){
init_blocked_pool(&gl_blocked_th_pool, MAX_NUMBER_APP_THREADS);
wheel_timer_t *wt =
init_wheel_timer(WHEEL_SIZE, WHEEL_TIMER_CLOCK_TIC_INTERVAL);
wt = init_wheel_timer(WHEEL_SIZE, WHEEL_TIMER_CLOCK_TIC_INTERVAL);
start_wheel_timer(wt);
/* WT thread is in DETACHED MODE, so below call is useless*/

View File

@@ -2,6 +2,7 @@ This is the simple demostration of WheelTimer in C
you should have gcc compiler installed to compile the project.
run 'make' to compile the project
use this cmd to create executable :
gcc -g main.c gluethread/glthread.c WheelTimer.c -o exe -lpthread
run ./exe to launch the application