Exemple #1
0
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);

    lock_timer_heap(ht);
    if (!ht->cur_size && next_delay) {
	next_delay->sec = next_delay->msec = PJ_MAXINT32;
        unlock_timer_heap(ht);
	return 0;
    }

    count = 0;
    pj_gettickcount(&now);

    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);
	pj_grp_lock_t *grp_lock;

	++count;

	grp_lock = node->_grp_lock;
	node->_grp_lock = NULL;

	unlock_timer_heap(ht);

	PJ_RACE_ME(5);

	if (node->cb)
	    (*node->cb)(ht, node);

	if (grp_lock)
	    pj_grp_lock_dec_ref(grp_lock);

	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;
}
Exemple #2
0
PJ_DEF(pj_status_t) pj_timer_fire(int entry_code_id){
    pj_thread_desc a_thread_desc;
	pj_thread_t *a_thread;
	unsigned i, j;
	int entry_id, heap_id;
	pj_timer_entry *entry;

	entry_id = entry_code_id % MAX_ENTRY_PER_HEAP;
	heap_id = entry_code_id / MAX_ENTRY_PER_HEAP;

	if(heap_id < 0 || heap_id >= MAX_HEAPS){
		PJ_LOG(1, (THIS_FILE, "Invalid timer code %d", entry_code_id));
		return PJ_EINVAL;
	}

	// First step is to register the thread if not already done
	if (!pj_thread_is_registered()) {
		char thread_name[160];
		int len = pj_ansi_snprintf(thread_name, sizeof(thread_name),
				"timer_thread_%d", entry_code_id);
		thread_name[len] = '\0';
		pj_thread_register(thread_name, a_thread_desc, &a_thread);
		PJ_LOG(5, (THIS_FILE, "Registered thread %s", thread_name));
	}


	// Find corresponding ht
	pj_timer_heap_t *ht = sHeaps[heap_id];
	if (ht != NULL) {
		PJ_LOG(5, (THIS_FILE, "FIRE timer %d of heap %d", entry_id, heap_id));

		pj_timer_heap_callback* cb = NULL;
		lock_timer_heap(ht);

		// Get callback if entry valid
		entry = ht->entries[entry_id];
		if (entry != NULL && entry->_timer_id >= 0) {
			cb = entry->cb;
		}
        //unlock_timer_heap(ht);

        //lock_timer_heap(ht);
		// Release slot
		ht->entries[entry_id] = NULL;
		entry->_timer_id = -1;
		unlock_timer_heap(ht);

        // Callback may modify current entry (re-enqueue), so do not fire cb before release the slot
        if (cb) {
            cb(ht, entry);
        }

		PJ_LOG(5, (THIS_FILE, "FIRE done and released"));

	} else {
		PJ_LOG(2, (THIS_FILE, "FIRE Ignore : No heap found at %d for this entry %d", heap_id, entry_code_id));
	}

	return PJ_SUCCESS;
}
Exemple #3
0
PJ_DEF(pj_status_t) pj_timer_heap_schedule( pj_timer_heap_t *ht,
					    pj_timer_entry *entry, 
					    const pj_time_val *delay)
#endif
{
    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);

#if PJ_TIMER_DEBUG
    entry->src_file = src_file;
    entry->src_line = src_line;
