commit a2dc93136a28701a3fece16e5f9c0d245027079c Author: Hizenberg Date: Sat Jun 1 10:49:19 2024 +0530 Timer Library Complete diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bcaf499 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*vsidx +*.opendb +.vs +out +CMakePresets.json + + diff --git a/Assignment/CMakeLists.txt b/Assignment/CMakeLists.txt new file mode 100644 index 0000000..fc31ee1 --- /dev/null +++ b/Assignment/CMakeLists.txt @@ -0,0 +1,13 @@ +set(RT_SRC "rt.c") +set(RT_MAIN "rt_entry_expiration.c") + +set(RT_EXE rtManager) + +add_executable(${RT_EXE} ${RT_SRC} + ${RT_MAIN}) + +target_include_directories(${RT_EXE} PUBLIC + ${HEADER_DIR}) + +target_link_libraries(${RT_EXE} PUBLIC + ${TIMER_LIB}) diff --git a/Assignment/rt.c b/Assignment/rt.c new file mode 100644 index 0000000..9ecbf53 --- /dev/null +++ b/Assignment/rt.c @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include "rt.h" + +void +rt_init_rt_table(rt_table_t* rt_table) { + + rt_table->head = NULL; +} + +bool +rt_add_new_rt_entry(rt_table_t* rt_table, + char* dest, + char mask, + char* gw_ip, + char* oif, + void (*timer_cb)(Timer_t* , void* )) { + + rt_entry_t* head = NULL; + rt_entry_t* rt_entry = NULL; + + rt_entry = calloc(1, sizeof(rt_entry_t)); + + if (!rt_entry) + return false; + + strncpy(rt_entry->rt_entry_keys.dest, dest, sizeof(rt_entry->rt_entry_keys.dest)); + rt_entry->rt_entry_keys.mask = mask; + + if (gw_ip) + strncpy(rt_entry->gw_ip, gw_ip, sizeof(rt_entry->gw_ip)); + if (oif) + strncpy(rt_entry->oif, oif, sizeof(rt_entry->oif)); + + rt_entry->time_to_expire = RT_TABLE_EXP_TIME; + + rt_entry->timer = setup_timer((*timer_cb), RT_TABLE_EXP_TIME*1000, 0, 0, (void*)rt_entry, false); + + head = rt_table->head; + rt_table->head = rt_entry; + rt_entry->prev = 0; + rt_entry->next = head; + if (head) + head->prev = rt_entry; + + start_timer(rt_entry->timer); + return true; +} + +bool +rt_delete_rt_entry(rt_table_t* rt_table, + char* dest, char mask) { + + rt_entry_t* rt_entry = NULL; + + ITERTAE_RT_TABLE_BEGIN(rt_table, rt_entry) { + + if (strncmp(rt_entry->rt_entry_keys.dest, + dest, sizeof(rt_entry->rt_entry_keys.dest)) == 0 && + rt_entry->rt_entry_keys.mask == mask) { + + rt_entry_remove(rt_table, rt_entry); + + printf("deleting rt entry %p [%s:%d]\n", + rt_entry, rt_entry->rt_entry_keys.dest, + rt_entry->rt_entry_keys.mask); + + free(rt_entry); + return true; + } + } ITERTAE_RT_TABLE_END(rt_table, curr); + + return false; +} + +bool +rt_update_rt_entry(rt_table_t* rt_table, + char* dest, + char mask, + char* new_gw_ip, + char* new_oif) { + + return true; +} + +void +rt_clear_rt_table(rt_table_t* rt_table) { + + +} + +void +rt_free_rt_table(rt_table_t* rt_table) { + + +} + +void +rt_dump_rt_table(rt_table_t* rt_table) { + + rt_entry_t* rt_entry = NULL; + + ITERTAE_RT_TABLE_BEGIN(rt_table, rt_entry) { + + unsigned long time_in_milli_sec = timer_get_time_remaining_in_milli_sec(rt_entry->timer); + + printf("%-20s %-4d %-20s %-12s %usec (%lu)\n", + rt_entry->rt_entry_keys.dest, + rt_entry->rt_entry_keys.mask, + rt_entry->gw_ip, + rt_entry->oif, + rt_entry->time_to_expire, + time_in_milli_sec); + } ITERTAE_RT_TABLE_END(rt_tabl, rt_entry); +} \ No newline at end of file diff --git a/Assignment/rt.h b/Assignment/rt.h new file mode 100644 index 0000000..3872559 --- /dev/null +++ b/Assignment/rt.h @@ -0,0 +1,97 @@ +#ifndef __RT__ +#define __RT__ + +#include +#include +#include + +#define RT_TABLE_EXP_TIME 30 /* 30 sec */ + + +typedef struct rt_entry_keys_ { + + char dest[16]; + char mask; +} rt_entry_keys_t; + +typedef struct rt_entry_ { + + /* A Structure which represents only the keys of the + * Routing Table.*/ + rt_entry_keys_t rt_entry_keys; + + char gw_ip[16]; + char oif[32]; + uint32_t time_to_expire; /* time left to delete the entry */ + Timer_t* timer; + struct rt_entry_* prev; + struct rt_entry_* next; +} rt_entry_t; + +typedef struct rt_table_ { + + rt_entry_t* head; +} rt_table_t; + +void +rt_init_rt_table(rt_table_t* rt_table); + +bool +rt_add_new_rt_entry(rt_table_t* rt_table, + char* dest_ip, char mask, char* gw_ip, char* oif, void (*timer_cb)(Timer_t*, void*)); + +bool +rt_delete_rt_entry(rt_table_t* rt_table, + char* dest_ip, char mask); + +bool +rt_update_rt_entry(rt_table_t* rt_table, + char* dest_ip, char mask, + char* new_gw_ip, char* new_oif); + +void +rt_clear_rt_table(rt_table_t* rt_table); + +void +rt_free_rt_table(rt_table_t* rt_table); + +void +rt_dump_rt_table(rt_table_t* rt_table); + +static inline void +rt_entry_remove(rt_table_t* rt_table, + rt_entry_t* rt_entry) { + + if (!rt_entry->prev) { + if (rt_entry->next) { + rt_entry->next->prev = 0; + rt_table->head = rt_entry->next; + rt_entry->next = 0; + return; + } + rt_table->head = NULL; + return; + } + if (!rt_entry->next) { + rt_entry->prev->next = 0; + rt_entry->prev = 0; + return; + } + + rt_entry->prev->next = rt_entry->next; + rt_entry->next->prev = rt_entry->prev; + rt_entry->prev = 0; + rt_entry->next = 0; +} + +#define ITERTAE_RT_TABLE_BEGIN(rt_table_ptr, rt_entry_ptr) \ +{ \ + rt_entry_t *_next_rt_entry; \ + for((rt_entry_ptr) = (rt_table_ptr)->head; \ + (rt_entry_ptr); \ + (rt_entry_ptr) = _next_rt_entry) { \ + _next_rt_entry = (rt_entry_ptr)->next; + +#define ITERTAE_RT_TABLE_END(rt_table_ptr, rt_entry_ptr) }} + +#endif /* __RT__ */ \ No newline at end of file diff --git a/Assignment/rt_entry_expiration.c b/Assignment/rt_entry_expiration.c new file mode 100644 index 0000000..a49b0bb --- /dev/null +++ b/Assignment/rt_entry_expiration.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include +#include +#include "rt.h" + +static rt_table_t rt; + +void rt_entry_delete_on_timer_expiry(Timer_t* timer, void* user_data) { + + assert(timer != NULL); + assert(user_data != NULL); + + rt_entry_t* rt_entry = (rt_entry_t*)user_data; + + char dest_ip[16]; + strncpy(dest_ip,rt_entry->rt_entry_keys.dest, sizeof(rt_entry->rt_entry_keys.dest)); + char mask = rt_entry->rt_entry_keys.mask; + delete_timer(rt_entry->timer); + + assert(rt_delete_rt_entry(&rt, dest_ip, mask)); + + +} + +int +main(int argc, char** argv) { + + rt_init_rt_table(&rt); + + rt_add_new_rt_entry(&rt, "122.1.1.1", 32, "10.1.1.1", "eth0",rt_entry_delete_on_timer_expiry); + rt_add_new_rt_entry(&rt, "122.1.1.2", 32, "10.1.1.2", "eth1",rt_entry_delete_on_timer_expiry); + rt_add_new_rt_entry(&rt, "122.1.1.3", 32, "10.1.1.3", "eth2",rt_entry_delete_on_timer_expiry); + rt_add_new_rt_entry(&rt, "122.1.1.4", 32, "10.1.1.4", "eth3",rt_entry_delete_on_timer_expiry); + rt_add_new_rt_entry(&rt, "122.1.1.5", 32, "10.1.1.5", "eth4",rt_entry_delete_on_timer_expiry); + + while (1) { + printf("1. Add rt table entry\n"); + printf("2. Update rt table entry\n"); + printf("3. Delete rt table entry\n"); + printf("4. Dump rt table\n"); + + int choice; + printf("Enter Choice :"); + scanf("%d", &choice); + fflush(stdin); + switch (choice) { + case 1: + { + char dest[16]; + uint8_t mask; + char oif[32]; + char gw[16]; + printf("Enter Destination :"); + scanf("%s", dest); + printf("Mask : "); + scanf("%hhd", &mask); + printf("Enter oif name :"); + scanf("%s", oif); + printf("Enter Gateway IP :"); + scanf("%s", gw); + if (!rt_add_new_rt_entry(&rt, dest, mask, + gw, oif, rt_entry_delete_on_timer_expiry)) { + printf("Error : Could not add an entry\n"); + } + } + break; + case 2: + break; + case 3: + break; + case 4: + rt_dump_rt_table(&rt); + default: + ; + } + } + return 0; +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..854bd40 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.22.1) + +project(Timer-Library VERSION 1.0.0 LANGUAGES C CXX) + +set(CMAKE_C_STANDARD 17) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS OFF) + + +#Output file structure + +#Scheme 1 +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/$") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib/$") +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib/$") + +#Scheme 2 +#set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$/bin") +#set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$/lib") +#set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$/lib") + +#Library Name... +set(TIMER_LIB timer) + + +#Header file directory... +set(HEADER_DIR ${CMAKE_SOURCE_DIR}/include) + +#Source file directory... +set(SOURCE_DIR ${CMAKE_SOURCE_DIR}/src) + +#Adding Sub-directory having CMakeLists.txt... +add_subdirectory(src) +add_subdirectory(test) +add_subdirectory(Assignment) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..7537809 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Timer-Library diff --git a/include/timerlib.h b/include/timerlib.h new file mode 100644 index 0000000..dfd2d78 --- /dev/null +++ b/include/timerlib.h @@ -0,0 +1,174 @@ +#ifndef __TIMER_WRAP__ +#define __TIMER_WRAP__ + +//To use POSIX TIMER library +#define __USE_POSIX199309 1 + +#include +#include +#include +#include +#include +#include + + +/* +* Timer Data Structure, with attributes +* for controlling timer. +*/ + +typedef enum { + + TIMER_INIT, + TIMER_RUNNING, + TIMER_CANCELLED, + TIMER_DELETED, + TIMER_PAUSED, + TIMER_RESUMED + +} TIMER_STATE_T; + + + +typedef struct Timer_ { + + /* Timer config */ + timer_t* posix_timer; //Handle to Posix timer + void* user_arg; //Arg to passed to timer callback fun. + unsigned long exp_time; //expiration or fire time after timer start + unsigned long sec_exp_time; //expiration or fire time after first timer exp., used in periodic timer + uint32_t threshold; //No. of times to invoke the timer callback + void (*cb)(struct Timer_*, void*); //Function-pointer to timer callback + bool exponential_backoff; //If the timer is exponential type + + /* + * Dynamic Attributes of timer data structure: + * + * Attributes which change dynamically with exec. of + * program. + * + */ + + unsigned long time_remaining; //Time left for paused timer for next expiration/launch + uint32_t invocation_counter; //No. of times callback is invoked( Useful in periodic/exponential type) + struct itimerspec ts; + unsigned long exp_back_off_time; + TIMER_STATE_T timer_state; //State of the Timer object + +}Timer_t; + + + +/* +* Assignment-1 functions. +*/ + +unsigned long +timespec_to_millisec(struct timespec* time); + +void +timer_fill_itimerspec(struct timespec* ts, + unsigned long msec); + +/* +* Assignment-1 functions. +*/ + + + +/* +* Assignment-2 functions +*/ + +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; +} + +static inline void +timer_set_state(Timer_t* timer, TIMER_STATE_T timer_state) { + + timer->timer_state = timer_state; + +} + +/* +* Assignment-2 functions +*/ + + + +/*Return NULL in timer creation fails, else +return a pointer to Timer object*/ + +Timer_t* +setup_timer( + /* Timer Callback with user data and user size */ + void (*)(Timer_t*, void*), + /* First expiration timer interval in msec*/ + unsigned long, + /*Subsequent expiration time interval in msec*/ + unsigned long, + /*Max no of expiration, 0 for infinite */ + uint32_t, + /* Arg to timer callback */ + void*, + /* Is timer Exp back off */ + bool +); + +/*****APIs' to control timer******/ + +void +resurrect_timer(Timer_t* timer); + +void +start_timer(Timer_t* timer); + +unsigned long +timer_get_time_remaining_in_milli_sec(Timer_t* timer); + +void +pause_timer(Timer_t* timer); + + +void +resume_timer(Timer_t* timer); + +int +execute_timer(Timer_t* timer, TIMER_STATE_T action); + +void +delete_timer(Timer_t* timer); + +void +cancel_timer(Timer_t* timer); + +void +restart_timer(Timer_t* timer); + +void +reschedule_timer(Timer_t* timer, + unsigned long exp_ti, + unsigned long sec_exp_ti); + +void +print_timer(Timer_t* timer); + +bool +is_timer_running(Timer_t* timer); + + +/*****APIs' to control timer******/ + +#endif \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..521f184 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,23 @@ +#timerlib.c src file... +set(TIMER_LIB_SRC "timerlib.c") + +#Library +add_library(${TIMER_LIB} STATIC + ${TIMER_LIB_SRC}) + +#Including Header file dir... +target_include_directories(${TIMER_LIB} PUBLIC + ${HEADER_DIR}) + +#Linking dependent library... + +if( NOT (CMAKE_SYSTEM_NAME STREQUAL "Linux") ) + message(FATAL_ERROR "It's not a Unix-based system.\n \ + POSIX TIMER Library will not compile in this project.\n") +endif() + +set(POSIX_TIMER_LIB rt) + + +target_link_libraries(${TIMER_LIB} PUBLIC + ${POSIX_TIMER_LIB}) \ No newline at end of file diff --git a/src/timerlib.c b/src/timerlib.c new file mode 100644 index 0000000..47a54c8 --- /dev/null +++ b/src/timerlib.c @@ -0,0 +1,334 @@ +#include +#include +#include +#include +#include +#include "timerlib.h" + + +unsigned long +timespec_to_millisec(struct timespec* time) { + + unsigned long res_time = 0; + + res_time += (unsigned long)time->tv_sec * 1000; // For seconds to be in millisecond. + + res_time += (unsigned long)time->tv_nsec / 1000000; // For nanosecond to millisecond. + + return res_time; +} + +void +timer_fill_itimerspec(struct timespec* ts, + unsigned long msec) { + + memset(ts, 0, sizeof(struct timespec)); + + if (!msec) return; + + unsigned long sec = msec / 1000; + ts->tv_sec = sec; + + unsigned long remaining_msec = msec % 1000; + ts->tv_nsec = remaining_msec * (1000000); + +} + + +static void +timer_callback_wrapper(union sigval arg) { + + Timer_t* timer = (Timer_t*)(arg.sival_ptr); + + timer->invocation_counter++; + + if (timer->threshold && + (timer->invocation_counter > timer->threshold)) { + cancel_timer(timer); + return; + } + + if (timer->timer_state == TIMER_RESUMED) { + if (timer->sec_exp_time != 0) { + timer->timer_state = TIMER_RUNNING; + } + } + + (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); + } + else if (timer->timer_state == TIMER_RESUMED) { + + reschedule_timer(timer, + timer->exp_time, timer->sec_exp_time); + + } +} + +/*Return NULL in timer creation fails, else +return a pointer to Timer object*/ + +Timer_t* +setup_timer( + /* Timer Callback with user data and user size */ + void (*timer_cb)(Timer_t*, void*), + /* First expiration timer interval in msec*/ + unsigned long exp_timer, + /*Subsequent expiration time interval in msec*/ + unsigned long sec_exp_timer, + /*Max no of expiration, 0 for infinite */ + uint32_t threshold, + /* Arg to timer callback */ + void* user_arg, + /* Is timer Exp back off */ + bool exponential_backoff) { + + Timer_t* timer = calloc(1, sizeof(Timer_t)); + + timer->posix_timer = calloc(1, sizeof(timer_t)); + + timer->user_arg = user_arg; + timer->exp_time = exp_timer; + timer->sec_exp_time = sec_exp_timer; + timer->cb = timer_cb; + timer->threshold = threshold; + timer_set_state(timer, TIMER_INIT); + timer->exponential_backoff = exponential_backoff; + + /* Check for error */ + assert(timer->cb); + + struct sigevent evp; + memset(&evp, 0, sizeof(struct sigevent)); + + evp.sigev_value.sival_ptr = (void*)(timer); + + evp.sigev_notify = SIGEV_THREAD; + evp.sigev_notify_function = timer_callback_wrapper; + + int rc = timer_create(CLOCK_REALTIME, + &evp, + timer->posix_timer); + + assert(rc >= 0); + + timer_fill_itimerspec(&timer->ts.it_value, timer->exp_time); + + if (!timer->exponential_backoff) { + timer_fill_itimerspec(&timer->ts.it_interval, timer->sec_exp_time); + 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; +} + +/*****APIs' to control timer******/ + +void +resurrect_timer(Timer_t* timer) { + + int rc; + rc = timer_settime(*(timer->posix_timer), 0, &timer->ts, NULL); + assert(rc >= 0); +} + +void +start_timer(Timer_t* timer) { + + resurrect_timer(timer); + timer_set_state(timer, TIMER_RUNNING); +} + +void +delete_timer(Timer_t* timer) { + + int rc; + rc = timer_delete(*(timer->posix_timer)); + assert(rc >= 0); + timer->user_arg = NULL; /* User arg need to be freed by Appln */ + timer_set_state(timer, TIMER_DELETED); + free(timer->posix_timer); + free(timer); +} + +void +cancel_timer(Timer_t* timer) { + + TIMER_STATE_T timer_curr_state; + + timer_curr_state = timer_get_current_state(timer); + + if (timer_curr_state = TIMER_INIT || + timer_curr_state == TIMER_DELETED) { + + return; /* No operations */ + } + + /* Only Paused or running timer can be cancelled */ + + timer_fill_itimerspec(&timer->ts.it_value, 0); + timer_fill_itimerspec(&timer->ts.it_interval, 0); + timer->time_remaining = 0; + timer->invocation_counter = 0; + resurrect_timer(timer); + timer_set_state(timer, TIMER_CANCELLED); +} + +void +pause_timer(Timer_t* timer) { + + if (timer_get_current_state(timer) == TIMER_PAUSED) { + return; + } + + timer->time_remaining = + timer_get_time_remaining_in_milli_sec(timer); + + timer_fill_itimerspec(&timer->ts.it_value, 0); + timer_fill_itimerspec(&timer->ts.it_interval, 0); + + resurrect_timer(timer); + + timer_set_state(timer, TIMER_PAUSED); +} + +void +resume_timer(Timer_t* timer) { + + assert(timer_get_current_state(timer) == TIMER_PAUSED); + + timer_fill_itimerspec(&timer->ts.it_value, timer->time_remaining); + timer_fill_itimerspec(&timer->ts.it_interval, timer->sec_exp_time); + + timer->time_remaining = 0; + + resurrect_timer(timer); + timer_set_state(timer, TIMER_RESUMED); +} + +unsigned long +timer_get_time_remaining_in_milli_sec(Timer_t* timer) { + + struct itimerspec remaining_time; + + switch (timer->timer_state) { + + case TIMER_INIT: + break; + + case TIMER_DELETED: + return ~0; + + case TIMER_PAUSED: + break; + + case TIMER_CANCELLED: + return ~0; + + case TIMER_RUNNING: + break; + + default:; + + } + + memset(&remaining_time, 0, sizeof(struct itimerspec)); + + timer_gettime(*timer->posix_timer, &remaining_time); + + return timespec_to_millisec(&remaining_time.it_value); + +} + +void +restart_timer(Timer_t* timer) { + + assert(timer->timer_state != TIMER_DELETED); + + cancel_timer(timer); + + timer_fill_itimerspec(&timer->ts.it_value, + timer->exp_time); + + if (!timer->exponential_backoff) { + timer_fill_itimerspec(&timer->ts.it_interval, timer->sec_exp_time); + } + else { + timer_fill_itimerspec(&timer->ts.it_interval, 0); + } + + timer->invocation_counter = 0; + timer->time_remaining = 0; + timer->exp_back_off_time = timer->exp_time; + resurrect_timer(timer); + timer_set_state(timer, TIMER_RUNNING); +} + +void +reschedule_timer(Timer_t* timer, + unsigned long exp_ti, + unsigned long sec_exp_ti) { + + uint32_t invocation_counter; + TIMER_STATE_T timer_state; + + timer_state = timer_get_current_state(timer); + + if (timer_state == TIMER_DELETED) assert(0); + + invocation_counter = timer->invocation_counter; + + if (timer_state != TIMER_CANCELLED) { + cancel_timer(timer); + } + + timer->invocation_counter = invocation_counter; + timer_fill_itimerspec(&timer->ts.it_value, 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; + resurrect_timer(timer); + timer_set_state(timer, 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_milli_sec(timer), + timer_get_current_state(timer)); +} + +bool +is_timer_running(Timer_t* timer) { + + TIMER_STATE_T timer_state; + + timer_state = timer_get_current_state(timer); + + if (timer_state == TIMER_RUNNING || + timer_state == TIMER_RESUMED) { + return true; + } + + return false; +} + + +/*****APIs' to control timer******/ \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..046ac6d --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,12 @@ +set(TIMERLIB_TEST_EXE timerlib_test) + +set(TIMERLIB_TEST_SRC "timerlib_test.c") + +add_executable(${TIMERLIB_TEST_EXE} + ${TIMERLIB_TEST_SRC}) + +target_link_libraries(${TIMERLIB_TEST_EXE} PUBLIC + ${TIMER_LIB}) + +target_include_directories(${TIMERLIB_TEST_EXE} PUBLIC + ${HEADER_DIR}) \ No newline at end of file diff --git a/test/timerlib_test.c b/test/timerlib_test.c new file mode 100644 index 0000000..40f5d2b --- /dev/null +++ b/test/timerlib_test.c @@ -0,0 +1,66 @@ +#include +#include "timerlib.h" + +static void +user_defined_app_cb(Timer_t* timer, void* user_data) { + + printf("User data = %s\n", (char*)user_data); + +} + +int +main(int argc, char* argv[]) { + + char* name = "Junet"; + + Timer_t* timer = setup_timer(user_defined_app_cb, 1000, 1000, 0, name, false); + 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_time, + timer->sec_exp_time);*/ + 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; + default:; + } + } + return 0; +} \ No newline at end of file