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 * 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:
/** using Microseconds = Time_source::Microseconds;
* Read out the now time of the scheduler
*/
virtual Microseconds curr_time() const = 0;
/** private:
* 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;
/** friend Timeout;
* 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 * Add a one-shot timeout to the schedule
* *
* \param timeout corresponding timeout callback object * \param timeout timeout callback object
*/ * \param duration timeout trigger delay
virtual void discard(Timeout &timeout) = 0; */
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) Timeout(Timeout_scheduler &timeout_scheduler)
: _alarm(timeout_scheduler) { } : _alarm(timeout_scheduler) { }
~Timeout() { _alarm.timeout_scheduler.discard(*this); } ~Timeout() { discard(); }
void schedule_periodic(Microseconds duration, Handler &handler); void schedule_periodic(Microseconds duration, Handler &handler);
void schedule_one_shot(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; 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: public:
Alarm_timeout_scheduler(Time_source &time_source); Alarm_timeout_scheduler(Time_source &time_source);
@ -246,14 +271,8 @@ class Genode::Alarm_timeout_scheduler : private Noncopyable,
** Timeout_scheduler ** ** Timeout_scheduler **
***********************/ ***********************/
void schedule_one_shot(Timeout &timeout, Microseconds duration) override;
void schedule_periodic(Timeout &timeout, Microseconds duration) override;
Microseconds curr_time() const override { Microseconds curr_time() const override {
return _time_source.curr_time(); } return _time_source.curr_time(); }
void discard(Timeout &timeout) override {
_alarm_scheduler.discard(&timeout._alarm); }
}; };
#endif /* _OS__TIMEOUT_H_ */ #endif /* _OS__TIMEOUT_H_ */

View File

@ -19,89 +19,82 @@
#include <os/time_source.h> #include <os/time_source.h>
#include <os/timeout.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: 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: if (_handler)
_handler->handle_timeout(curr_time());
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 };
public: public:
Timer(::Timer::Session &session, Entrypoint &ep) Timer_time_source(::Timer::Session &session, Entrypoint &ep)
: _time_source(session, 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 { Timer(::Timer::Session &session, Entrypoint &ep)
_timeout_scheduler.schedule_periodic(timeout, duration); } :
Timer_time_source(session, ep),
void schedule_one_shot(Timeout &timeout, Microseconds duration) override { Alarm_timeout_scheduler(*(Time_source*)this)
_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); }
}; };
#endif /* _TIMER_H_ */ #endif /* _TIMER_H_ */

View File

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

View File

@ -25,14 +25,20 @@ void Timeout::schedule_periodic(Microseconds duration, Handler &handler)
{ {
_alarm.handler = &handler; _alarm.handler = &handler;
_alarm.periodic = true; _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) void Timeout::schedule_one_shot(Microseconds duration, Handler &handler)
{ {
_alarm.handler = &handler; _alarm.handler = &handler;
_alarm.periodic = false; _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, void Alarm_timeout_scheduler::_schedule_one_shot(Timeout &timeout,
Microseconds duration) Microseconds duration)
{ {
_alarm_scheduler.schedule_absolute(&timeout._alarm, _alarm_scheduler.schedule_absolute(&timeout._alarm,
_time_source.curr_time().value + _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, void Alarm_timeout_scheduler::_schedule_periodic(Timeout &timeout,
Microseconds duration) Microseconds duration)
{ {
_alarm_scheduler.handle(_time_source.curr_time().value); _alarm_scheduler.handle(_time_source.curr_time().value);
_alarm_scheduler.schedule(&timeout._alarm, duration.value); _alarm_scheduler.schedule(&timeout._alarm, duration.value);