📄 timer.c
字号:
ht->max_size = new_size;
}
static void insert_node(pj_timer_heap_t *ht, pj_timer_entry *new_node)
{
if (ht->cur_size + 2 >= ht->max_size)
grow_heap(ht);
reheap_up( ht, new_node, ht->cur_size, HEAP_PARENT(ht->cur_size));
ht->cur_size++;
}
static pj_status_t schedule_entry( pj_timer_heap_t *ht,
pj_timer_entry *entry,
const pj_time_val *future_time )
{
if (ht->cur_size < ht->max_size)
{
// Obtain the next unique sequence number.
// Set the entry
entry->_timer_id = pop_freelist(ht);
entry->_timer_value = *future_time;
insert_node( ht, entry);
return 0;
}
else
return -1;
}
static int cancel( pj_timer_heap_t *ht,
pj_timer_entry *entry,
int dont_call)
{
long timer_node_slot;
PJ_CHECK_STACK();
// Check to see if the timer_id is out of range
if (entry->_timer_id < 0 || (pj_size_t)entry->_timer_id > ht->max_size)
return 0;
timer_node_slot = ht->timer_ids[entry->_timer_id];
if (timer_node_slot < 0) // Check to see if timer_id is still valid.
return 0;
if (entry != ht->heap[timer_node_slot])
{
pj_assert(entry == ht->heap[timer_node_slot]);
return 0;
}
else
{
remove_node( ht, timer_node_slot);
if (dont_call == 0)
// Call the close hook.
(*ht->callback)(ht, entry);
return 1;
}
}
/*
* Calculate memory size required to create a timer heap.
*/
PJ_DEF(pj_size_t) pj_timer_heap_mem_size(pj_size_t count)
{
return /* size of the timer heap itself: */
sizeof(pj_timer_heap_t) +
/* size of each entry: */
(count+2) * (sizeof(pj_timer_entry*)+sizeof(pj_timer_id_t)) +
/* lock, pool etc: */
132;
}
/*
* Create a new timer heap.
*/
PJ_DEF(pj_status_t) pj_timer_heap_create( pj_pool_t *pool,
pj_size_t size,
pj_timer_heap_t **p_heap)
{
pj_timer_heap_t *ht;
pj_size_t i;
PJ_ASSERT_RETURN(pool && p_heap, PJ_EINVAL);
*p_heap = NULL;
/* Magic? */
size += 2;
/* Allocate timer heap data structure from the pool */
ht = PJ_POOL_ALLOC_T(pool, pj_timer_heap_t);
if (!ht)
return PJ_ENOMEM;
/* Initialize timer heap sizes */
ht->max_size = size;
ht->cur_size = 0;
ht->max_entries_per_poll = DEFAULT_MAX_TIMED_OUT_PER_POLL;
ht->timer_ids_freelist = 1;
ht->pool = pool;
/* Lock. */
ht->lock = NULL;
ht->auto_delete_lock = 0;
// Create the heap array.
ht->heap = (pj_timer_entry**)
pj_pool_alloc(pool, sizeof(pj_timer_entry*) * size);
if (!ht->heap)
return PJ_ENOMEM;
// Create the parallel
ht->timer_ids = (pj_timer_id_t *)
pj_pool_alloc( pool, sizeof(pj_timer_id_t) * size);
if (!ht->timer_ids)
return PJ_ENOMEM;
// Initialize the "freelist," which uses negative values to
// distinguish freelist elements from "pointers" into the <heap_>
// array.
for (i=0; i<size; ++i)
ht->timer_ids[i] = -((pj_timer_id_t) (i + 1));
*p_heap = ht;
return PJ_SUCCESS;
}
PJ_DEF(void) pj_timer_heap_destroy( pj_timer_heap_t *ht )
{
if (ht->lock && ht->auto_delete_lock) {
pj_lock_destroy(ht->lock);
ht->lock = NULL;
}
}
PJ_DEF(void) pj_timer_heap_set_lock( pj_timer_heap_t *ht,
pj_lock_t *lock,
pj_bool_t auto_del )
{
if (ht->lock && ht->auto_delete_lock)
pj_lock_destroy(ht->lock);
ht->lock = lock;
ht->auto_delete_lock = auto_del;
}
PJ_DEF(unsigned) pj_timer_heap_set_max_timed_out_per_poll(pj_timer_heap_t *ht,
unsigned count )
{
unsigned old_count = ht->max_entries_per_poll;
ht->max_entries_per_poll = count;
return old_count;
}
PJ_DEF(pj_timer_entry*) pj_timer_entry_init( pj_timer_entry *entry,
int id,
void *user_data,
pj_timer_heap_callback *cb )
{
pj_assert(entry && cb);
entry->id = id;
entry->user_data = user_data;
entry->cb = cb;
return entry;
}
PJ_DEF(pj_status_t) pj_timer_heap_schedule( pj_timer_heap_t *ht,
pj_timer_entry *entry,
const pj_time_val *delay)
{
pj_status_t status;
pj_time_val expires;
PJ_ASSERT_RETURN(ht && entry && delay, PJ_EINVAL);
PJ_ASSERT_RETURN(entry->cb != NULL, PJ_EINVAL);
/* Prevent same entry from being scheduled more than once */
PJ_ASSERT_RETURN(entry->_timer_id < 1, PJ_EINVALIDOP);
pj_gettimeofday(&expires);
PJ_TIME_VAL_ADD(expires, *delay);
lock_timer_heap(ht);
status = schedule_entry(ht, entry, &expires);
unlock_timer_heap(ht);
return status;
}
PJ_DEF(int) pj_timer_heap_cancel( pj_timer_heap_t *ht,
pj_timer_entry *entry)
{
int count;
PJ_ASSERT_RETURN(ht && entry, PJ_EINVAL);
lock_timer_heap(ht);
count = cancel(ht, entry, 1);
unlock_timer_heap(ht);
return count;
}
PJ_DEF(unsigned) pj_timer_heap_poll( pj_timer_heap_t *ht,
pj_time_val *next_delay )
{
pj_time_val now;
unsigned count;
PJ_ASSERT_RETURN(ht, 0);
if (!ht->cur_size && next_delay) {
next_delay->sec = next_delay->msec = PJ_MAXINT32;
return 0;
}
count = 0;
pj_gettimeofday(&now);
lock_timer_heap(ht);
while ( ht->cur_size &&
PJ_TIME_VAL_LTE(ht->heap[0]->_timer_value, now) &&
count < ht->max_entries_per_poll )
{
pj_timer_entry *node = remove_node(ht, 0);
++count;
unlock_timer_heap(ht);
if (node->cb)
(*node->cb)(ht, node);
lock_timer_heap(ht);
}
if (ht->cur_size && next_delay) {
*next_delay = ht->heap[0]->_timer_value;
PJ_TIME_VAL_SUB(*next_delay, now);
if (next_delay->sec < 0 || next_delay->msec < 0)
next_delay->sec = next_delay->msec = 0;
} else if (next_delay) {
next_delay->sec = next_delay->msec = PJ_MAXINT32;
}
unlock_timer_heap(ht);
return count;
}
PJ_DEF(pj_size_t) pj_timer_heap_count( pj_timer_heap_t *ht )
{
PJ_ASSERT_RETURN(ht, 0);
return ht->cur_size;
}
PJ_DEF(pj_status_t) pj_timer_heap_earliest_time( pj_timer_heap_t * ht,
pj_time_val *timeval)
{
pj_assert(ht->cur_size != 0);
if (ht->cur_size == 0)
return PJ_ENOTFOUND;
lock_timer_heap(ht);
*timeval = ht->heap[0]->_timer_value;
unlock_timer_heap(ht);
return PJ_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -