123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- #pragma once
- #include "ring_buffer.h"
- #include <library/cpp/deprecated/atomic/atomic.h>
- #include <util/system/spinlock.h>
- template <typename T>
- class TRingBufferWithSpinLock {
- private:
- TRingBuffer<T> RingBuffer;
- TSpinLock SpinLock;
- TAtomic CachedSize;
- public:
- TRingBufferWithSpinLock()
- : CachedSize(0)
- {
- }
- void Push(const T& t) {
- PushAll(t);
- }
- void PushAll(TArrayRef<const T> collection) {
- if (collection.empty()) {
- return;
- }
- TGuard<TSpinLock> Guard(SpinLock);
- RingBuffer.PushAll(collection);
- AtomicSet(CachedSize, RingBuffer.Size());
- }
- bool TryPop(T* r, size_t* sizePtr = nullptr) {
- if (AtomicGet(CachedSize) == 0) {
- return false;
- }
- bool ok;
- size_t size;
- {
- TGuard<TSpinLock> Guard(SpinLock);
- ok = RingBuffer.TryPop(r);
- size = RingBuffer.Size();
- AtomicSet(CachedSize, size);
- }
- if (!!sizePtr) {
- *sizePtr = size;
- }
- return ok;
- }
- TMaybe<T> TryPop() {
- T tmp;
- if (TryPop(&tmp)) {
- return tmp;
- } else {
- return TMaybe<T>();
- }
- }
- bool PushAllAndTryPop(TArrayRef<const T> collection, T* r) {
- if (collection.size() == 0) {
- return TryPop(r);
- } else {
- if (AtomicGet(CachedSize) == 0) {
- *r = collection[0];
- if (collection.size() > 1) {
- TGuard<TSpinLock> guard(SpinLock);
- RingBuffer.PushAll(MakeArrayRef(collection.data() + 1, collection.size() - 1));
- AtomicSet(CachedSize, RingBuffer.Size());
- }
- } else {
- TGuard<TSpinLock> guard(SpinLock);
- RingBuffer.PushAll(collection);
- *r = RingBuffer.Pop();
- AtomicSet(CachedSize, RingBuffer.Size());
- }
- return true;
- }
- }
- bool Empty() const {
- return AtomicGet(CachedSize) == 0;
- }
- size_t Size() const {
- TGuard<TSpinLock> Guard(SpinLock);
- return RingBuffer.Size();
- }
- };
|