Hide implementation details in timeout framework

Fixes #2205
This commit is contained in:
Christian Helmuth 2016-12-20 17:01:23 +01:00 committed by Norman Feske
parent a2a51985f2
commit f2568856dd
4 changed files with 127 additions and 109 deletions

View File

@ -31,38 +31,50 @@ namespace Genode {
/**
* Interface of a time-source multiplexer
*
* Beside 'curr_time()', this abstract interface is used by the Timeout
* implementation only. Users of the timeout framework must schedule and
* discard timeouts via methods of the timeout.
*/
struct Genode::Timeout_scheduler
class Genode::Timeout_scheduler
{
using Microseconds = Time_source::Microseconds;
public:
/**
* Read out the now time of the scheduler
*/
virtual Microseconds curr_time() const = 0;
using Microseconds = Time_source::Microseconds;
/**
* Add a one-shot timeout to the schedule
*
* \param timeout timeout callback object
* \param duration timeout trigger delay
*/
virtual void schedule_one_shot(Timeout &timeout, Microseconds duration) = 0;
private:
/**
* Add a periodic timeout to the schedule
*
* \param timeout timeout callback object
* \param duration timeout trigger period
*/
virtual void schedule_periodic(Timeout &timeout, Microseconds duration) = 0;
friend Timeout;
/**
* Remove timeout from the scheduler
*
* \param timeout corresponding timeout callback object
*/
virtual void discard(Timeout &timeout) = 0;
/**
* Add a one-shot timeout to the schedule
*
* \param timeout timeout callback object
* \param duration timeout trigger delay
*/
virtual void _schedule_one_shot(Timeout &timeout, Microseconds duration) = 0;
/**
* Add a periodic timeout to the schedule
*
* \param timeout timeout callback object
* \param duration timeout trigger period
*/
virtual void _schedule_periodic(Timeout &timeout, Microseconds duration) = 0;
/**
* Remove timeout from the scheduler
*
* \param timeout corresponding timeout callback object
*/
virtual void _discard(Timeout &timeout) = 0;
public:
/**
* Read out the now time of the scheduler
*/
virtual Microseconds curr_time() const = 0;
};
@ -118,11 +130,13 @@ class Genode::Timeout : private Noncopyable
Timeout(Timeout_scheduler &timeout_scheduler)
: _alarm(timeout_scheduler) { }
~Timeout() { _alarm.timeout_scheduler.discard(*this); }
~Timeout() { discard(); }
void schedule_periodic(Microseconds duration, Handler &handler);
void schedule_one_shot(Microseconds duration, Handler &handler);
void discard();
};
@ -237,6 +251,17 @@ class Genode::Alarm_timeout_scheduler : private Noncopyable,
void handle_timeout(Microseconds curr_time) override;
/***********************
** Timeout_scheduler **
***********************/
void _schedule_one_shot(Timeout &timeout, Microseconds duration) override;
void _schedule_periodic(Timeout &timeout, Microseconds duration) override;
void _discard(Timeout &timeout) override {
_alarm_scheduler.discard(&timeout._alarm); }
public:
Alarm_timeout_scheduler(Time_source &time_source);
@ -246,14 +271,8 @@ class Genode::Alarm_timeout_scheduler : private Noncopyable,
** Timeout_scheduler **
***********************/
void schedule_one_shot(Timeout &timeout, Microseconds duration) override;
void schedule_periodic(Timeout &timeout, Microseconds duration) override;
Microseconds curr_time() const override {
return _time_source.curr_time(); }
void discard(Timeout &timeout) override {
_alarm_scheduler.discard(&timeout._alarm); }
};
#endif /* _OS__TIMEOUT_H_ */

View File

