/* $Id$ */ /* * 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; either version 2 of the License, or * (at your option) any later version. * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __PJ_TIMER_H__ #define __PJ_TIMER_H__ /** * @file timer.h * @brief Timer Heap */ #include #include #if PJ_TIMER_USE_LINKED_LIST # include #endif PJ_BEGIN_DECL /** * @defgroup PJ_TIMER Timer Heap Management. * @ingroup PJ_MISC * @brief * The timer scheduling implementation here is based on ACE library's * ACE_Timer_Heap, with only little modification to suit our library's style * (I even left most of the comments in the original source). * * To quote the original quote in ACE_Timer_Heap_T class: * * This implementation uses a heap-based callout queue of * absolute times. Therefore, in the average and worst case, * scheduling, canceling, and expiring timers is O(log N) (where * N is the total number of timers). In addition, we can also * preallocate as many \a ACE_Timer_Nodes as there are slots in * the heap. This allows us to completely remove the need for * dynamic memory allocation, which is important for real-time * systems. * * You can find the fine ACE library at: * http://www.cs.wustl.edu/~schmidt/ACE.html * * ACE is Copyright (C)1993-2006 Douglas C. Schmidt * * @{ * * \section pj_timer_examples_sec Examples * * For some examples on how to use the timer heap, please see the link below. * * - \ref page_pjlib_timer_test */ /** * The type for internal timer ID. */ typedef int pj_timer_id_t; /** * Forward declaration for pj_timer_entry. */ struct pj_timer_entry; /** * The type of callback function to be called by timer scheduler when a timer * has expired. * * @param timer_heap The timer heap. * @param entry Timer entry which timer's has expired. */ typedef void pj_timer_heap_callback(pj_timer_heap_t *timer_heap, struct pj_timer_entry *entry); /** * This structure represents an entry to the timer. */ typedef struct pj_timer_entry { #if !PJ_TIMER_USE_COPY && PJ_TIMER_USE_LINKED_LIST /** * Standard list members. */ PJ_DECL_LIST_MEMBER(struct pj_timer_entry); #endif /** * User data to be associated with this entry. * Applications normally will put the instance of object that * owns the timer entry in this field. */ void *user_data; /** * Arbitrary ID assigned by the user/owner of this entry. * Applications can use this ID to distinguish multiple * timer entries that share the same callback and user_data. */ int id; /** * Callback to be called when the timer expires. */ pj_timer_heap_callback *cb; /** * Internal unique timer ID, which is assigned by the timer heap. * Application should not touch this ID. */ pj_timer_id_t _timer_id; #if !PJ_TIMER_USE_COPY /** * The future time when the timer expires, which the value is updated * by timer heap when the timer is scheduled. */ pj_time_val _timer_value; /** * Internal: the group lock used by this entry, set when * pj_timer_heap_schedule_w_lock() is used. */ pj_grp_lock_t *_grp_lock; #if PJ_TIMER_DEBUG const char *src_file; int src_line; #endif #endif } pj_timer_entry; /** * Calculate memory size required to create a timer heap. * * @param count Number of timer entries to be supported. * @return Memory size requirement in bytes. */ PJ_DECL(pj_size_t) pj_timer_heap_mem_size(pj_size_t count); /** * Create a timer heap. * * @param pool The pool where allocations in the timer heap will be * allocated. The timer heap will dynamicly allocate * more storate from the pool if the number of timer * entries registered is more than the size originally * requested when calling this function. * @param count The maximum number of timer entries to be supported * initially. If the application registers more entries * during runtime, then the timer heap will resize. * @param ht Pointer to receive the created timer heap. * * @return PJ_SUCCESS, or the appropriate error code. */ PJ_DECL(pj_status_t) pj_timer_heap_create( pj_pool_t *pool, pj_size_t count, pj_timer_heap_t **ht); /** * Destroy the timer heap. * * @param ht The timer heap. */ PJ_DECL(void) pj_timer_heap_destroy( pj_timer_heap_t *ht ); /** * Set lock object to be used by the timer heap. By default, the timer heap * uses dummy synchronization. * * @param ht The timer heap. * @param lock The lock object to be used for synchronization. * @param auto_del If nonzero, the lock object will be destroyed when * the timer heap is destroyed. */ PJ_DECL(void) pj_timer_heap_set_lock( pj_timer_heap_t *ht, pj_lock_t *lock, pj_bool_t auto_del ); /** * Set maximum number of timed out entries to process in a single poll. * * @param ht The timer heap. * @param count Number of entries. * * @return The old number. */ PJ_DECL(unsigned) pj_timer_heap_set_max_timed_out_per_poll(pj_timer_heap_t *ht, unsigned count ); /** * Initialize a timer entry. Application should call this function at least * once before scheduling the entry to the timer heap, to properly initialize * the timer entry. * * @param entry The timer entry to be initialized. * @param id Arbitrary ID assigned by the user/owner of this entry. * Applications can use this ID to distinguish multiple * timer entries that share the same callback and user_data. * @param user_data User data to be associated with this entry. * Applications normally will put the instance of object that * owns the timer entry in this field. * @param cb Callback function to be called when the timer elapses. * * @return The timer entry itself. */ PJ_DECL(pj_timer_entry*) pj_timer_entry_init( pj_timer_entry *entry, int id, void *user_data, pj_timer_heap_callback *cb ); /** * Queries whether a timer entry is currently running. * * @param entry The timer entry to query. * * @return PJ_TRUE if the timer is running. PJ_FALSE if not. */ PJ_DECL(pj_bool_t) pj_timer_entry_running( pj_timer_entry *entry ); /** * Schedule a timer entry which will expire AFTER the specified delay. * * @param ht The timer heap. * @param entry The entry to be registered. * @param delay The interval to expire. * @return PJ_SUCCESS, or the appropriate error code. */ #if PJ_TIMER_DEBUG # define pj_timer_heap_schedule(ht,e,d) \ pj_timer_heap_schedule_dbg(ht,e,d,__FILE__,__LINE__) PJ_DECL(pj_status_t) pj_timer_heap_schedule_dbg( pj_timer_heap_t *ht, pj_timer_entry *entry, const pj_time_val *delay, const char *src_file, int src_line); #else PJ_DECL(pj_status_t) pj_timer_heap_schedule( pj_timer_heap_t *ht, pj_timer_entry *entry, const pj_time_val *delay); #endif /* PJ_TIMER_DEBUG */ /** * Schedule a timer entry which will expire AFTER the specified delay, and * increment the reference counter of the group lock while the timer entry * is active. The group lock reference counter will automatically be released * after the timer callback is called or when the timer is cancelled. * * @param ht The timer heap. * @param entry The entry to be registered. * @param delay The interval to expire. * @param id_val The value to be set to the "id" field of the timer entry * once the timer is scheduled. * @param grp_lock The group lock. * * @return PJ_SUCCESS, or the appropriate error code. */ #if PJ_TIMER_DEBUG # define pj_timer_heap_schedule_w_grp_lock(ht,e,d,id,g) \ pj_timer_heap_schedule_w_grp_lock_dbg(ht,e,d,id,g,__FILE__,__LINE__) PJ_DECL(pj_status_t) pj_timer_heap_schedule_w_grp_lock_dbg( pj_timer_heap_t *ht, pj_timer_entry *entry, const pj_time_val *delay, int id_val, pj_grp_lock_t *grp_lock, const char *src_file, int src_line); #else PJ_DECL(pj_status_t) pj_timer_heap_schedule_w_grp_lock( pj_timer_heap_t *ht, pj_timer_entry *entry, const pj_time_val *delay, int id_val, pj_grp_lock_t *grp_lock); #endif /* PJ_TIMER_DEBUG */ /** * Cancel a previously registered timer. This will also decrement the * reference counter of the group lock associated with the timer entry, * if the entry was scheduled with one. * * @param ht The timer heap. * @param entry The entry to be cancelled. * @return The number of timer cancelled, which should be one if the * entry has really been registered, or zero if no timer was * cancelled. */ PJ_DECL(int) pj_timer_heap_cancel( pj_timer_heap_t *ht, pj_timer_entry *entry); /** * Cancel only if the previously registered timer is active. This will * also decrement the reference counter of the group lock associated * with the timer entry, if the entry was scheduled with one. In any * case, set the "id" to the specified value. * * @param ht The timer heap. * @param entry The entry to be cancelled. * @param id_val Value to be set to "id" * * @return The number of timer cancelled, which should be one if the * entry has really been registered, or zero if no timer was * cancelled. */ PJ_DECL(int) pj_timer_heap_cancel_if_active(pj_timer_heap_t *ht, pj_timer_entry *entry, int id_val); /** * Get the number of timer entries. * * @param ht The timer heap. * @return The number of timer entries. */ PJ_DECL(pj_size_t) pj_timer_heap_count( pj_timer_heap_t *ht ); /** * Get the earliest time registered in the timer heap. The timer heap * MUST have at least one timer being scheduled (application should use * #pj_timer_heap_count() before calling this function). * * @param ht The timer heap. * @param timeval The time deadline of the earliest timer entry. * * @return PJ_SUCCESS, or PJ_ENOTFOUND if no entry is scheduled. */ PJ_DECL(pj_status_t) pj_timer_heap_earliest_time( pj_timer_heap_t *ht, pj_time_val *timeval); /** * Poll the timer heap, check for expired timers and call the callback for * each of the expired timers. * * Note: polling the timer heap is not necessary in Symbian. Please see * @ref PJ_SYMBIAN_OS for more info. * * @param ht The timer heap. * @param next_delay If this parameter is not NULL, it will be filled up with * the time delay until the next timer elapsed, or * PJ_MAXINT32 in the sec part if no entry exist. * * @return The number of timers expired. */ PJ_DECL(unsigned) pj_timer_heap_poll( pj_timer_heap_t *ht, pj_time_val *next_delay); #if PJ_TIMER_DEBUG /** * Dump timer heap entries. * * @param ht The timer heap. */ PJ_DECL(void) pj_timer_heap_dump(pj_timer_heap_t *ht); #endif /** * @} */ PJ_END_DECL #endif /* __PJ_TIMER_H__ */