Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 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_LOCKED_QUEUE_INL_ |
| 6 | #define V8_LOCKED_QUEUE_INL_ |
| 7 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 8 | #include "src/base/atomic-utils.h" |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 9 | #include "src/locked-queue.h" |
| 10 | |
| 11 | namespace v8 { |
| 12 | namespace internal { |
| 13 | |
| 14 | template <typename Record> |
| 15 | struct LockedQueue<Record>::Node : Malloced { |
| 16 | Node() : next(nullptr) {} |
| 17 | Record value; |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 18 | base::AtomicValue<Node*> next; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 19 | }; |
| 20 | |
| 21 | |
| 22 | template <typename Record> |
| 23 | inline LockedQueue<Record>::LockedQueue() { |
| 24 | head_ = new Node(); |
| 25 | CHECK(head_ != nullptr); |
| 26 | tail_ = head_; |
| 27 | } |
| 28 | |
| 29 | |
| 30 | template <typename Record> |
| 31 | inline LockedQueue<Record>::~LockedQueue() { |
| 32 | // Destroy all remaining nodes. Note that we do not destroy the actual values. |
| 33 | Node* old_node = nullptr; |
| 34 | Node* cur_node = head_; |
| 35 | while (cur_node != nullptr) { |
| 36 | old_node = cur_node; |
| 37 | cur_node = cur_node->next.Value(); |
| 38 | delete old_node; |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | |
| 43 | template <typename Record> |
| 44 | inline void LockedQueue<Record>::Enqueue(const Record& record) { |
| 45 | Node* n = new Node(); |
| 46 | CHECK(n != nullptr); |
| 47 | n->value = record; |
| 48 | { |
| 49 | base::LockGuard<base::Mutex> guard(&tail_mutex_); |
| 50 | tail_->next.SetValue(n); |
| 51 | tail_ = n; |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | |
| 56 | template <typename Record> |
| 57 | inline bool LockedQueue<Record>::Dequeue(Record* record) { |
| 58 | Node* old_head = nullptr; |
| 59 | { |
| 60 | base::LockGuard<base::Mutex> guard(&head_mutex_); |
| 61 | old_head = head_; |
| 62 | Node* const next_node = head_->next.Value(); |
| 63 | if (next_node == nullptr) return false; |
| 64 | *record = next_node->value; |
| 65 | head_ = next_node; |
| 66 | } |
| 67 | delete old_head; |
| 68 | return true; |
| 69 | } |
| 70 | |
| 71 | |
| 72 | template <typename Record> |
| 73 | inline bool LockedQueue<Record>::IsEmpty() const { |
| 74 | base::LockGuard<base::Mutex> guard(&head_mutex_); |
| 75 | return head_->next.Value() == nullptr; |
| 76 | } |
| 77 | |
| 78 | |
| 79 | template <typename Record> |
| 80 | inline bool LockedQueue<Record>::Peek(Record* record) const { |
| 81 | base::LockGuard<base::Mutex> guard(&head_mutex_); |
| 82 | Node* const next_node = head_->next.Value(); |
| 83 | if (next_node == nullptr) return false; |
| 84 | *record = next_node->value; |
| 85 | return true; |
| 86 | } |
| 87 | |
| 88 | } // namespace internal |
| 89 | } // namespace v8 |
| 90 | |
| 91 | #endif // V8_LOCKED_QUEUE_INL_ |