@ -19,89 +19,82 @@
#include <os/time_source.h>
#include <os/timeout.h>
namespace Genode { class Timer; }
namespace Genode {
class Timer;
class Timer_time_source;
}
/**
* Multiplexes a timer session amongst different timeouts
* Implementation helper for 'Timer'
*
* \noapi
*/
class Genode::Timer : public Timeout_scheduler
class Genode::Timer_time_source : public Genode::Time_source
{
private:
class Time_source : public Genode::Time_source
enum { MIN_TIMEOUT_US = 100000 };
using Signal_handler = Genode::Signal_handler<Timer_time_source>;
::Timer::Session &_session;
Signal_handler _signal_handler;
Timeout_handler *_handler = nullptr;
void _handle_timeout()
{
private:
enum { MIN_TIMEOUT_US = 100000 };
using Signal_handler =
Genode::Signal_handler<Time_source>;
::Timer::Session &_session;
Signal_handler _signal_handler;
Timeout_handler *_handler = nullptr;
void _handle_timeout()
{
if (_handler) {
_handler->handle_timeout(curr_time()); }
}
public:
Time_source(::Timer::Session &session, Entrypoint &ep)
:
_session(session),
_signal_handler(ep, *this, &Time_source::_handle_timeout)
{
_session.sigh(_signal_handler);
}
Microseconds curr_time() const {
return Microseconds(1000ULL * _session.elapsed_ms()); }
void schedule_timeout(Microseconds duration,
Timeout_handler &handler)
{
if (duration.value < MIN_TIMEOUT_US) {
duration.value = MIN_TIMEOUT_US; }
if (duration.value > max_timeout().value) {
duration.value = max_timeout().value; }
_handler = &handler;
_session.trigger_once(duration.value);
}
Microseconds max_timeout() const {
return Microseconds(~0UL); }
} _time_source;
Alarm_timeout_scheduler _timeout_scheduler { _time_source };
if (_handler)
_handler->handle_timeout(curr_time());
}
public:
Timer(::Timer::Session &session, Entrypoint &ep)
: _time_source(session, ep) { }
Timer_time_source(::Timer::Session &session, Entrypoint &ep)
:
_session(session),
_signal_handler(ep, *this, &Timer_time_source::_handle_timeout)
{
_session.sigh(_signal_handler);
}
Microseconds curr_time() const {
return Microseconds(1000ULL * _session.elapsed_ms()); }
void schedule_timeout(Microseconds duration,
Timeout_handler &handler)
{
if (duration.value < MIN_TIMEOUT_US)
duration.value = MIN_TIMEOUT_US;
if (duration.value > max_timeout().value)
duration.value = max_timeout().value;
_handler = &handler;
_session.trigger_once(duration.value);
}
Microseconds max_timeout() const {
return Microseconds(~0UL); }
};
/***********************
** Timeout_scheduler **
***********************/
/**
* Timer-session based timeout scheduler
*
* Multiplexes a timer session amongst different timeouts.
*/
struct Genode::Timer : private Genode::Timer_time_source,
public Genode::Alarm_timeout_scheduler
{
using Time_source::Microseconds;
void schedule_periodic(Timeout &timeout, Microseconds duration) override {
_timeout_scheduler.schedule_periodic(timeout, duration); }
void schedule_one_shot(Timeout &timeout, Microseconds duration) override {
_timeout_scheduler.schedule_one_shot(timeout, duration); }
Microseconds curr_time() const override {
return _timeout_scheduler.curr_time(); }
void discard(Timeout &timeout) override {
_timeout_scheduler.discard(timeout); }
Timer(::Timer::Session &session, Entrypoint &ep)
:
Timer_time_source(session, ep),
Alarm_timeout_scheduler(*(Time_source*)this)
{ }
};
#endif /* _TIMER_H_ */

View File

@ -61,7 +61,7 @@ class Timer::Session_component : public Genode::Rpc_object<Session>,
{
_sigh = sigh;
if (!sigh.valid())
_timeout_scheduler.discard(_timeout);
_timeout.discard();
}
unsigned long elapsed_ms() const override {

View File

@ -25,14 +25,20 @@ void Timeout::schedule_periodic(Microseconds duration, Handler &handler)
{
_alarm.handler = &handler;
_alarm.periodic = true;
_alarm.timeout_scheduler.schedule_periodic(*this, duration);
_alarm.timeout_scheduler._schedule_periodic(*this, duration);
}
void Timeout::schedule_one_shot(Microseconds duration, Handler &handler)
{
_alarm.handler = &handler;
_alarm.periodic = false;
_alarm.timeout_scheduler.schedule_one_shot(*this, duration);
_alarm.timeout_scheduler._schedule_one_shot(*this, duration);
}
void Timeout::discard()
{
_alarm.timeout_scheduler._discard(*this);
_alarm.handler = nullptr;
}
@ -82,8 +88,8 @@ Alarm_timeout_scheduler::Alarm_timeout_scheduler(Time_source &time_source)
}
void Alarm_timeout_scheduler::schedule_one_shot(Timeout &timeout,
Microseconds duration)
void Alarm_timeout_scheduler::_schedule_one_shot(Timeout &timeout,
Microseconds duration)
{
_alarm_scheduler.schedule_absolute(&timeout._alarm,
_time_source.curr_time().value +
@ -94,8 +100,8 @@ void Alarm_timeout_scheduler::schedule_one_shot(Timeout &timeout,
}
void Alarm_timeout_scheduler::schedule_periodic(Timeout &timeout,
Microseconds duration)
void Alarm_timeout_scheduler::_schedule_periodic(Timeout &timeout,
Microseconds duration)
{
_alarm_scheduler.handle(_time_source.curr_time().value);
_alarm_scheduler.schedule(&timeout._alarm, duration.value);