#include <mutex>

#include "pls/internal/data_structures/deque.h"

namespace pls {
namespace internal {
namespace data_structures {

deque_item *deque_internal::pop_head_internal() {
  std::lock_guard<base::spin_lock> lock{lock_};

  if (head_ == nullptr) {
    return nullptr;
  }

  deque_item *result = head_;
  head_ = head_->next_;
  if (head_ == nullptr) {
    tail_ = nullptr;
  } else {
    head_->prev_ = nullptr;
  }

  return result;
}

deque_item *deque_internal::pop_tail_internal() {
  std::lock_guard<base::spin_lock> lock{lock_};

  if (tail_ == nullptr) {
    return nullptr;
  }

  deque_item *result = tail_;
  tail_ = tail_->prev_;
  if (tail_ == nullptr) {
    head_ = nullptr;
  } else {
    tail_->next_ = nullptr;
  }

  return result;
}

void deque_internal::push_tail_internal(deque_item *new_item) {
  std::lock_guard<base::spin_lock> lock{lock_};

  if (tail_ != nullptr) {
    tail_->next_ = new_item;
  } else {
    head_ = new_item;
  }
  new_item->prev_ = tail_;
  new_item->next_ = nullptr;
  tail_ = new_item;
}

}
}
}
