Пример #1
0
void Timers::Execute()
{
    timeval curTime;
    gettimeofday(&curTime, 0);

    for (Timer* s = m_firstTimer; s != 0; s = m_firstTimer)
    {
        if (CompareTimevals(s->GetNextExecution(), curTime))
            break;

        TimerCbk_t cbk = s->GetCallback();
        void* userdata = s->GetUserdata();
        s->Update();
        int remainingReps = s->GetRemainingRepetitions();

        cbk(userdata);

        if (FindTimer(s))
        {
            DeleteFromList(s);
            if (remainingReps == 0)
                delete s;
            else
                InsertTimer(s);
        }
    }
}
Пример #2
0
Timer* Timers::Create(TimerCbk_t cbk, int nrep, unsigned int ms, void* userData)
{
    if (ms < 10)
        return 0;

    Timer* newTimer = new Timer(cbk, nrep, ms, userData);
    InsertTimer(newTimer);

    return newTimer;
}
Пример #3
0
/**
    \param pArg a pointer to a timer structure that the user has filled with desired timer properties.
    \sa timeElement, cancelTimer, modifyTimer
*/
void Timer::startTimer (p_timeElement pArg)
{
	pArg->setTimeOut (_presentTime + pArg->getTimePeriod ()); // Set the expiration time.

	// Search the _timeOutList for correct insertion point to keep the list sorted.
	// This saves the interrupt service routine from needing to check every timer
	// for expiration; if timer[0] has not expired, then none have because the list
	// is sorted.

	InsertTimer (pArg);
}
Пример #4
0
// Timeout() is called when a select() time out.  Returns number of seconds
// until next timeout event, a 0 if there are no more events, or a -1 if
// called while a handler is active (i.e. handler calls Timeout;
// Timeout is not re-entrant).
int
TimerManager::Timeout(int * pNumFired /*= NULL*/, double * pruntime /*=NULL*/)
{
	int				result, timer_check_cntr;
	time_t			now, time_sample;
	int				num_fires = 0;	// num of handlers called in this timeout

    if (pNumFired) *pNumFired = 0;

	if ( in_timeout != NULL ) {
		dprintf(D_DAEMONCORE,"DaemonCore Timeout() called and in_timeout is non-NULL\n");
		if ( timer_list == NULL ) {
			result = 0;
		} else {
			result = (timer_list->when) - time(NULL);
		}
		if ( result < 0 ) {
			result = 0;
		}
		return(result);
	}
		
	dprintf( D_DAEMONCORE, "In DaemonCore Timeout()\n");

	if (timer_list == NULL) {
		dprintf( D_DAEMONCORE, "Empty timer list, nothing to do\n" );
	}

	time(&now);
	timer_check_cntr = 0;

	DumpTimerList(D_DAEMONCORE | D_FULLDEBUG);

	// loop until all handlers that should have been called by now or before
	// are invoked and renewed if periodic.  Remember that NewTimer and CancelTimer
	// keep the timer_list happily sorted on "when" for us.  We use "now" as a 
	// variable so that if some of these handler functions run for a long time,
	// we do not sit in this loop forever.
	// we make certain we do not call more than "max_fires" handlers in a 
	// single timeout --- this ensures that timers don't starve out the rest
	// of daemonCore if a timer handler resets itself to 0.
	while( (timer_list != NULL) && (timer_list->when <= now ) && 
		   (num_fires++ < MAX_FIRES_PER_TIMEOUT)) 
	{
		// DumpTimerList(D_DAEMONCORE | D_FULLDEBUG);

		in_timeout = timer_list;

		// In some cases, resuming from a suspend can cause the system
		// clock to become temporarily skewed, causing crazy things to 
		// happen with our timers (particularly for sending updates to
		// the collector). So, to correct for such skews, we routinely
		// check to make sure that 'now' is not in the future.

		timer_check_cntr++; 

			// since time() is somewhat expensive, we 
			// only check every 10 times we loop 
			
		if ( timer_check_cntr > 10 ) {

			timer_check_cntr = 0;

			time(&time_sample);
			if (now > time_sample) {
				dprintf(D_ALWAYS, "DaemonCore: Clock skew detected "
					"(time=%ld; now=%ld). Resetting TimerManager's "
					"notion of 'now'\n", (long) time_sample, 
					(long) now);
				now = time_sample;
			}
		}

		// Update curr_dataptr for GetDataPtr()
		curr_dataptr = &(in_timeout->data_ptr);

		// Initialize our flag so we know if ResetTimer was called.
		did_reset = false;
		did_cancel = false;

		// Log a message before calling handler, but only if
		// D_FULLDEBUG is also enabled.
		if (IsDebugVerbose(D_COMMAND)) {
			dprintf(D_COMMAND, "Calling Timer handler %d (%s)\n",
					in_timeout->id, in_timeout->event_descrip);
		}

		if( in_timeout->timeslice ) {
			in_timeout->timeslice->setStartTimeNow();
		}

		// Now we call the registered handler.  If we were told that the handler
		// is a c++ method, we call the handler from the c++ object referenced 
		// by service*.  If we were told the handler is a c function, we call
		// it and pass the service* as a parameter.
		if ( in_timeout->handlercpp ) {
			// typedef int (*TimerHandlercpp)()
			((in_timeout->service)->*(in_timeout->handlercpp))();
		} else {
			// typedef int (*TimerHandler)()
			(*(in_timeout->handler))();
		}

		if( in_timeout->timeslice ) {
			in_timeout->timeslice->setFinishTimeNow();
		}

		if (IsDebugVerbose(D_COMMAND)) {
			if( in_timeout->timeslice ) {
				dprintf(D_COMMAND, "Return from Timer handler %d (%s) - took %.3fs\n",
						in_timeout->id, in_timeout->event_descrip,
						in_timeout->timeslice->getLastDuration() );
			}
			else {
				dprintf(D_COMMAND, "Return from Timer handler %d (%s)\n",
						in_timeout->id, in_timeout->event_descrip);
			}
		}

		if (pruntime) {           
			*pruntime = daemonCore->dc_stats.AddRuntime(in_timeout->event_descrip, *pruntime);
		}

        // Make sure we didn't leak our priv state
		daemonCore->CheckPrivState();

		// Clear curr_dataptr
		curr_dataptr = NULL;

		if ( did_cancel ) {
			// Timer was canceled inside its handler. All we need to do
			// is delete it.
			DeleteTimer( in_timeout );
		} else if ( !did_reset ) {
			// here we remove the timer we just serviced, or renew it if it is 
			// periodic.

			// If a new timer was added at a time in the past
			// (possible when resetting a timeslice timer), then
			// it may have landed before the timer we just processed,
			// meaning that we cannot assume prev==NULL in the call
			// to RemoveTimer() below.

			Timer *prev = NULL;
			ASSERT( GetTimer(in_timeout->id,&prev) == in_timeout );
			RemoveTimer( in_timeout, prev );

			if ( in_timeout->period > 0 || in_timeout->timeslice ) {
				in_timeout->period_started = time(NULL);
				in_timeout->when = in_timeout->period_started;
				if ( in_timeout->timeslice ) {
					in_timeout->when += in_timeout->timeslice->getTimeToNextRun();
				} else {
					if( in_timeout->period == TIMER_NEVER ) {
						in_timeout->when = TIME_T_NEVER;
					} else {
						in_timeout->when += in_timeout->period;
					}
				}
				InsertTimer( in_timeout );
			} else {
				// timer is not perodic; it is just a one-time event.  we just called
				// the handler, so now just delete it. 
				DeleteTimer( in_timeout );
			}
		}
	}  // end of while loop


	// set result to number of seconds until next event.  get an update on the
	// time from time() in case the handlers we called above took significant time.
	if ( timer_list == NULL ) {
		// we set result to be -1 so that we do not busy poll.
		// a -1 return value will tell the DaemonCore:Driver to use select with
		// no timeout.
		result = -1;
	} else {
		result = (timer_list->when) - time(NULL);
		if (result < 0)
			result = 0;
	}

	dprintf( D_DAEMONCORE, "DaemonCore Timeout() Complete, returning %d \n",result);
    if (pNumFired) *pNumFired = num_fires;
	in_timeout = NULL;
	return(result);
}
Пример #5
0
int TimerManager::ResetTimer(int id, unsigned when, unsigned period,
							 bool recompute_when,
							 Timeslice const *new_timeslice)
{
	Timer*			timer_ptr;
	Timer*			trail_ptr;

	dprintf( D_DAEMONCORE,
			 "In reset_timer(), id=%d, time=%d, period=%d\n",id,when,period);
	if (timer_list == NULL) {
		dprintf( D_DAEMONCORE, "Reseting Timer from empty list!\n");
		return -1;
	}

	timer_ptr = timer_list;
	trail_ptr = NULL;
	while ( timer_ptr && timer_ptr->id != id ) {
		trail_ptr = timer_ptr;
		timer_ptr = timer_ptr->next;
	}

	if ( timer_ptr == NULL ) {
		dprintf( D_ALWAYS, "Timer %d not found\n",id );
		return -1;
	}
	if ( new_timeslice ) {
		if( timer_ptr->timeslice == NULL ) {
			timer_ptr->timeslice = new Timeslice( *new_timeslice );
		}
		else {
			*timer_ptr->timeslice = *new_timeslice;
		}

		timer_ptr->when = timer_ptr->timeslice->getNextStartTime();
	}
	else if ( timer_ptr->timeslice ) {
		dprintf( D_DAEMONCORE, "Timer %d with timeslice can't be reset\n",
				 id );
		return 0;
	} else if( recompute_when ) {
		time_t old_when = timer_ptr->when;

		timer_ptr->when = timer_ptr->period_started + period;

			// sanity check
		int wait_time = (int)timer_ptr->when - (int)time(NULL);
		if( wait_time > (int64_t)period ) {
			dprintf(D_ALWAYS,
					"ResetTimer() tried to set next call to %d (%s) %ds into"
					" the future, which is larger than the new period %d.\n",
					id,
					timer_ptr->event_descrip ? timer_ptr->event_descrip : "",
					wait_time,
					period);

				// start a new period now to restore sanity
			timer_ptr->period_started = time(NULL);
			timer_ptr->when = timer_ptr->period_started + period;
		}

		dprintf(D_FULLDEBUG,
				"Changing period of timer %d (%s) from %u to %u "
				"(added %ds to time of next scheduled call)\n",
				id, 
				timer_ptr->event_descrip ? timer_ptr->event_descrip : "",
				timer_ptr->period,
				period,
				(int)timer_ptr->when - (int)old_when);
	} else {
		timer_ptr->period_started = time(NULL);
		if ( when == TIMER_NEVER ) {
			timer_ptr->when = TIME_T_NEVER;
		} else {
			timer_ptr->when = when + timer_ptr->period_started;
		}
	}
	timer_ptr->period = period;

	RemoveTimer( timer_ptr, trail_ptr );
	InsertTimer( timer_ptr );

	if ( in_timeout == timer_ptr ) {
		// We're inside the handler for this timer. Let Timeout() know
		// the timer has already been reset for its next call.
		did_reset = true;
	}

	return 0;
}
Пример #6
0
// Add a new event in the timer list. if period is 0, this event is a one time
// event instead of periodical
int TimerManager::NewTimer(Service* s, unsigned deltawhen,
						   TimerHandler handler, TimerHandlercpp handlercpp,
						   Release release, Releasecpp releasecpp,
						   const char *event_descrip, unsigned period, 
						   const Timeslice *timeslice)
{
	Timer*		new_timer;

	dprintf( D_DAEMONCORE, "in DaemonCore NewTimer()\n" );
	new_timer = new Timer;
	if ( new_timer == NULL ) {
		dprintf( D_ALWAYS, "DaemonCore: Unable to allocate new timer\n" );
		return -1;
	}

    if (daemonCore) {
       daemonCore->dc_stats.NewProbe("Timer", event_descrip, AS_COUNT | IS_RCT | IF_NONZERO | IF_VERBOSEPUB);
    }

    new_timer->handler = handler;
	new_timer->handlercpp = handlercpp;
	new_timer->release = release;
	new_timer->releasecpp = releasecpp;
	new_timer->period = period;
	new_timer->service = s; 

	if( timeslice ) {
		new_timer->timeslice = new Timeslice( *timeslice );
		deltawhen = new_timer->timeslice->getTimeToNextRun();
	}
	else {
		new_timer->timeslice = NULL;
	}

	new_timer->period_started = time(NULL);
	if ( TIMER_NEVER == deltawhen ) {
		new_timer->when = TIME_T_NEVER;
	} else {
		new_timer->when = deltawhen + new_timer->period_started;
	}
	new_timer->data_ptr = NULL;
	if ( event_descrip ) 
		new_timer->event_descrip = strdup(event_descrip);
	else
		new_timer->event_descrip = strdup("<NULL>");


	new_timer->id = timer_ids++;		


	InsertTimer( new_timer );

	DumpTimerList(D_DAEMONCORE | D_FULLDEBUG);

	// Update curr_regdataptr for SetDataPtr()
	curr_regdataptr = &(new_timer->data_ptr);

	dprintf(D_DAEMONCORE,"leaving DaemonCore NewTimer, id=%d\n",new_timer->id);

	return	new_timer->id;
}