diff options
Diffstat (limited to 'branches/1.0/tinySAK/src/tsk_timer.c')
-rw-r--r-- | branches/1.0/tinySAK/src/tsk_timer.c | 531 |
1 files changed, 0 insertions, 531 deletions
diff --git a/branches/1.0/tinySAK/src/tsk_timer.c b/branches/1.0/tinySAK/src/tsk_timer.c deleted file mode 100644 index 0cb4ba0..0000000 --- a/branches/1.0/tinySAK/src/tsk_timer.c +++ /dev/null @@ -1,531 +0,0 @@ -/* -* Copyright (C) 2009-2010 Mamadou Diop. -* -* Contact: Mamadou Diop <diopmamadou(at)doubango.org> -* -* This file is part of Open Source Doubango Framework. -* -* DOUBANGO 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, either version 3 of the License, or -* (at your option) any later version. -* -* DOUBANGO 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 DOUBANGO. -* -*/ - -/**@file tsk_timer.c -* @brief Timer Manager. -* -* @author Mamadou Diop <diopmamadou(at)doubango.org> -* -* @date Created: Sat Nov 8 16:54:58 2009 mdiop -*/ -#include "tsk_timer.h" -#include "tsk_debug.h" -#include "tsk_list.h" -#include "tsk_thread.h" -#include "tsk_runnable.h" -#include "tsk_condwait.h" -#include "tsk_semaphore.h" -#include "tsk_time.h" - - -/**@defgroup tsk_timer_group Timers Management -*/ - -#define TSK_TIMER_CREATE(timeout, callback, arg) tsk_object_new(tsk_timer_def_t, timeout, callback, arg) -#define TSK_TIMER_TIMEOUT(self) ((tsk_timer_t*)self)->timeout -#define TSK_TIMER_GET_FIRST() (manager->timers && manager->timers->head) ? (tsk_timer_t*)(((tsk_list_item_t*)(manager->timers->head))->data) : 0 - -/** - * @struct tsk_timer_s - * @brief Timer. -**/ -typedef struct tsk_timer_s -{ - TSK_DECLARE_OBJECT; - - tsk_timer_id_t id; /**< Unique timer identifier. */ - const void *arg; /**< Opaque data to return with the callback function. */ - uint64_t timeout; /**< When the timer will timeout(as EPOCH time). */ - tsk_timer_callback_f callback; /**< The callback function to call after @ref timeout milliseconds. */ - - unsigned canceled:1; -} -tsk_timer_t; -typedef tsk_list_t tsk_timers_L_t; /**< List of @ref tsk_timer_t elements. */ - -/** - * @struct tsk_timer_manager_s - * - * @brief Timer manager. -**/ -typedef struct tsk_timer_manager_s -{ - TSK_DECLARE_RUNNABLE; - - void* mainThreadId[1]; - tsk_condwait_handle_t *condwait; - tsk_mutex_handle_t *mutex; - tsk_semaphore_handle_t *sem; - - tsk_timers_L_t *timers; -} -tsk_timer_manager_t; -typedef tsk_list_t tsk_timer_manager_L_t; /**< List of @ref tsk_timer_manager_t elements. */ - -/*== Definitions */ -static void *__tsk_timer_manager_mainthread(void *param); -static int __tsk_pred_find_timer_by_id(const tsk_list_item_t *item, const void *id); -static void __tsk_timer_manager_raise(tsk_timer_t *timer); -static void *run(void* self); - -/**@ingroup tsk_timer_group -*/ -tsk_timer_manager_handle_t* tsk_timer_manager_create() -{ - return tsk_object_new(tsk_timer_manager_def_t); -} - -/**@ingroup tsk_timer_group -* Starts the timer manager. -*/ -int tsk_timer_manager_start(tsk_timer_manager_handle_t *self) -{ - int err = -1; - tsk_timer_manager_t *manager = self; - - TSK_DEBUG_INFO("tsk_timer_manager_start"); - - if(!manager){ - return -1; - } - - tsk_mutex_lock(manager->mutex); - - if(!TSK_RUNNABLE(manager)->running && !TSK_RUNNABLE(manager)->started){ - TSK_RUNNABLE(manager)->run = run; - if(err = tsk_runnable_start(TSK_RUNNABLE(manager), tsk_timer_def_t)){ - //TSK_OBJECT_SAFE_FREE(manager); - goto bail; - } - } - else{ - TSK_DEBUG_WARN("Timer manager already running"); - } - -bail: - tsk_mutex_unlock(manager->mutex); - - return err; -} - -#if defined(DEBUG) || defined(_DEBUG) || !defined(NDEBUG) -/**@ingroup tsk_timer_group -*/ -void tsk_timer_manager_debug(tsk_timer_manager_handle_t *self) -{ - tsk_timer_manager_t *manager = self; - if(manager){ - //int index = 0; - tsk_list_item_t *item = tsk_null; - - tsk_mutex_lock(manager->mutex); - - tsk_list_foreach(item, manager->timers){ - tsk_timer_t* timer = item->data; - TSK_DEBUG_INFO("timer [%llu]- %llu, %llu", timer->id, timer->timeout, tsk_time_epoch()); - } - - tsk_mutex_unlock(manager->mutex); - } -} -#endif - -/**@ingroup tsk_timer_group -*/ -int tsk_timer_manager_stop(tsk_timer_manager_handle_t *self) -{ - int ret = -1; - tsk_timer_manager_t *manager = self; - - if(!manager){ - TSK_DEBUG_ERROR("Invalid paramater"); - return -1; - } - - // all functions called below are thread-safe ==> do not lock - // "mainthread" uses manager->mutex and runs in a separate thread ==> deadlock - - if(TSK_RUNNABLE(manager)->running){ - if(ret = tsk_runnable_stop(TSK_RUNNABLE(manager))){ - goto bail; - } - - tsk_semaphore_increment(manager->sem); - tsk_condwait_signal(manager->condwait); - - ret = tsk_thread_join(manager->mainThreadId); - goto bail; - } - else{ - ret = 0; /* already running. */ - goto bail; - } - -bail: - return ret; -} - -/**@ingroup tsk_timer_group -*/ -tsk_timer_id_t tsk_timer_manager_schedule(tsk_timer_manager_handle_t *self, uint64_t timeout, tsk_timer_callback_f callback, const void *arg) -{ - tsk_timer_id_t timer_id = TSK_INVALID_TIMER_ID; - tsk_timer_manager_t *manager = self; - - if(manager && (TSK_RUNNABLE(manager)->running || TSK_RUNNABLE(manager)->started)){ - tsk_timer_t *timer; - - timer = TSK_TIMER_CREATE(timeout, callback, arg); - timer_id = timer->id; - tsk_mutex_lock(manager->mutex); - tsk_list_push_ascending_data(manager->timers, ((void**) &timer)); - tsk_mutex_unlock(manager->mutex); - - //tsk_timer_manager_debug(self); - - tsk_condwait_signal(manager->condwait); - tsk_semaphore_increment(manager->sem); - } - - return timer_id; -} - -/**@ingroup tsk_timer_group -*/ -int tsk_timer_manager_cancel(tsk_timer_manager_handle_t *self, tsk_timer_id_t id) -{ - int ret = -1; - tsk_timer_manager_t *manager = self; - - /* Check validity. */ - if(!TSK_TIMER_ID_IS_VALID(id)){ /* Very common. */ - return 0; - } - - if(!TSK_LIST_IS_EMPTY(manager->timers) && TSK_RUNNABLE(manager)->running){ - const tsk_list_item_t *item; - tsk_mutex_lock(manager->mutex); - item = tsk_list_find_item_by_pred(manager->timers, __tsk_pred_find_timer_by_id, &id); - if(item && item->data){ - tsk_timer_t *timer = item->data; - timer->canceled = 1; - - if(item == manager->timers->head){ - /* The timer we are waiting on ? ==> remove it now. */ - tsk_condwait_signal(manager->condwait); - } - - ret = 0; - } - tsk_mutex_unlock(manager->mutex); - } - return ret; -} - -static void *run(void* self) -{ - int ret; - tsk_list_item_t *curr; - tsk_timer_manager_t *manager = self; - - TSK_RUNNABLE(manager)->running = tsk_true; // VERY IMPORTANT --> needed by the main thread - - /* create main thread */ - if((ret = tsk_thread_create(&(manager->mainThreadId[0]), __tsk_timer_manager_mainthread, manager))){ - TSK_DEBUG_FATAL("Failed to create mainthread: %d\n", ret); - return tsk_null; - } - - TSK_DEBUG_INFO("Timer manager run()::enter"); - - TSK_RUNNABLE_RUN_BEGIN(manager); - - if(curr = TSK_RUNNABLE_POP_FIRST(manager)){ - tsk_timer_t *timer = (tsk_timer_t *)curr->data; - if(timer->callback){ - timer->callback(timer->arg, timer->id); - } - tsk_object_unref(curr); - } - - TSK_RUNNABLE_RUN_END(manager); - - TSK_DEBUG_INFO("Timer manager run()::exit"); - - return tsk_null; -} - -static int __tsk_pred_find_timer_by_id(const tsk_list_item_t *item, const void *id) -{ - tsk_timer_t *timer; - if(item && item->data){ - timer = item->data; - return (int)(timer->id - *((tsk_timer_id_t*)id)); - } - return -1; -} - -static void *__tsk_timer_manager_mainthread(void *param) -{ - int ret; - tsk_timer_t *curr; - uint64_t epoch; - tsk_timer_manager_t *manager = param; - - TSK_DEBUG_INFO("TIMER MANAGER -- START"); - - while(TSK_RUNNABLE(manager)->running){ - tsk_semaphore_decrement(manager->sem); - -peek_first: - if(!TSK_RUNNABLE(manager)->running){ - break; - } - - tsk_mutex_lock(manager->mutex); - curr = TSK_TIMER_GET_FIRST(); - tsk_mutex_unlock(manager->mutex); - - if(curr && !curr->canceled) { - epoch = tsk_time_epoch(); - if(epoch >= curr->timeout){ - tsk_timer_t *timer = tsk_object_ref(curr); - //TSK_DEBUG_INFO("Timer raise %llu", timer->id); - - tsk_mutex_lock(manager->mutex); - TSK_RUNNABLE_ENQUEUE_OBJECT(TSK_RUNNABLE(manager), timer); - tsk_list_remove_item_by_data(manager->timers, curr); - tsk_mutex_unlock(manager->mutex); - } - else{ - if((ret = tsk_condwait_timedwait(manager->condwait, (curr->timeout - epoch)))){ - TSK_DEBUG_ERROR("CONWAIT for timer manager failed [%d]", ret); - break; - } - else{ - goto peek_first; - } - } - } - else if(curr){ - tsk_mutex_lock(manager->mutex); - /* TSK_DEBUG_INFO("Timer canceled %llu", curr->id); */ - tsk_list_remove_item_by_data(manager->timers, curr); - tsk_mutex_unlock(manager->mutex); - } - } /* while() */ - - TSK_DEBUG_INFO("TIMER MANAGER -- STOP"); - - return 0; -} - - - - - -/* ================= Global Timer Manager ================= */ - -static tsk_timer_manager_t* __timer_mgr = tsk_null; -static int __timer_mgr_start_count = 0; - -int tsk_timer_mgr_global_ref() -{ - if(!__timer_mgr){ - __timer_mgr = tsk_timer_manager_create(); - } - else{ - __timer_mgr = tsk_object_ref(__timer_mgr); - } - return 0; -} - -int tsk_timer_mgr_global_start() -{ - int ret = 0; - if(!__timer_mgr){ - TSK_DEBUG_ERROR("No global Timer manager could be found"); - return -1; - } - if(!TSK_RUNNABLE(__timer_mgr)->running && !TSK_RUNNABLE(__timer_mgr)->started){ - if((ret = tsk_timer_manager_start(__timer_mgr))){ - return ret; - } - } - __timer_mgr_start_count++; - return ret; -} - -tsk_timer_id_t tsk_timer_mgr_global_schedule(uint64_t timeout, tsk_timer_callback_f callback, const void *arg) -{ - if(!__timer_mgr){ - TSK_DEBUG_ERROR("No global Timer manager could be found"); - return TSK_INVALID_TIMER_ID; - } - return tsk_timer_manager_schedule(__timer_mgr, timeout, callback, arg); -} - -int tsk_timer_mgr_global_cancel(tsk_timer_id_t id) -{ - if(!__timer_mgr){ - TSK_DEBUG_ERROR("No global Timer manager could be found"); - return -1; - } - return tsk_timer_manager_cancel(__timer_mgr, id); -} - -int tsk_timer_mgr_global_stop() -{ - int ret = 0; - if(!__timer_mgr){ - TSK_DEBUG_ERROR("No global Timer manager could be found"); - return -1; - } - - if(__timer_mgr_start_count <= 0){ - TSK_DEBUG_ERROR("Global Timer is in an invalid state"); - return -2; - } - - if(TSK_RUNNABLE(__timer_mgr)->running){ - if(__timer_mgr_start_count == 1){ - if((ret = tsk_timer_manager_stop(__timer_mgr))){ - return ret; - } - } - __timer_mgr_start_count--; - } - return 0; -} - -int tsk_timer_mgr_global_unref() -{ - if(!__timer_mgr){ - TSK_DEBUG_ERROR("No global Timer manager could be found"); - return -1; - } - - __timer_mgr = tsk_object_unref(__timer_mgr); - - return 0; -} - - - - - - - -//================================================================================================= -// Timer manager object definition -// -static tsk_object_t* tsk_timer_manager_ctor(tsk_object_t * self, va_list * app) -{ - tsk_timer_manager_t *manager = self; - if(manager){ - manager->timers = tsk_list_create(); - manager->sem = tsk_semaphore_create(); - manager->condwait = tsk_condwait_create(); - manager->mutex = tsk_mutex_create(); - } - return self; -} - -static tsk_object_t* tsk_timer_manager_dtor(tsk_object_t * self) -{ - tsk_timer_manager_t *manager = self; - - if(manager){ - tsk_timer_manager_stop(manager); - - tsk_semaphore_destroy(&manager->sem); - tsk_condwait_destroy(&manager->condwait); - tsk_mutex_destroy(&manager->mutex); - tsk_object_unref(manager->timers); - } - - return self; -} - -static const tsk_object_def_t tsk_timer_manager_def_s = -{ - sizeof(tsk_timer_manager_t), - tsk_timer_manager_ctor, - tsk_timer_manager_dtor, - tsk_null, -}; -const tsk_object_def_t * tsk_timer_manager_def_t = &tsk_timer_manager_def_s; - - - - - - -//================================================================================================= -// Timer object definition -// -static tsk_object_t* tsk_timer_ctor(tsk_object_t * self, va_list * app) -{ - static tsk_timer_id_t tsk_unique_timer_id = 1; - tsk_timer_t *timer = self; - if(timer){ - timer->id = tsk_unique_timer_id++; - timer->timeout = va_arg(*app, uint64_t); - timer->callback = va_arg(*app, tsk_timer_callback_f); - timer->arg = va_arg(*app, const void *); - - timer->timeout += tsk_time_epoch(); - } - return self; -} - -static tsk_object_t* tsk_timer_dtor(tsk_object_t * self) -{ - tsk_timer_t *timer = self; - if(timer){ - } - - return self; -} - -static int tsk_timer_cmp(const tsk_object_t *obj1, const tsk_object_t *obj2) -{ - const tsk_timer_t *t1 = obj1; - const tsk_timer_t *t2 = obj2; - - if(t1 && t2){ - return (int)(t1->timeout - t2->timeout); - } - else if(!t1 && !t2) return 0; - else return -1; -} - -static const tsk_object_def_t tsk_timer_def_s = -{ - sizeof(tsk_timer_t), - tsk_timer_ctor, - tsk_timer_dtor, - tsk_timer_cmp, -}; -const tsk_object_def_t * tsk_timer_def_t = &tsk_timer_def_s; - - |