I've got one guaranteed needs-fixing, which is that the TimerFd interface is incorrect - it combines both a factory for TimerFds and the TimerFd interface itself, with the result that there's nothing stopping you allocating a mir::Fd from one TimerFd implementation and using it on another.
It should be split into TimerFdProvider and TimerFd interfaces.
Secondarily, I'm pretty sure the simplification would work - here's mostly complete code:
class AlarmFactory : public Dispatchable, public time::AlarmFactory
{
public:
AlarmFactory(std::shared_ptr<time::TimerFdProvider> const& timer_source);
std::unique_ptr<time::Alarm> create_alarm(std::function<void()> const& callback) override;
std::unique_ptr<time::Alarm> create_alarm(std::unique_ptr<LockableCallback>&& callback) override;
if (state_holder == triggered)
{
// Either there are no pending calls or we're currently in the callback.
// In either case, we don't have to wait. return;
}
}
// We need to be triggered once more to remove us from the MultiplexingDispatchable. reschedule_in(0ms);
// Might be better to take shared ownership of the MultiplexingDispatchable and
// manually remove_watch() us. Would let us not have to wait for a dispatch() iteration.
if (!canary.expired())
{ std::unique_lock<decltype(state_mutex)> lock(state_mutex);
Ok.
I've got one guaranteed needs-fixing, which is that the TimerFd interface is incorrect - it combines both a factory for TimerFds and the TimerFd interface itself, with the result that there's nothing stopping you allocating a mir::Fd from one TimerFd implementation and using it on another.
It should be split into TimerFdProvider and TimerFd interfaces.
Secondarily, I'm pretty sure the simplification would work - here's mostly complete code:
class AlarmFactory : public Dispatchable, public time::AlarmFactory y(std:: shared_ ptr<time: :TimerFdProvide r> const& timer_source); :unique_ ptr<time: :Alarm> create_ alarm(std: :function< void()> const& callback) override; :unique_ ptr<time: :Alarm> create_ alarm(std: :unique_ ptr<LockableCal lback>& & callback) override;
{
public:
AlarmFactor
std:
std:
Fd watch_fd() const override; :shared_ ptr<time: :TimerFdProvide r> const timer_source; gDispatchable multiplexer;
bool dispatch(FdEvents events) override;
FdEvents relevant_events() const override;
private:
std:
Multiplexin
};
class Alarm : public mt::Alarm
std::unique_ ptr<mt: :TimerFd> && timer,
std::unique_ ptr<mir: :LockableCallba ck>&& callback,
md::Multiplexi ngDispatchable& multiplexer) :move(timer) },
callback{ callback. release( ),
[this]( auto* victim)
destroyed. notify_ all();
delete victim;
std::weak_ ptr<mir: :LockableCallba ck> weak_cb = this->callback;
std: :lock_guard< decltype( state_mutex) > lock{state_mutex};
{
public:
Alarm(
: timer{std:
{
}}
{
auto internal_callback = [this, weak_cb]()
{
if (auto cb = weak_cb.lock())
{
}
}
}
~Alarm()
std: :lock_guard< decltype( state_mutex) > lock(state_mutex);
{
{
if (state_holder == triggered)
return;
{
// Either there are no pending calls or we're currently in the callback.
// In either case, we don't have to wait.
}
}
cancel();
std::weak_ ptr<mir: :LockableCallba ck> canary = callback;
callback. reset() ;
// We need to be triggered once more to remove us from the MultiplexingDis patchable.
reschedule_ in(0ms) ;
// Might be better to take shared ownership of the MultiplexingDis patchable and
std: :unique_ lock<decltype( state_mutex) > lock(state_mutex);
// manually remove_watch() us. Would let us not have to wait for a dispatch() iteration.
if (!canary.expired())
{
}
}
bool cancel() override
std::unique_ lock<decltype( state_mutex) > lock(state_mutex);
{
if (state_holder != triggered)
state_ holder = cancelled;
timer- >cancel( );
{
}
return state_holder == cancelled;
}
State state() const override
{
// Obvious thing goes here.
}
bool reschedule_ in(std: :chrono: :milliseconds delay) override
{
// Obvious thing goes here
}
bool reschedule_ for(mt: :Timestamp timeout) override
timer- >schedule_ for(timeout) ;
{
}
private: :unique_ ptr<mt: :TimerFd> timer; :recursive_ mutex state_mutex; :Alarm: :State state_holder; :condition_ variable destroyed; :shared_ ptr<mir: :LockableCallba ck> callback;
std:
std:
mt:
std:
std:
};