genode/repos/libports/src/lib/libc/internal/timer.h

118 lines
2.4 KiB
C++

/*
* \brief Libc-internal timer handling
* \author Norman Feske
* \date 2019-09-16
*/
/*
* Copyright (C) 2019 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _LIBC__INTERNAL__TIMER_H_
#define _LIBC__INTERNAL__TIMER_H_
/* Genode includes */
#include <timer_session/connection.h>
namespace Libc {
class Timer;
class Timer_accessor;
class Timeout;
class Timeout_handler;
}
struct Libc::Timer
{
::Timer::Connection _timer;
Timer(Genode::Env &env) : _timer(env) { }
Genode::Duration curr_time()
{
return _timer.curr_time();
}
static Microseconds microseconds(Genode::uint64_t timeout_ms)
{
return Microseconds(1000*timeout_ms);
}
static Genode::uint64_t max_timeout()
{
return ~0UL/1000;
}
};
/**
* Interface for obtaining the libc-global timer instance
*
* The 'Timer' is instantiated on demand whenever the 'Timer_accessor::timer'
* method is first called. This way, libc-using components do not depend of a
* timer connection unless they actually use time-related functionality.
*/
struct Libc::Timer_accessor
{
virtual Timer &timer() = 0;
};
struct Libc::Timeout_handler
{
virtual void handle_timeout() = 0;
};
/*
* TODO curr_time wrapping
*/
struct Libc::Timeout
{
Libc::Timer_accessor &_timer_accessor;
Timeout_handler &_handler;
::Timer::One_shot_timeout<Timeout> _timeout;
bool _expired = true;
Genode::uint64_t _absolute_timeout_ms = 0;
void _handle(Duration now)
{
_expired = true;
_absolute_timeout_ms = 0;
_handler.handle_timeout();
}
Timeout(Timer_accessor &timer_accessor, Timeout_handler &handler)
:
_timer_accessor(timer_accessor),
_handler(handler),
_timeout(_timer_accessor.timer()._timer, *this, &Timeout::_handle)
{ }
void start(Genode::uint64_t timeout_ms)
{
Milliseconds const now = _timer_accessor.timer().curr_time().trunc_to_plain_ms();
_expired = false;
_absolute_timeout_ms = now.value + timeout_ms;
_timeout.schedule(_timer_accessor.timer().microseconds(timeout_ms));
}
Genode::uint64_t duration_left() const
{
Milliseconds const now = _timer_accessor.timer().curr_time().trunc_to_plain_ms();
if (_expired || _absolute_timeout_ms < now.value)
return 0;
return _absolute_timeout_ms - now.value;
}
};
#endif /* _LIBC__INTERNAL__TIMER_H_ */