#include "tout.hpp"
#include <assert.h>


ToutQueue::ToutQueue(): head(NULL), tail(NULL) {
}


ToutQueue::~ToutQueue() {
    if (!head) return;
    LOG("timeouts still pending");
    do {
        tout_node_t* node = head;
        head = head->next;
        pool.push(node);
    } while (head);
}


bool ToutQueue::empty() const {
    return (head == NULL);
}


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 {
        assert(tail->at <= node->at);
        node->prev = tail;
        tail->next = node;
        tail = node;
    }
}


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;
}


void ToutQueue::pop(int fd) {
    tout_node_t* node = fds[fd];
    assert(node);
    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;
}