1// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_UTILS_LOCKED_QUEUE_INL_H_
6#define V8_UTILS_LOCKED_QUEUE_INL_H_
7
8#include "src/base/atomic-utils.h"
9#include "src/utils/locked-queue.h"
10
11namespace v8 {
12namespace internal {
13
14template <typename Record>
15struct LockedQueue<Record>::Node : Malloced {
16  Node() : next(nullptr) {}
17  Record value;
18  base::AtomicValue<Node*> next;
19};
20
21template <typename Record>
22inline LockedQueue<Record>::LockedQueue() {
23  head_ = new Node();
24  CHECK_NOT_NULL(head_);
25  tail_ = head_;
26  size_ = 0;
27}
28
29template <typename Record>
30inline LockedQueue<Record>::~LockedQueue() {
31  // Destroy all remaining nodes. Note that we do not destroy the actual values.
32  Node* old_node = nullptr;
33  Node* cur_node = head_;
34  while (cur_node != nullptr) {
35    old_node = cur_node;
36    cur_node = cur_node->next.Value();
37    delete old_node;
38  }
39}
40
41template <typename Record>
42inline void LockedQueue<Record>::Enqueue(Record record) {
43  Node* n = new Node();
44  CHECK_NOT_NULL(n);
45  n->value = std::move(record);
46  {
47    base::MutexGuard guard(&tail_mutex_);
48    size_++;
49    tail_->next.SetValue(n);
50    tail_ = n;
51  }
52}
53
54template <typename Record>
55inline bool LockedQueue<Record>::Dequeue(Record* record) {
56  Node* old_head = nullptr;
57  {
58    base::MutexGuard guard(&head_mutex_);
59    old_head = head_;
60    Node* const next_node = head_->next.Value();
61    if (next_node == nullptr) return false;
62    *record = std::move(next_node->value);
63    head_ = next_node;
64    size_t old_size = size_.fetch_sub(1);
65    USE(old_size);
66    DCHECK_GT(old_size, 0);
67  }
68  delete old_head;
69  return true;
70}
71
72template <typename Record>
73inline bool LockedQueue<Record>::IsEmpty() const {
74  base::MutexGuard guard(&head_mutex_);
75  return head_->next.Value() == nullptr;
76}
77
78template <typename Record>
79inline bool LockedQueue<Record>::Peek(Record* record) const {
80  base::MutexGuard guard(&head_mutex_);
81  Node* const next_node = head_->next.Value();
82  if (next_node == nullptr) return false;
83  *record = next_node->value;
84  return true;
85}
86
87template <typename Record>
88inline size_t LockedQueue<Record>::size() const {
89  return size_;
90}
91
92}  // namespace internal
93}  // namespace v8
94
95#endif  // V8_UTILS_LOCKED_QUEUE_INL_H_
96