mirror of
https://github.com/Hizenberg469/WheelTimer.git
synced 2026-04-19 18:52:22 +03:00
uploaded src files
This commit is contained in:
275
WheelTimer/LinkedListApi.c
Normal file
275
WheelTimer/LinkedListApi.c
Normal file
@@ -0,0 +1,275 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include "LinkedListApi.h"
|
||||
#include <assert.h>
|
||||
|
||||
ll_t* init_singly_ll(){
|
||||
return calloc(1, sizeof(ll_t));
|
||||
}
|
||||
|
||||
singly_ll_node_t* singly_ll_init_node(void* data){
|
||||
singly_ll_node_t* node = calloc(1, sizeof(singly_ll_node_t));
|
||||
node->data = data;
|
||||
return node;
|
||||
}
|
||||
|
||||
int
|
||||
singly_ll_add_node(ll_t* ll, singly_ll_node_t *node){
|
||||
if(!ll) return -1;
|
||||
if(!node) return -1;
|
||||
if(!GET_HEAD_SINGLY_LL(ll)){
|
||||
GET_HEAD_SINGLY_LL(ll) = node;
|
||||
INC_NODE_COUNT_SINGLY_LL(ll);
|
||||
return 0;
|
||||
}
|
||||
|
||||
node->next = GET_HEAD_SINGLY_LL(ll);
|
||||
GET_HEAD_SINGLY_LL(ll) = node;
|
||||
INC_NODE_COUNT_SINGLY_LL(ll);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
singly_ll_add_node_by_val(ll_t *ll, void* data){
|
||||
singly_ll_node_t* node = singly_ll_init_node(data);
|
||||
return singly_ll_add_node(ll, node);
|
||||
}
|
||||
|
||||
int
|
||||
singly_ll_delete_node(ll_t *ll, singly_ll_node_t *node){
|
||||
if(!ll) return -1;
|
||||
if(!GET_HEAD_SINGLY_LL(ll) || !node) return 0;
|
||||
singly_ll_node_t *trav = NULL;
|
||||
/*if node is not the last node*/
|
||||
if(node->next){
|
||||
singly_ll_node_t *temp = NULL;
|
||||
node->data = node->next->data;
|
||||
temp = node->next;
|
||||
node->next = node->next->next;
|
||||
free(temp);
|
||||
DEC_NODE_COUNT_SINGLY_LL(ll);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if node is the only node in LL*/
|
||||
if(ll->node_count == 1 && GET_HEAD_SINGLY_LL(ll) == node){
|
||||
free(node);
|
||||
GET_HEAD_SINGLY_LL(ll) = NULL;
|
||||
DEC_NODE_COUNT_SINGLY_LL(ll);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*if node is the last node of the LL*/
|
||||
trav = GET_HEAD_SINGLY_LL(ll);
|
||||
while(trav->next != node){
|
||||
trav = trav->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
trav->next = NULL;
|
||||
free(node);
|
||||
DEC_NODE_COUNT_SINGLY_LL(ll);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
singly_ll_remove_node(ll_t *ll, singly_ll_node_t *node){
|
||||
if(!ll || !GET_HEAD_SINGLY_LL(ll)) return 0;
|
||||
if(!node){
|
||||
printf("%s(%d) : Error : node is NULL\n", __FUNCTION__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
int i = 0;
|
||||
singly_ll_node_t *head = GET_HEAD_SINGLY_LL(ll), *prev = NULL;
|
||||
|
||||
if(head == node){
|
||||
GET_HEAD_SINGLY_LL(ll) = GET_NEXT_NODE_SINGLY_LL(head);
|
||||
DEC_NODE_COUNT_SINGLY_LL(ll);
|
||||
node->next = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
prev = head;
|
||||
head = GET_NEXT_NODE_SINGLY_LL(head);
|
||||
for(i =1; i < GET_NODE_COUNT_SINGLY_LL(ll); i++){
|
||||
if(head != node){
|
||||
prev = head;
|
||||
head = GET_NEXT_NODE_SINGLY_LL(head);
|
||||
continue;
|
||||
}
|
||||
|
||||
prev->next = GET_NEXT_NODE_SINGLY_LL(head);
|
||||
GET_NEXT_NODE_SINGLY_LL(head) = NULL;
|
||||
DEC_NODE_COUNT_SINGLY_LL(ll);
|
||||
node->next = NULL;
|
||||
return 0;
|
||||
}
|
||||
printf("%s(%d) : Error : node not found\n", __FUNCTION__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned int
|
||||
singly_ll_delete_node_by_value(ll_t *ll, void *data, int size){
|
||||
if(!ll || !GET_HEAD_SINGLY_LL(ll)) return 0;
|
||||
unsigned int curren_node_count = GET_NODE_COUNT_SINGLY_LL(ll);
|
||||
singly_ll_node_t* trav = GET_HEAD_SINGLY_LL(ll);
|
||||
while(trav != NULL){
|
||||
if(memcmp(trav->data, data, size) == 0){
|
||||
singly_ll_delete_node(ll, trav);
|
||||
return curren_node_count - GET_NODE_COUNT_SINGLY_LL(ll);
|
||||
}
|
||||
trav = trav->next;
|
||||
}
|
||||
return curren_node_count - GET_NODE_COUNT_SINGLY_LL(ll);
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
singly_ll_remove_node_by_value(ll_t *ll, void *data, int size){
|
||||
if(!ll || !GET_HEAD_SINGLY_LL(ll)) return 0;
|
||||
unsigned int curren_node_count = GET_NODE_COUNT_SINGLY_LL(ll);
|
||||
singly_ll_node_t* trav = GET_HEAD_SINGLY_LL(ll);
|
||||
while(trav != NULL){
|
||||
if(memcmp(trav->data, data, size) == 0){
|
||||
singly_ll_remove_node(ll, trav);
|
||||
return curren_node_count - GET_NODE_COUNT_SINGLY_LL(ll);
|
||||
}
|
||||
trav = trav->next;
|
||||
}
|
||||
return curren_node_count - GET_NODE_COUNT_SINGLY_LL(ll);
|
||||
}
|
||||
|
||||
singly_ll_node_t*
|
||||
singly_ll_get_node_by_data_ptr(ll_t *ll, void *data){
|
||||
if(!ll || !GET_HEAD_SINGLY_LL(ll)) return NULL;
|
||||
int i = 0;
|
||||
singly_ll_node_t *head = GET_HEAD_SINGLY_LL(ll);
|
||||
|
||||
for(; i < GET_NODE_COUNT_SINGLY_LL(ll); i++){
|
||||
if(head->data == data)
|
||||
return head;
|
||||
head = GET_NEXT_NODE_SINGLY_LL(head);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void print_singly_LL(ll_t *ll){
|
||||
if(!ll) {
|
||||
printf("Invalid Linked List\n");
|
||||
return;
|
||||
}
|
||||
if(is_singly_ll_empty(ll)){
|
||||
printf("Empty Linked List\n");
|
||||
return;
|
||||
}
|
||||
|
||||
singly_ll_node_t* trav = GET_HEAD_SINGLY_LL(ll);
|
||||
unsigned int i = 0;
|
||||
printf("node count = %d\n", GET_NODE_COUNT_SINGLY_LL(ll));
|
||||
while(trav){
|
||||
printf("%d. Data = %p, node = %p\n", i, trav->data, trav);
|
||||
i++;
|
||||
trav = trav->next;
|
||||
}
|
||||
}
|
||||
|
||||
bool_t
|
||||
is_singly_ll_empty(ll_t *ll){
|
||||
if(!ll) assert(0);
|
||||
if(ll->node_count == 0)
|
||||
return LL_TRUE;
|
||||
return LL_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
reverse_singly_ll(ll_t *ll){
|
||||
if(!ll) assert(0) ;
|
||||
if(is_singly_ll_empty(ll)) return;
|
||||
if(GET_NODE_COUNT_SINGLY_LL(ll) == 1) return;
|
||||
singly_ll_node_t *p1 = GET_HEAD_SINGLY_LL(ll),
|
||||
*p2 = ll->head->next, *p3 = NULL;
|
||||
p1->next = NULL;
|
||||
do{
|
||||
p3 = p2->next;
|
||||
p2->next = p1;
|
||||
p1 = p2;
|
||||
p2 = p3;
|
||||
}while(p3);
|
||||
ll->head = p1;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
delete_singly_ll(ll_t *ll){
|
||||
if(!ll) return;
|
||||
|
||||
if(is_singly_ll_empty(ll)){
|
||||
return;
|
||||
}
|
||||
|
||||
singly_ll_node_t *head = GET_HEAD_SINGLY_LL(ll),
|
||||
*next = GET_NEXT_NODE_SINGLY_LL(head);
|
||||
|
||||
do{
|
||||
free(head);
|
||||
head = next;
|
||||
if(next)
|
||||
next = GET_NEXT_NODE_SINGLY_LL(next);
|
||||
|
||||
} while(head);
|
||||
|
||||
ll->node_count = 0;
|
||||
ll->head = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
int
|
||||
main(int argc, char **argv){
|
||||
ll_t* list = init_singly_ll();
|
||||
int n1 = 1;
|
||||
singly_ll_add_node_by_val(list, &n1);
|
||||
#if 1
|
||||
int n2 =2;
|
||||
singly_ll_add_node_by_val(list, &n2);
|
||||
int n3 =3;
|
||||
singly_ll_add_node_by_val(list, &n3);
|
||||
int n4 =4;
|
||||
singly_ll_add_node_by_val(list, &n4);
|
||||
int n5 =5;
|
||||
singly_ll_add_node_by_val(list, &n5);
|
||||
int n6 =6;
|
||||
singly_ll_add_node_by_val(list, &n6);
|
||||
int n7 =7;
|
||||
singly_ll_add_node_by_val(list, &n7);
|
||||
int n8 = 8;
|
||||
singly_ll_add_node_by_val(list, &n8);
|
||||
int n9 = 9;
|
||||
singly_ll_add_node_by_val(list, &n9);
|
||||
int n10 = 10;
|
||||
singly_ll_add_node_by_val(list, &n10);
|
||||
#endif
|
||||
print_singly_LL(list);
|
||||
|
||||
#if 1
|
||||
int n = 5;
|
||||
unsigned int num_nodes_removed = singly_ll_remove_node_by_value(list, &n, sizeof(int));
|
||||
printf("number of noded removed = %d\n", num_nodes_removed);
|
||||
print_singly_LL(list);
|
||||
#endif
|
||||
n = 1;
|
||||
singly_ll_remove_node_by_value(list, &n, sizeof(int));
|
||||
//reverse_singly_ll(list);
|
||||
print_singly_LL(list);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
#endif
|
||||
39
WheelTimer/LinkedListApi.h
Normal file
39
WheelTimer/LinkedListApi.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef __LINKEDLIST__
|
||||
#define __LINKEDLIST__
|
||||
|
||||
|
||||
#define GET_HEAD_SINGLY_LL(ll) (ll->head)
|
||||
#define INC_NODE_COUNT_SINGLY_LL(ll) (ll->node_count++)
|
||||
#define DEC_NODE_COUNT_SINGLY_LL(ll) (ll->node_count--)
|
||||
#define GET_NODE_COUNT_SINGLY_LL(ll) (ll->node_count)
|
||||
#define GET_NEXT_NODE_SINGLY_LL(node) (node->next)
|
||||
|
||||
typedef enum{
|
||||
LL_FALSE,
|
||||
LL_TRUE
|
||||
} bool_t;
|
||||
|
||||
typedef struct LL_Node{
|
||||
void *data;
|
||||
struct LL_Node *next;
|
||||
} singly_ll_node_t;
|
||||
|
||||
typedef struct LL{
|
||||
unsigned int node_count;
|
||||
singly_ll_node_t *head;
|
||||
} ll_t;
|
||||
|
||||
ll_t* init_singly_ll();
|
||||
singly_ll_node_t* singly_ll_init_node(void* data);
|
||||
int singly_ll_add_node(ll_t *ll, singly_ll_node_t *node);
|
||||
int singly_ll_add_node_by_val(ll_t *ll, void* data);
|
||||
int singly_ll_remove_node(ll_t *ll, singly_ll_node_t *node);
|
||||
unsigned int singly_ll_remove_node_by_value(ll_t *ll, void* data, int size);
|
||||
bool_t is_singly_ll_empty(ll_t *ll);
|
||||
void print_singly_LL(ll_t *ll);
|
||||
void reverse_singly_ll(ll_t *ll);
|
||||
void delete_singly_ll(ll_t *ll);
|
||||
int singly_ll_delete_node(ll_t *ll, singly_ll_node_t *node);
|
||||
unsigned int singly_ll_delete_node_by_value(ll_t *ll, void *data, int size);
|
||||
singly_ll_node_t *singly_ll_get_node_by_data_ptr(ll_t *ll, void *data);
|
||||
#endif
|
||||
14
WheelTimer/Makefile
Normal file
14
WheelTimer/Makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
LIBS=-lpthread
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -g
|
||||
INCLUDES=-I .
|
||||
SRC=WheelTimer.o threadApi.o main.o LinkedListApi.o
|
||||
TARGET:exe
|
||||
%.o:%.c
|
||||
${CC} ${CFLAGS} -c ${INCLUDES} $<
|
||||
exe:$(SRC)
|
||||
${CC} ${CFLAGS} $(SRC) -o exe $(LIBS)
|
||||
clean:
|
||||
rm *.o
|
||||
rm exe
|
||||
|
||||
190
WheelTimer/WheelTimer.c
Normal file
190
WheelTimer/WheelTimer.c
Normal file
@@ -0,0 +1,190 @@
|
||||
#include "WheelTimer.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include "LinkedListApi.h"
|
||||
|
||||
#define TH_JOINABLE 1
|
||||
#define TH_DETACHED 0
|
||||
|
||||
extern blocked_pool_t gl_blocked_th_pool;
|
||||
|
||||
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 *));
|
||||
|
||||
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);
|
||||
|
||||
int i = 0;
|
||||
for(; i < wheel_size; i++)
|
||||
wt->slots[i] = init_singly_ll();
|
||||
|
||||
return wt;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
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++;
|
||||
|
||||
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);
|
||||
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->current_cycle_no == wt_elem->execute_cycle_no){
|
||||
wt_elem->app_callback(wt_elem->arg, wt_elem->arg_size);
|
||||
if(wt_elem->is_recurrence){
|
||||
/*relocate*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
head = next_node;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
register_app_event(wheel_timer_t *wt,
|
||||
app_call_back call_back,
|
||||
void *arg,
|
||||
int arg_size,
|
||||
int time_interval,
|
||||
char is_recursive){
|
||||
|
||||
if(!wt || !call_back) return ;
|
||||
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;
|
||||
wt_elem->is_recurrence = is_recursive;
|
||||
|
||||
/*Stop the Wheel timer Thread here*/
|
||||
pause_wheel_timer(wt);
|
||||
|
||||
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;
|
||||
singly_ll_add_node_by_val(wt->slots[slot_no], wt_elem);
|
||||
//printf("Wheel Timer snapshot on New Registration\n");
|
||||
//print_wheel_timer(wt);
|
||||
|
||||
resume_wheel_timer(wt);
|
||||
}
|
||||
|
||||
void
|
||||
free_wheel_timer_element(wheel_timer_elem_t *wt_elem){
|
||||
free(wt_elem->arg);
|
||||
free(wt_elem);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
print_wheel_timer(wheel_timer_t *wt){
|
||||
int i = 0, j = 0;
|
||||
ll_t* slot_list = 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->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("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);
|
||||
printf(" wt_elem->execute_cycle_no = %d\n", wt_elem->execute_cycle_no);
|
||||
printf(" wt_elem->app_callback = %p\n", wt_elem->app_callback);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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))
|
||||
{
|
||||
printf("Wheel Timer Thread initialization failed, exiting ... \n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
reset_wheel_timer(wheel_timer_t *wt){
|
||||
wt->current_clock_tic = 0;
|
||||
wt->current_cycle_no = 0;
|
||||
}
|
||||
|
||||
void
|
||||
pause_wheel_timer(wheel_timer_t *wt){
|
||||
send_wait_order(wt->wheel_thread);
|
||||
}
|
||||
|
||||
void
|
||||
resume_wheel_timer(wheel_timer_t *wt){
|
||||
signal_t(wt->wheel_thread);
|
||||
}
|
||||
72
WheelTimer/WheelTimer.h
Normal file
72
WheelTimer/WheelTimer.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#ifndef __WHEEL_TIMER__
|
||||
#define __WHEEL_TIMER__
|
||||
#include "threadApi.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;
|
||||
|
||||
struct _wheel_timer_elem_t{
|
||||
int time_interval;
|
||||
int execute_cycle_no;
|
||||
app_call_back app_callback;
|
||||
void *arg;
|
||||
int arg_size;
|
||||
char is_recurrence;
|
||||
};
|
||||
|
||||
|
||||
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];
|
||||
} wheel_timer_t;
|
||||
|
||||
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);
|
||||
|
||||
void
|
||||
register_app_event(wheel_timer_t *wt,
|
||||
app_call_back call_back,
|
||||
void *arg,
|
||||
int arg_size,
|
||||
int time_interval,
|
||||
char is_recursive);
|
||||
|
||||
int
|
||||
unregister_app_event(wheel_timer_t *wt,
|
||||
app_call_back call_back,
|
||||
int time_interval);
|
||||
|
||||
|
||||
void
|
||||
free_wheel_timer_element(wheel_timer_elem_t *wt_elem);
|
||||
|
||||
void
|
||||
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);
|
||||
|
||||
#endif
|
||||
143
WheelTimer/main.c
Normal file
143
WheelTimer/main.c
Normal file
@@ -0,0 +1,143 @@
|
||||
#include "WheelTimer.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <memory.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;
|
||||
|
||||
void
|
||||
generate_general_query(int vlan){
|
||||
static int count = 0;
|
||||
printf("%s() : Query no : %d : general query is generated for vlan %d\n", __FUNCTION__, count++, vlan);
|
||||
}
|
||||
|
||||
void wrapper_generate_general_query(void *arg, int arg_size){
|
||||
|
||||
int vlan = *(int *)arg;
|
||||
generate_general_query(vlan);
|
||||
}
|
||||
|
||||
void
|
||||
generate_pim_hello(int vlan){
|
||||
static int count = 0;
|
||||
printf("%s() : Query no : %d : pim_hello is generated for vlan %d\n", __FUNCTION__, count++, vlan);
|
||||
}
|
||||
|
||||
void
|
||||
wrapper_generate_pim_hello(void *arg, int arg_size){
|
||||
int vlan = *(int *)arg;
|
||||
generate_pim_hello(vlan);
|
||||
}
|
||||
|
||||
void
|
||||
generate_ospf_hello(int vlan){
|
||||
static int count = 0;
|
||||
printf("%s() : Query no : %d : ospf_hello is generated for vlan %d\n", __FUNCTION__, count++, vlan);
|
||||
}
|
||||
|
||||
void wrapper_generate_ospf_hello(void *arg, int arg_size){
|
||||
|
||||
int vlan = *(int *)arg;
|
||||
generate_ospf_hello(vlan);
|
||||
}
|
||||
|
||||
void
|
||||
main_menu(wheel_timer_t *wt){
|
||||
do{
|
||||
printf("\nMain Menu\n");
|
||||
printf("*************\n");
|
||||
printf("1. dump Wheel Timer\n");
|
||||
printf("2. Register General Query Event\n");
|
||||
printf("3. Register Pim Hello Event\n");
|
||||
printf("4. Register Ospf Hello Event\n");
|
||||
printf("5. Reset Wheel Timer\n");
|
||||
printf("6. Exit\n");
|
||||
int choice;
|
||||
scanf("%d", &choice);
|
||||
switch(choice){
|
||||
case 1:
|
||||
print_wheel_timer(wt);
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
int vlan_no;
|
||||
printf("Enter vlan no : ");
|
||||
scanf("%d", &vlan_no);
|
||||
char is_recursive;
|
||||
printf("Is Recirsive (1/0) ? ");
|
||||
scanf("%d", (int *)&is_recursive);
|
||||
int time_interval;
|
||||
printf("time_interval ? ");
|
||||
scanf("%d", &time_interval);
|
||||
register_app_event(wt, wrapper_generate_general_query,
|
||||
(void *)&vlan_no, sizeof(vlan_no), time_interval, is_recursive);
|
||||
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
int vlan_no;
|
||||
printf("Enter vlan no : ");
|
||||
scanf("%d", &vlan_no);
|
||||
char is_recursive;
|
||||
printf("Is Recirsive (1/0) ? ");
|
||||
scanf("%d", (int *)&is_recursive);
|
||||
int time_interval;
|
||||
printf("time_interval ? ");
|
||||
scanf("%d", &time_interval);
|
||||
register_app_event(wt, wrapper_generate_pim_hello,
|
||||
(void *)&vlan_no, sizeof(vlan_no), time_interval, is_recursive);
|
||||
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
int vlan_no;
|
||||
printf("Enter vlan no : ");
|
||||
scanf("%d", &vlan_no);
|
||||
char is_recursive;
|
||||
printf("Is Recirsive (1/0) ? ");
|
||||
scanf("%d", (int *)&is_recursive);
|
||||
int time_interval;
|
||||
printf("time_interval ? ");
|
||||
scanf("%d", &time_interval);
|
||||
register_app_event(wt, wrapper_generate_ospf_hello,
|
||||
(void *)&vlan_no, sizeof(vlan_no), time_interval, is_recursive);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 5:
|
||||
reset_wheel_timer(wt);
|
||||
break;
|
||||
case 6:
|
||||
exit(0);
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
while(1);
|
||||
}
|
||||
|
||||
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);
|
||||
start_wheel_timer(wt);
|
||||
|
||||
/* WT thread is in DETACHED MODE, so below call is useless*/
|
||||
//pthread_join(wt->wheel_thread->pthread_handle, &ret_val);
|
||||
|
||||
main_menu(wt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
7
WheelTimer/readme
Normal file
7
WheelTimer/readme
Normal file
@@ -0,0 +1,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
|
||||
|
||||
run ./exe to launch the application
|
||||
216
WheelTimer/threadApi.c
Normal file
216
WheelTimer/threadApi.c
Normal file
@@ -0,0 +1,216 @@
|
||||
#include "threadApi.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
blocked_pool_t gl_blocked_th_pool;
|
||||
|
||||
|
||||
_pthread_t*
|
||||
get_blocked_thread_from_pool(blocked_pool_t *block_pool){
|
||||
int i ;
|
||||
for (i = block_pool->pool_size -1; i >=0; i--){
|
||||
if(block_pool->blocked_thread_collection[i])
|
||||
return block_pool->blocked_thread_collection[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
dump_block_pool(blocked_pool_t *block_pool){
|
||||
printf("pool size = %d\n", block_pool->pool_size);
|
||||
unsigned int i = 0;
|
||||
for(;i < block_pool->pool_size; i++){
|
||||
if(block_pool->blocked_thread_collection[i]){
|
||||
printf("pool[%d] = %d\n", i, block_pool->blocked_thread_collection[i]->selfid);
|
||||
dump_thread_DS(block_pool->blocked_thread_collection[i]);
|
||||
}
|
||||
else
|
||||
printf("block_pool->blocked_thread_collection[%d] = NULL\n", i );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
is_thread_in_block_pool(unsigned int thid, blocked_pool_t *block_pool){
|
||||
int i ;
|
||||
for (i = 0; i < block_pool->pool_size; i++)
|
||||
{
|
||||
if(block_pool->blocked_thread_collection[i] &&
|
||||
block_pool->blocked_thread_collection[i]->selfid == thid){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
is_thread_in_block_pool_mutex(unsigned int thid, blocked_pool_t *block_pool){
|
||||
int i ;
|
||||
pthread_mutex_lock(&(block_pool->pool_mutex));
|
||||
for (i = 0; i < block_pool->pool_size; i++)
|
||||
{
|
||||
if(block_pool->blocked_thread_collection[i] &&
|
||||
block_pool->blocked_thread_collection[i]->selfid == thid){
|
||||
pthread_mutex_unlock(&(block_pool->pool_mutex));
|
||||
return i;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&(block_pool->pool_mutex));
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
void
|
||||
init_blocked_pool(blocked_pool_t *block_pool, unsigned int pool_size){
|
||||
int i = 0;
|
||||
block_pool->pool_size = pool_size;
|
||||
for (i = 0; i < pool_size; i++)
|
||||
block_pool->blocked_thread_collection[i] = NULL;
|
||||
pthread_mutex_init(&(block_pool->pool_mutex), NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
get_empty_slot_from_pool(blocked_pool_t *block_pool){
|
||||
int i;
|
||||
for(i = block_pool->pool_size -1; i >=0; i--){
|
||||
if(block_pool->blocked_thread_collection[i] == NULL)
|
||||
return i;
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
get_empty_slot_from_pool_mutex(blocked_pool_t *block_pool){
|
||||
int i;
|
||||
pthread_mutex_lock(&(block_pool->pool_mutex));
|
||||
for(i = block_pool->pool_size -1; i >=0; i--){
|
||||
if(block_pool->blocked_thread_collection[i] == NULL)
|
||||
pthread_mutex_unlock(&(block_pool->pool_mutex));
|
||||
return i;
|
||||
}
|
||||
pthread_mutex_unlock(&(block_pool->pool_mutex));
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
int
|
||||
remove_thread_from_pool(blocked_pool_t *block_pool, _pthread_t *thread){
|
||||
int loc = -1;
|
||||
if(thread->selfid > (block_pool->pool_size - 1)) return FAILURE;
|
||||
pthread_mutex_lock(&(block_pool->pool_mutex));
|
||||
if((loc = is_thread_in_block_pool(thread->selfid, block_pool)) > -1)
|
||||
{
|
||||
block_pool->blocked_thread_collection[loc] = NULL;
|
||||
printf("thread %d is removed from gl_blocked_th_pool\n", thread->selfid);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("thread %d already does not exist in gl_blocked_th_pool\n", thread->selfid);
|
||||
}
|
||||
pthread_mutex_unlock(&(block_pool->pool_mutex));
|
||||
return loc;
|
||||
}
|
||||
|
||||
void
|
||||
dump_thread_DS(_pthread_t *thread)
|
||||
{
|
||||
printf("===================================\n");
|
||||
printf("selfid = %d\n", thread->selfid);
|
||||
printf("pthread_handle = %ld\n", thread->pthread_handle);
|
||||
printf("isWaiting = %d\n", thread->isWaiting);
|
||||
printf("resume_thread_id = %d\n", thread->resume_thread_id);
|
||||
printf("attr = 0x%x\n", (unsigned int )&(thread->attr));
|
||||
printf("cond = 0x%x\n", (unsigned int )&(thread->cond));
|
||||
printf("===================================\n");
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
_pool_add(blocked_pool_t *block_pool, _pthread_t *thread)
|
||||
{
|
||||
int loc = -1;
|
||||
if(thread->selfid > block_pool->pool_size -1) return -1;
|
||||
loc = get_empty_slot_from_pool(block_pool);
|
||||
if(loc > -1){
|
||||
block_pool->blocked_thread_collection[loc] = thread;
|
||||
printf("thread %d is added to gl_blocked_th_pool at index %d\n", thread->selfid, loc);
|
||||
return loc;
|
||||
}
|
||||
else{
|
||||
printf("gl_blocked_th_pool is full, thread %d cannot be added\n", thread->selfid);
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
add_thread_to_pool(blocked_pool_t *block_pool , _pthread_t *thread)
|
||||
{
|
||||
if (!block_pool) return -1;
|
||||
int rc = SUCCESS;
|
||||
pthread_mutex_lock(&block_pool->pool_mutex);
|
||||
|
||||
if(is_thread_in_block_pool(thread->selfid, block_pool) < 0)
|
||||
{
|
||||
rc = _pool_add(block_pool, thread);
|
||||
pthread_mutex_unlock(&block_pool->pool_mutex);
|
||||
return rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Thread %d is already in blocked pool\n", thread->selfid);
|
||||
pthread_mutex_unlock(&block_pool->pool_mutex);
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
void pthread_init(_pthread_t *_pthread, unsigned int tid, unsigned int JOINABLE)
|
||||
{
|
||||
_pthread->selfid = tid;
|
||||
pthread_attr_init(&_pthread->attr);
|
||||
JOINABLE ? pthread_attr_setdetachstate(&_pthread->attr, PTHREAD_CREATE_JOINABLE):
|
||||
pthread_attr_setdetachstate(&_pthread->attr, PTHREAD_CREATE_DETACHED);
|
||||
pthread_cond_init(&_pthread->cond, NULL);
|
||||
_pthread->isWaiting = FALSE;
|
||||
_pthread->resume_thread_id = -1;
|
||||
}
|
||||
|
||||
void cleanup_pthread(_pthread_t *thread)
|
||||
{
|
||||
pthread_attr_destroy(&(thread->attr));
|
||||
pthread_cond_destroy(&(thread->cond));
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
wait_t (_pthread_t *thread_to_block, pthread_mutex_t *mutex, unsigned int line_no){
|
||||
pthread_mutex_lock(mutex);
|
||||
thread_to_block->isWaiting = TRUE;
|
||||
if(pthread_cond_wait (&(thread_to_block->cond), mutex)){
|
||||
printf("pthread_cond_wait failed, thread id = %d, line_no = %d", thread_to_block->selfid, line_no);
|
||||
thread_to_block->isWaiting = FALSE;
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
pthread_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
void
|
||||
signal_t (_pthread_t *signalled_thread){
|
||||
remove_thread_from_pool(&gl_blocked_th_pool, signalled_thread);
|
||||
if(pthread_cond_signal(&(signalled_thread->cond))){
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
signalled_thread->isWaiting = FALSE;
|
||||
signalled_thread->resume_thread_id = 0;
|
||||
}
|
||||
|
||||
void tentative_wait(_pthread_t *thread, pthread_mutex_t *mutex){
|
||||
if(is_thread_in_block_pool_mutex(0, &gl_blocked_th_pool) > -1)
|
||||
wait_t(thread, mutex, __LINE__);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
send_wait_order(_pthread_t *thread){
|
||||
add_thread_to_pool(&gl_blocked_th_pool, thread);
|
||||
}
|
||||
87
WheelTimer/threadApi.h
Normal file
87
WheelTimer/threadApi.h
Normal file
@@ -0,0 +1,87 @@
|
||||
#ifndef __PTHREAD__
|
||||
#define __PTHREAD__
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef SUCCESS
|
||||
#define SUCCESS 0
|
||||
#endif
|
||||
|
||||
#ifndef FAILURE
|
||||
#define FAILURE -1
|
||||
#endif
|
||||
|
||||
#define MAX_POOL_SIZE 100
|
||||
|
||||
typedef struct _pthread_t_{
|
||||
pthread_t pthread_handle;
|
||||
unsigned int selfid;
|
||||
char isWaiting;
|
||||
unsigned int resume_thread_id;
|
||||
pthread_attr_t attr;
|
||||
pthread_cond_t cond;
|
||||
} _pthread_t;
|
||||
|
||||
typedef struct _pool_blocked_threads_{
|
||||
unsigned int pool_size;
|
||||
_pthread_t* blocked_thread_collection[MAX_POOL_SIZE];
|
||||
pthread_mutex_t pool_mutex;
|
||||
} blocked_pool_t;
|
||||
|
||||
void
|
||||
dump_block_pool(blocked_pool_t *block_pool);
|
||||
|
||||
int
|
||||
is_thread_in_block_pool(unsigned int thid, blocked_pool_t *block_pool);
|
||||
|
||||
|
||||
int
|
||||
is_thread_in_block_pool_mutex(unsigned int thid, blocked_pool_t *block_pool);
|
||||
|
||||
void
|
||||
init_blocked_pool(blocked_pool_t *block_pool, unsigned int pool_size);
|
||||
|
||||
int
|
||||
get_empty_slot_from_pool(blocked_pool_t *block_pool);
|
||||
|
||||
int
|
||||
get_empty_slot_from_pool_mutex(blocked_pool_t *block_pool);
|
||||
|
||||
_pthread_t*
|
||||
get_blocked_thread_from_pool(blocked_pool_t *block_pool);
|
||||
|
||||
int
|
||||
remove_thread_from_pool(blocked_pool_t *block_pool , _pthread_t *thread);
|
||||
|
||||
int
|
||||
add_thread_to_pool(blocked_pool_t *block_pool, _pthread_t *thread);
|
||||
|
||||
void
|
||||
send_wait_order(_pthread_t *thread);
|
||||
|
||||
void
|
||||
dump_thread_DS(_pthread_t *thread);
|
||||
|
||||
void
|
||||
wait_t (_pthread_t *thread_to_block, pthread_mutex_t *mutex, unsigned int line_no);
|
||||
|
||||
void
|
||||
signal_t (_pthread_t *signalled_thread);
|
||||
|
||||
void
|
||||
pthread_init(_pthread_t *_pthread, unsigned int tid, unsigned int JOINABLE);
|
||||
|
||||
void
|
||||
cleanup_pthread(_pthread_t *thread);
|
||||
|
||||
void tentative_wait(_pthread_t *thread, pthread_mutex_t *mutex);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user