1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BREAKOUT_BOX_FRAME_QUEUE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BREAKOUT_BOX_FRAME_QUEUE_H_
#include <optional>
#include "base/synchronization/lock.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
namespace blink {
// Implements a thread-safe circular queue.
template <typename NativeFrameType>
class FrameQueue
: public WTF::ThreadSafeRefCounted<FrameQueue<NativeFrameType>> {
public:
explicit FrameQueue(wtf_size_t max_size)
: max_size_(std::max(1u, max_size)) {}
base::Lock& GetLock() { return lock_; }
std::optional<NativeFrameType> Push(NativeFrameType frame) {
base::AutoLock locker_(GetLock());
return PushLocked(std::move(frame));
}
std::optional<NativeFrameType> PushLocked(NativeFrameType frame)
EXCLUSIVE_LOCKS_REQUIRED(GetLock()) {
std::optional<NativeFrameType> ret;
if (queue_.size() == max_size_)
ret = queue_.TakeFirst();
queue_.push_back(std::move(frame));
return ret;
}
std::optional<NativeFrameType> Pop() {
base::AutoLock locker_(GetLock());
return PopLocked();
}
std::optional<NativeFrameType> PopLocked()
EXCLUSIVE_LOCKS_REQUIRED(GetLock()) {
if (queue_.empty())
return std::nullopt;
return queue_.TakeFirst();
}
std::optional<NativeFrameType> PeekLocked()
EXCLUSIVE_LOCKS_REQUIRED(GetLock()) {
if (queue_.empty())
return std::nullopt;
return queue_.front();
}
bool IsEmpty() {
base::AutoLock locker_(GetLock());
return IsEmptyLocked();
}
bool IsEmptyLocked() EXCLUSIVE_LOCKS_REQUIRED(GetLock()) {
return queue_.empty();
}
wtf_size_t MaxSize() const { return max_size_; }
void Clear() {
base::AutoLock locker_(GetLock());
queue_.clear();
}
private:
base::Lock lock_;
Deque<NativeFrameType> queue_ GUARDED_BY(GetLock());
const wtf_size_t max_size_;
};
// Wrapper that allows sharing a single FrameQueue reference across multiple
// threads.
template <typename NativeFrameType>
class FrameQueueHandle {
public:
explicit FrameQueueHandle(
scoped_refptr<FrameQueue<NativeFrameType>> frame_queue)
: queue_(std::move(frame_queue)) {
DCHECK(queue_);
}
FrameQueueHandle(const FrameQueueHandle&) = delete;
FrameQueueHandle& operator=(const FrameQueueHandle&) = delete;
~FrameQueueHandle() { Invalidate(); }
// Returns a copy of |queue_|, which should be checked for nullity and
// re-used throughout the scope of a function call, instead of calling
// Queue() multiple times. Otherwise the queue could be destroyed
// between calls.
scoped_refptr<FrameQueue<NativeFrameType>> Queue() const {
base::AutoLock locker(lock_);
return queue_;
}
// Releases the internal FrameQueue reference.
void Invalidate() {
base::AutoLock locker(lock_);
queue_.reset();
}
private:
mutable base::Lock lock_;
scoped_refptr<FrameQueue<NativeFrameType>> queue_ GUARDED_BY(lock_);
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_BREAKOUT_BOX_FRAME_QUEUE_H_
|