event/Loop: use boost::intrusive::multiset to store TimeoutMonitors
By using an "intrusive" data structure, we can easily eliminate struct TimerRecord.
This commit is contained in:
parent
71ed3ff992
commit
010855a294
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Loop.hxx"
|
#include "Loop.hxx"
|
||||||
#include "TimeoutMonitor.hxx"
|
|
||||||
#include "SocketMonitor.hxx"
|
#include "SocketMonitor.hxx"
|
||||||
#include "IdleMonitor.hxx"
|
#include "IdleMonitor.hxx"
|
||||||
#include "DeferredMonitor.hxx"
|
#include "DeferredMonitor.hxx"
|
||||||
@ -27,18 +26,6 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
inline std::chrono::steady_clock::time_point
|
|
||||||
EventLoop::TimerRecord::GetDue() const noexcept
|
|
||||||
{
|
|
||||||
return timer.due;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
|
||||||
EventLoop::TimerRecord::operator<(const TimerRecord &other) const noexcept
|
|
||||||
{
|
|
||||||
return timer.due < other.timer.due;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventLoop::EventLoop(ThreadId _thread)
|
EventLoop::EventLoop(ThreadId _thread)
|
||||||
:SocketMonitor(*this), thread(_thread)
|
:SocketMonitor(*this), thread(_thread)
|
||||||
{
|
{
|
||||||
@ -106,7 +93,7 @@ EventLoop::AddTimer(TimeoutMonitor &t, std::chrono::steady_clock::duration d)
|
|||||||
assert(IsInside());
|
assert(IsInside());
|
||||||
|
|
||||||
t.due = now + d;
|
t.due = now + d;
|
||||||
timers.insert(TimerRecord(t));
|
timers.insert(t);
|
||||||
again = true;
|
again = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,12 +102,7 @@ EventLoop::CancelTimer(TimeoutMonitor &t)
|
|||||||
{
|
{
|
||||||
assert(IsInside());
|
assert(IsInside());
|
||||||
|
|
||||||
for (auto i = timers.begin(), end = timers.end(); i != end; ++i) {
|
timers.erase(timers.iterator_to(t));
|
||||||
if (&i->timer == &t) {
|
|
||||||
timers.erase(i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -163,11 +145,11 @@ EventLoop::Run()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout = i->GetDue() - now;
|
TimeoutMonitor &m = *i;
|
||||||
|
timeout = m.due - now;
|
||||||
if (timeout > timeout.zero())
|
if (timeout > timeout.zero())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
TimeoutMonitor &m = i->timer;
|
|
||||||
timers.erase(i);
|
timers.erase(i);
|
||||||
|
|
||||||
m.Run();
|
m.Run();
|
||||||
|
@ -28,6 +28,9 @@
|
|||||||
#include "thread/Mutex.hxx"
|
#include "thread/Mutex.hxx"
|
||||||
#include "WakeFD.hxx"
|
#include "WakeFD.hxx"
|
||||||
#include "SocketMonitor.hxx"
|
#include "SocketMonitor.hxx"
|
||||||
|
#include "TimeoutMonitor.hxx"
|
||||||
|
|
||||||
|
#include <boost/intrusive/set.hpp>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <list>
|
#include <list>
|
||||||
@ -50,22 +53,23 @@ class DeferredMonitor;
|
|||||||
*/
|
*/
|
||||||
class EventLoop final : SocketMonitor
|
class EventLoop final : SocketMonitor
|
||||||
{
|
{
|
||||||
struct TimerRecord {
|
|
||||||
TimeoutMonitor &timer;
|
|
||||||
|
|
||||||
explicit constexpr TimerRecord(TimeoutMonitor &_timer)
|
|
||||||
:timer(_timer) {}
|
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
std::chrono::steady_clock::time_point GetDue() const noexcept;
|
|
||||||
|
|
||||||
gcc_pure
|
|
||||||
bool operator<(const TimerRecord &other) const noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
WakeFD wake_fd;
|
WakeFD wake_fd;
|
||||||
|
|
||||||
std::multiset<TimerRecord> timers;
|
struct TimerCompare {
|
||||||
|
constexpr bool operator()(const TimeoutMonitor &a,
|
||||||
|
const TimeoutMonitor &b) const {
|
||||||
|
return a.due < b.due;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef boost::intrusive::multiset<TimeoutMonitor,
|
||||||
|
boost::intrusive::member_hook<TimeoutMonitor,
|
||||||
|
TimeoutMonitor::TimerSetHook,
|
||||||
|
&TimeoutMonitor::timer_set_hook>,
|
||||||
|
boost::intrusive::compare<TimerCompare>,
|
||||||
|
boost::intrusive::constant_time_size<false>> TimerSet;
|
||||||
|
TimerSet timers;
|
||||||
|
|
||||||
std::list<IdleMonitor *> idle;
|
std::list<IdleMonitor *> idle;
|
||||||
|
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
|
@ -24,10 +24,8 @@
|
|||||||
void
|
void
|
||||||
TimeoutMonitor::Cancel()
|
TimeoutMonitor::Cancel()
|
||||||
{
|
{
|
||||||
if (IsActive()) {
|
if (IsActive())
|
||||||
active = false;
|
|
||||||
loop.CancelTimer(*this);
|
loop.CancelTimer(*this);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -35,13 +33,5 @@ TimeoutMonitor::Schedule(std::chrono::steady_clock::duration d)
|
|||||||
{
|
{
|
||||||
Cancel();
|
Cancel();
|
||||||
|
|
||||||
active = true;
|
|
||||||
loop.AddTimer(*this, d);
|
loop.AddTimer(*this, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
TimeoutMonitor::Run()
|
|
||||||
{
|
|
||||||
active = false;
|
|
||||||
OnTimeout();
|
|
||||||
}
|
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
|
||||||
|
#include <boost/intrusive/set_hook.hpp>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
class EventLoop;
|
class EventLoop;
|
||||||
@ -37,6 +39,9 @@ class EventLoop;
|
|||||||
class TimeoutMonitor {
|
class TimeoutMonitor {
|
||||||
friend class EventLoop;
|
friend class EventLoop;
|
||||||
|
|
||||||
|
typedef boost::intrusive::set_member_hook<> TimerSetHook;
|
||||||
|
TimerSetHook timer_set_hook;
|
||||||
|
|
||||||
EventLoop &loop;
|
EventLoop &loop;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,11 +50,9 @@ class TimeoutMonitor {
|
|||||||
*/
|
*/
|
||||||
std::chrono::steady_clock::time_point due;
|
std::chrono::steady_clock::time_point due;
|
||||||
|
|
||||||
bool active;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TimeoutMonitor(EventLoop &_loop)
|
TimeoutMonitor(EventLoop &_loop)
|
||||||
:loop(_loop), active(false) {
|
:loop(_loop) {
|
||||||
}
|
}
|
||||||
|
|
||||||
~TimeoutMonitor() {
|
~TimeoutMonitor() {
|
||||||
@ -61,7 +64,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IsActive() const {
|
bool IsActive() const {
|
||||||
return active;
|
return timer_set_hook.is_linked();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Schedule(std::chrono::steady_clock::duration d);
|
void Schedule(std::chrono::steady_clock::duration d);
|
||||||
@ -71,7 +74,9 @@ protected:
|
|||||||
virtual void OnTimeout() = 0;
|
virtual void OnTimeout() = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Run();
|
void Run() {
|
||||||
|
OnTimeout();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* MAIN_NOTIFY_H */
|
#endif /* MAIN_NOTIFY_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user