Commit e5bee55a authored by Juho Snellman's avatar Juho Snellman

Concentrate all the linked list manipulation in one method

parent 0f99a803
...@@ -19,14 +19,10 @@ class TimerWheel; ...@@ -19,14 +19,10 @@ class TimerWheel;
class TimerEventInterface { class TimerEventInterface {
public: public:
TimerEventInterface() TimerEventInterface() {
: slot_(NULL),
next_(NULL),
prev_(NULL) {
} }
void cancel(); void cancel();
void relink(TimerWheelSlot* slot);
virtual void execute() = 0; virtual void execute() = 0;
...@@ -36,10 +32,14 @@ public: ...@@ -36,10 +32,14 @@ public:
Tick scheduled_at() { return scheduled_at_; } Tick scheduled_at() { return scheduled_at_; }
void set_scheduled_at(Tick ts) { scheduled_at_ = ts; } void set_scheduled_at(Tick ts) { scheduled_at_ = ts; }
private: private:
TimerEventInterface(const TimerEventInterface& other) = delete; TimerEventInterface(const TimerEventInterface& other) = delete;
TimerEventInterface& operator=(const TimerEventInterface& other) = delete; TimerEventInterface& operator=(const TimerEventInterface& other) = delete;
friend TimerWheelSlot; friend TimerWheelSlot;
friend TimerWheel;
void relink(TimerWheelSlot* slot);
Tick scheduled_at_; Tick scheduled_at_;
// The slot this event is currently in (NULL if not currently scheduled). // The slot this event is currently in (NULL if not currently scheduled).
...@@ -47,8 +47,8 @@ private: ...@@ -47,8 +47,8 @@ private:
// The events are linked together in the slot using an internal // The events are linked together in the slot using an internal
// doubly-linked list; this iterator does double duty as the // doubly-linked list; this iterator does double duty as the
// linked list node for this event. // linked list node for this event.
TimerEventInterface* next_; TimerEventInterface* next_ = NULL;
TimerEventInterface* prev_; TimerEventInterface* prev_ = NULL;
}; };
template<typename CBType> template<typename CBType>
...@@ -96,20 +96,20 @@ public: ...@@ -96,20 +96,20 @@ public:
} }
event->next_ = NULL; event->next_ = NULL;
event->slot_ = NULL; event->slot_ = NULL;
lose_event();
return event; return event;
} }
void push_event(TimerEventInterface* event) {
event->slot_ = this;
event->next_ = events_;
if (events_) {
events_->prev_ = event;
}
events_ = event;
}
private: private:
TimerWheelSlot(const TimerWheelSlot& other) = delete; TimerWheelSlot(const TimerWheelSlot& other) = delete;
TimerWheelSlot& operator=(const TimerWheelSlot& other) = delete; TimerWheelSlot& operator=(const TimerWheelSlot& other) = delete;
friend TimerEventInterface;
void lose_event() {
}
void gain_event(TimerEventInterface *e) {
}
TimerEventInterface* events_ = NULL; TimerEventInterface* events_ = NULL;
}; };
...@@ -159,11 +159,7 @@ public: ...@@ -159,11 +159,7 @@ public:
size_t slot_index = (now_ + delta) & MASK; size_t slot_index = (now_ + delta) & MASK;
auto slot = &slots_[slot_index]; auto slot = &slots_[slot_index];
if (event->active()) { event->relink(slot);
event->relink(slot);
} else {
slot->push_event(event);
}
} }
// Return the current tick value. Note that if the timers advance by // Return the current tick value. Note that if the timers advance by
...@@ -194,38 +190,52 @@ private: ...@@ -194,38 +190,52 @@ private:
TimerWheel* down_; TimerWheel* down_;
}; };
void TimerEventInterface::cancel() { void TimerEventInterface::relink(TimerWheelSlot* new_slot) {
// It's ok to cancel a timer that's not running. if (new_slot == slot_) {
if (!slot_) {
return; return;
} }
if (this == slot_->events()) { // Unlink from old location.
slot_->pop_event(); if (slot_) {
} else {
auto prev = prev_; auto prev = prev_;
auto next = next_; auto next = next_;
if (next) {
next->prev_ = prev;
}
if (prev) { if (prev) {
prev->next_ = next; prev->next_ = next;
} else {
// Must be at head of slot. Move the next item to the head.
slot_->events_ = next;
} }
if (next) { slot_->lose_event();
next->prev_ = prev; }
// Insert in new slot.
{
if (new_slot) {
auto old = new_slot->events_;
next_ = old;
if (old) {
old->prev_ = this;
}
new_slot->events_ = this;
new_slot->gain_event(this);
} else {
next_ = NULL;
} }
prev_ = NULL; prev_ = NULL;
next_ = NULL;
} }
slot_ = NULL; slot_ = new_slot;
} }
void TimerEventInterface::relink(TimerWheelSlot* slot) { void TimerEventInterface::cancel() {
assert(slot_); // It's ok to cancel a timer that's not running.
if (slot_ == slot) { if (!slot_) {
return; return;
} }
cancel();
slot_ = slot;
slot_->push_event(this);
}
relink(NULL);
}
#endif // _TIMER_WHEEL_H #endif // _TIMER_WHEEL_H
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment