388 lines
12 KiB
C
388 lines
12 KiB
C
|
/* $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 <pj/types.h>
|
||
|
#include <pj/lock.h>
|
||
|
|
||
|
#if PJ_TIMER_USE_LINKED_LIST
|
||
|
# include <pj/list.h>
|
||
|
#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 <d.schmidt@vanderbilt.edu>
|
||
|
*
|
||
|
* @{
|
||
|
*
|
||
|
* \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.
|
||
|
* Positive values indicate that the timer entry is running,
|
||
|
* while -1 means that it's not. Any other value may indicate that it
|
||
|
* hasn't been properly initialised or is in a bad state.
|
||
|
* 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__ */
|
||
|
|