#include "tout.hpp"
TPool<tout_node_t> ToutQueue::pool;
TEST(ToutQueue) {
ToutQueue q;
q.push(1, 42);
q.push(2, 42);
q.push(3, 50);
q.push(4, 100);
if (!q.pop((int)3)) return false;
if (q.pop((int)5)) return false;
if (q.pop((time_t)50) != 1) return false;
if (q.pop((time_t)50) != 2) return false;
if (q.pop((time_t)50) != -1) return false;
if (q.pop((time_t)1000) != 4) return false;
if (q.pop((time_t)100000) != -1) return false;
return true;
}
ToutQueue::ToutQueue(): head(NULL), tail(NULL) {
}
ToutQueue::~ToutQueue() {
if (head) {
log(notice, "aborting timeouts");
do {
tout_node_t* node = head;
head = head->next;
pool.push(node);
} while (head);
}
}
void ToutQueue::push(int fd, time_t now) {
tout_node_t* node = pool.pop();
assert(!fds[fd]);
fds[fd] = node;
node->fd = fd;
node->at = now;
node->next = NULL;
if (!tail) {
node->prev = NULL;
head = tail = node;
} else {
node->prev = tail;
tail->next = node;
tail = node;
}
assert(!node->prev || node->prev->at <= node->at);
assert(!node->next || node->next->at >= node->at);
}
int ToutQueue::pop(time_t tout) {
if (!head || head->at >= tout) {
return -1;
}
tout_node_t* node = head;
head = head->next;
if (head) {
head->prev = NULL;
} else {
tail = NULL;
}
int fd = node->fd;
pool.push(node);
fds[fd] = NULL;
return fd;
}
bool ToutQueue::pop(int fd) {
tout_node_t* node = fds[fd];
if (!node) return false;
if (node == tail) {
tail = node->prev;
} else {
node->next->prev = node->prev;
}
if (node == head) {
head = node->next;
} else {
node->prev->next = node->next;
}
pool.push(node);
fds[fd] = NULL;
return true;
}