#endif
    pj_gettickcount(&expires);
    PJ_TIME_VAL_ADD(expires, *delay);
    
    lock_timer_heap(ht);
    status = schedule_entry(ht, entry, &expires);
    unlock_timer_heap(ht);

    return status;
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #6
0
PJ_DEF(void) pj_timer_heap_destroy( pj_timer_heap_t *ht )
{
	int i;
	lock_timer_heap(ht);
	// Cancel all entries
	for (i = 0; i < MAX_ENTRY_PER_HEAP; i++) {
		if (ht->entries[i] != NULL) {
			pj_timer_entry *entry = ht->entries[i];
			cancel(ht, entry, 1);
		}
	}
	unlock_timer_heap(ht);

	if (ht->lock && ht->auto_delete_lock) {
		pj_lock_destroy(ht->lock);
		ht->lock = NULL;
	}
	sCurrentHeap++;
	sCurrentHeap = sCurrentHeap % MAX_HEAPS;
	sHeaps[ht->heap_id] = NULL;
}
Exemple #7
0
PJ_DEF(void) pj_timer_heap_dump(pj_timer_heap_t *ht)
{
    lock_timer_heap(ht);

    PJ_LOG(3,(THIS_FILE, "Dumping timer heap:"));
    PJ_LOG(3,(THIS_FILE, "  Cur size: %d entries, max: %d",
			 (int)ht->cur_size, (int)ht->max_size));

    if (ht->cur_size) {
	unsigned i;
	pj_time_val now;

	PJ_LOG(3,(THIS_FILE, "  Entries: "));
	PJ_LOG(3,(THIS_FILE, "    _id\tId\tElapsed\tSource"));
	PJ_LOG(3,(THIS_FILE, "    ----------------------------------"));

	pj_gettickcount(&now);

	for (i=0; i<(unsigned)ht->cur_size; ++i) {
	    pj_timer_entry *e = ht->heap[i];
	    pj_time_val delta;

	    if (PJ_TIME_VAL_LTE(e->_timer_value, now))
		delta.sec = delta.msec = 0;
	    else {
		delta = e->_timer_value;
		PJ_TIME_VAL_SUB(delta, now);
	    }

	    PJ_LOG(3,(THIS_FILE, "    %d\t%d\t%d.%03d\t%s:%d",
		      e->_timer_id, e->id,
		      (int)delta.sec, (int)delta.msec,
		      e->src_file, e->src_line));
	}
    }

    unlock_timer_heap(ht);
}
Exemple #8
0
static pj_status_t schedule_w_grp_lock(pj_timer_heap_t *ht,
                                       pj_timer_entry *entry,
                                       const pj_time_val *delay,
                                       pj_bool_t set_id,
                                       int id_val,
                                       pj_grp_lock_t *grp_lock)
#endif
{
    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);

#if PJ_TIMER_DEBUG
    entry->src_file = src_file;
    entry->src_line = src_line;
#endif
    pj_gettickcount(&expires);
    PJ_TIME_VAL_ADD(expires, *delay);
    
    lock_timer_heap(ht);
    status = schedule_entry(ht, entry, &expires);
    if (status == PJ_SUCCESS) {
	if (set_id)
	    entry->id = id_val;
	entry->_grp_lock = grp_lock;
	if (entry->_grp_lock) {
	    pj_grp_lock_add_ref(entry->_grp_lock);
	}
    }
    unlock_timer_heap(ht);

    return status;
}
Exemple #9
0
static int cancel_timer(pj_timer_heap_t *ht,
			pj_timer_entry *entry,
			unsigned flags,
			int id_val)
{
    int count;

    PJ_ASSERT_RETURN(ht && entry, PJ_EINVAL);

    lock_timer_heap(ht);
    count = cancel(ht, entry, flags | F_DONT_CALL);
    if (flags & F_SET_ID) {
	entry->id = id_val;
    }
    if (entry->_grp_lock) {
	pj_grp_lock_t *grp_lock = entry->_grp_lock;
	entry->_grp_lock = NULL;
	pj_grp_lock_dec_ref(grp_lock);
    }
    unlock_timer_heap(ht);

    return count;
}
Exemple #10
0
static int cancel_timer(pj_timer_heap_t *ht,
			pj_timer_entry *entry,
			pj_bool_t set_id,
			int id_val)
{
    int count;

    PJ_ASSERT_RETURN(ht && entry, PJ_EINVAL);

    lock_timer_heap(ht);
    count = cancel(ht, entry, 1);
    if (set_id) {
	entry->id = id_val;
    }
    if (entry->_grp_lock) {
	pj_grp_lock_t *grp_lock = entry->_grp_lock;
	entry->_grp_lock = NULL;
	pj_grp_lock_dec_ref(grp_lock);
    }
    unlock_timer_heap(ht);

    return count;
}