
#ifndef PLS_DEQUE_H
#define PLS_DEQUE_H

#include "pls/internal/base/spin_lock.h"

namespace pls {
namespace internal {
namespace data_structures {

/**
 * Turns any object into deque item when inheriting from this.
 */
class deque_item {
  friend class deque_internal;

  deque_item *prev_;
  deque_item *next_;

};

class deque_internal {
 protected:
  deque_item *head_;
  deque_item *tail_;

  base::spin_lock lock_;

  deque_item *pop_head_internal();
  deque_item *pop_tail_internal();
  void push_tail_internal(deque_item *new_item);
};

/**
 * A double linked list based deque.
 * Storage is therefore only needed for the individual items.
 *
 * @tparam Item The type of items stored in this deque
 */
template<typename Item>
class deque : deque_internal {
 public:
  explicit deque() : deque_internal{} {}

  inline Item *pop_head() {
    return static_cast<Item *>(pop_head_internal());
  }

  inline Item *pop_tail() {
    return static_cast<Item *>(pop_tail_internal());
  }

  inline void push_tail(Item *new_item) {
    push_tail_internal(new_item);
  }
};

}
}
}

#endif //PLS_DEQUE_H
