/**Run event and message loop for given duration. * * The function su_root_sleep() runs event loop for @a duration milliseconds. * The event loop waits for wait objects and the timers associated with the * @a root object. When any wait object is signaled, timer is expired, or * message is received, it invokes the callbacks and returns waiting. * * @param self pointer to root object * @param duration milliseconds to run event loop * * @retval milliseconds until next timer expiration */ su_duration_t su_root_sleep(su_root_t *self, su_duration_t duration) { su_duration_t retval, accrued = 0; su_time_t started; if (self == NULL) return (void)(errno = EFAULT), SU_WAIT_FOREVER; assert(self->sur_port); started = su_now(); do { retval = su_port_step(self->sur_port, duration - accrued); accrued = su_duration(su_now(), started); } while (accrued < duration); return retval; }
void TimerQueue::doTimer(su_timer_t* timer) { //self check assert( m_length == numberOfElements()) ; assert( 0 != m_length || (NULL == m_head && NULL == m_tail) ) ; assert( 1 != m_length || (m_head == m_tail)) ; assert( m_length < 2 || (m_head != m_tail)) ; assert( !(NULL == m_head && NULL != m_tail)) ; assert( !(NULL == m_tail && NULL != m_head)) ; #ifndef TEST DR_LOG(log_debug) << m_name << ": running timer function" ; #endif //std::cout << "doTimer: running timer function with " << m_length << " timers queued " << std::endl; if( m_in_timer ) return ; m_in_timer = 1 ; queueEntry_t* expired = NULL ; queueEntry_t* tailExpired = NULL ; su_time_t now = su_now() ; assert( NULL != m_head ) ; queueEntry_t* ptr = m_head ; while( ptr && su_time_cmp( ptr->m_when, now ) < 0 ) { //std::cout << "expiring a timer" << std::endl ; m_length-- ; m_head = ptr->m_next ; if( m_head ) m_head->m_prev = NULL ; else m_tail = NULL ; //detach and assemble them into a new queue temporarily if( !expired ) { expired = tailExpired = ptr ; ptr->m_prev = ptr->m_next = NULL ; } else { tailExpired->m_next = ptr ; ptr->m_prev = tailExpired ; tailExpired = ptr ; } ptr = ptr->m_next ; } if( NULL == m_head ) { #ifndef TEST DR_LOG(log_debug) << m_name << ": timer not set (queue is empty after processing expired timers), length: " << dec << m_length ; #endif //std::cout << "doTimer: timer not set (queue is empty after processing expired timers)" << std::endl; assert( 0 == m_length ) ; } else { //std::cout << "doTimer: Setting timer for " << su_duration( m_head->m_when, su_now() ) << "ms after processing expired timers" << std::endl; #ifndef TEST DR_LOG(log_debug) << m_name << ": Setting timer for " << su_duration( m_head->m_when, su_now() ) << "ms after processing expired timers, length: " << dec << m_length ; #endif int rc = su_timer_set_at(m_timer, timer_function, this, m_head->m_when); } m_in_timer = 0 ; while( NULL != expired ) { expired->m_function( expired->m_functionArgs ) ; queueEntry_t* p = expired ; expired = expired->m_next ; delete p ; } //self check assert( m_length == numberOfElements()) ; assert( 0 != m_length || (NULL == m_head && NULL == m_tail) ) ; assert( 1 != m_length || (m_head == m_tail)) ; assert( m_length < 2 || (m_head != m_tail)) ; assert( !(NULL == m_head && NULL != m_tail)) ; assert( !(NULL == m_tail && NULL != m_head)) ; }
void TimerQueue::remove( TimerEventHandle entry) { #ifndef TEST DR_LOG(log_debug) << m_name << ": removing entry, prior to removal length: " << dec << m_length; #endif //self check assert( m_length == numberOfElements()) ; assert( 0 != m_length || (NULL == m_head && NULL == m_tail) ) ; assert( 1 != m_length || (m_head == m_tail)) ; assert( m_length < 2 || (m_head != m_tail)) ; assert( !(NULL == m_head && NULL != m_tail)) ; assert( !(NULL == m_tail && NULL != m_head)) ; assert( m_head && m_length >= 1 ) ; int queueLength ; { if( m_head == entry ) { m_head = entry->m_next ; if( m_head ) m_head->m_prev = NULL ; else { assert( 1 == m_length ) ; m_tail = NULL ; } } else if( m_tail == entry ) { assert( m_head && entry->m_prev ) ; m_tail = entry->m_prev ; m_tail->m_next = NULL ; } else { assert( entry->m_prev ) ; assert( entry->m_next ) ; entry->m_prev->m_next = entry->m_next ; entry->m_next->m_prev = entry->m_prev ; } m_length-- ; assert( m_length >= 0 ) ; if( NULL == m_head ) { #ifndef TEST DR_LOG(log_debug) << m_name << ": removed entry, timer not set (queue is empty after removal), length: " << dec << m_length; #endif //std::cout << "timer not set (queue is empty after removal)" << std::endl; su_timer_reset( m_timer ) ; } else if( m_head == entry->m_next ) { #ifndef TEST DR_LOG(log_debug) << m_name << ": removed entry, setting timer for " << std::dec << su_duration( m_head->m_when, su_now() ) << "ms after removal, length: " << dec << m_length; #endif //std::cout << "Setting timer for " << su_duration( m_head->m_when, su_now() ) << "ms after removal of head entry" << std::endl; int rc = su_timer_set_at(m_timer, timer_function, this, m_head->m_when); } } //DR_LOG(log_debug) << "timer remove: queue length is now " << queueLength ; //std::cout << "timer remove: queue length is now " << queueLength << std::endl; delete entry ; //self check assert( m_length == numberOfElements()) ; assert( 0 != m_length || (NULL == m_head && NULL == m_tail) ) ; assert( 1 != m_length || (m_head == m_tail)) ; assert( m_length < 2 || (m_head != m_tail)) ; assert( !(NULL == m_head && NULL != m_tail)) ; assert( !(NULL == m_tail && NULL != m_head)) ; }