예제 #1
0
파일: timer.cpp 프로젝트: CSRedRat/icinga2
/**
 * Reschedules this timer.
 *
 * @param next The time when this timer should be called again. Use -1 to let
 * 	       the timer figure out a suitable time based on the interval.
 */
void Timer::Reschedule(double next)
{
	ASSERT(!OwnsLock());

	boost::mutex::scoped_lock lock(l_Mutex);

	if (next < 0) {
		/* Don't schedule the next call if this is not a periodic timer. */
		if (m_Interval <= 0)
			return;

		next = Utility::GetTime() + m_Interval;
	}

	m_Next = next;

	if (m_Started) {
		/* Remove and re-add the timer to update the index. */
		l_Timers.erase(GetSelf());
		l_Timers.insert(GetSelf());

		/* Notify the worker that we've rescheduled a timer. */
		l_CV.notify_all();
	}
}
예제 #2
0
/**
 * Reschedules this timer.
 *
 * @param completed Whether the timer has just completed its callback.
 * @param next The time when this timer should be called again. Use -1 to let
 * 	       the timer figure out a suitable time based on the interval.
 */
void Timer::InternalReschedule(bool completed, double next)
{
	ASSERT(!OwnsLock());

	boost::mutex::scoped_lock lock(l_TimerMutex);

	if (completed)
		m_Running = false;

	if (next < 0) {
		/* Don't schedule the next call if this is not a periodic timer. */
		if (m_Interval <= 0)
			return;

		next = Utility::GetTime() + m_Interval;
	}

	m_Next = next;

	if (m_Started && !m_Running) {
		/* Remove and re-add the timer to update the index. */
		l_Timers.erase(this);
		l_Timers.insert(this);

		/* Notify the worker that we've rescheduled a timer. */
		l_TimerCV.notify_all();
	}
}
예제 #3
0
파일: timer.cpp 프로젝트: CSRedRat/icinga2
/**
 * Unregisters the timer and stops processing events for it.
 */
void Timer::Stop(void)
{
	ASSERT(!OwnsLock());

	boost::mutex::scoped_lock lock(l_Mutex);

	m_Started = false;
	l_Timers.erase(GetSelf());

	/* Notify the worker thread that we've disabled a timer. */
	l_CV.notify_all();
}
예제 #4
0
/**
 * Adjusts all timers by adding the specified amount of time to their
 * next scheduled timestamp.
 *
 * @param adjustment The adjustment.
 */
void Timer::AdjustTimers(double adjustment)
{
	boost::mutex::scoped_lock lock(l_TimerMutex);

	double now = Utility::GetTime();

	typedef boost::multi_index::nth_index<TimerSet, 1>::type TimerView;
	TimerView& idx = boost::get<1>(l_Timers);

	std::vector<Timer *> timers;

	BOOST_FOREACH(Timer *timer, idx) {
		if (std::fabs(now - (timer->m_Next + adjustment)) <
		    std::fabs(now - timer->m_Next)) {
			timer->m_Next += adjustment;
			timers.push_back(timer);
		}
	}

	BOOST_FOREACH(Timer *timer, timers) {
		l_Timers.erase(timer);
		l_Timers.insert(timer);
	}
예제 #5
0
파일: timer.cpp 프로젝트: CSRedRat/icinga2
/**
 * Adjusts all timers by adding the specified amount of time to their
 * next scheduled timestamp.
 *
 * @param adjustment The adjustment.
 */
void Timer::AdjustTimers(double adjustment)
{
	boost::mutex::scoped_lock lock(l_Mutex);

	double now = Utility::GetTime();

	typedef boost::multi_index::nth_index<TimerSet, 1>::type TimerView;
	TimerView& idx = boost::get<1>(l_Timers);

	TimerView::iterator it;
	for (it = idx.begin(); it != idx.end(); it++) {
		Timer::Ptr timer = it->lock();

		if (abs(now - (timer->m_Next + adjustment)) <
		    abs(now - timer->m_Next)) {
			timer->m_Next += adjustment;
			l_Timers.erase(timer);
			l_Timers.insert(timer);
		}
	}

	/* Notify the worker that we've rescheduled some timers. */
	l_CV.notify_all();
}
예제 #6
0
파일: timer.cpp 프로젝트: CSRedRat/icinga2
/**
 * Worker thread proc for Timer objects.
 */
void Timer::TimerThreadProc(void)
{
	Utility::SetThreadName("Timer Thread");

	for (;;) {
		boost::mutex::scoped_lock lock(l_Mutex);

		typedef boost::multi_index::nth_index<TimerSet, 1>::type NextTimerView;
		NextTimerView& idx = boost::get<1>(l_Timers);

		/* Wait until there is at least one timer. */
		while (idx.empty() && !l_StopThread)
			l_CV.wait(lock);

		if (l_StopThread)
			break;

		NextTimerView::iterator it = idx.begin();
		Timer::Ptr timer = it->lock();

		if (!timer) {
			/* Remove the timer from the list if it's not alive anymore. */
			idx.erase(it);
			continue;
		}

		double wait = timer->m_Next - Utility::GetTime();

		if (wait > 0) {
			/* Make sure the timer we just examined can be destroyed while we're waiting. */
			timer.reset();

			/* Wait for the next timer. */
			l_CV.timed_wait(lock, boost::posix_time::milliseconds(wait * 1000));

			continue;
		}

		/* Remove the timer from the list so it doesn't get called again
		 * until the current call is completed. */
		l_Timers.erase(timer);

		lock.unlock();

		/* Asynchronously call the timer. */
		Utility::QueueAsyncCallback(boost::bind(&Timer::Call, timer));
	}
}
예제 #7
0
/**
 * Unregisters the timer and stops processing events for it.
 */
void Timer::Stop(bool wait)
{
	ASSERT(!OwnsLock());

	if (l_StopTimerThread)
		return;

	boost::mutex::scoped_lock lock(l_TimerMutex);

	m_Started = false;
	l_Timers.erase(this);

	/* Notify the worker thread that we've disabled a timer. */
	l_TimerCV.notify_all();

	while (wait && m_Running)
		l_TimerCV.wait(lock);
}