blob: 05a4a01be7ea759013acd172d55fb257604f31ff [file] [log] [blame] [edit]
//===-- A lock-free fixed capacity buffer for caching values ----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SRC___SUPPORT_GPU_FIXEDBUFFER_H
#define LLVM_LIBC_SRC___SUPPORT_GPU_FIXEDBUFFER_H
#include "src/__support/CPP/atomic.h"
#include <stdint.h>
namespace LIBC_NAMESPACE_DECL {
// A lock-free fixed capacity buffer for caching pointer-like values. Uses a
// flat array where a null/zero value indicates an empty slot.
template <typename T, uint32_t CAPACITY> struct alignas(16) FixedBuffer {
T slots[CAPACITY] = {};
LIBC_INLINE bool push(const T &val) {
for (uint32_t i = 0; i < CAPACITY; ++i) {
cpp::AtomicRef<T> slot(slots[i]);
if (slot.load(cpp::MemoryOrder::RELAXED) != T{})
continue;
T expected{};
if (slot.compare_exchange_strong(expected, val, cpp::MemoryOrder::RELEASE,
cpp::MemoryOrder::RELAXED))
return true;
}
return false;
}
LIBC_INLINE bool pop(T &val) {
for (uint32_t i = 0; i < CAPACITY; ++i) {
cpp::AtomicRef<T> slot(slots[i]);
if (slot.load(cpp::MemoryOrder::RELAXED) == T{})
continue;
val = slot.exchange(T{}, cpp::MemoryOrder::ACQUIRE);
if (val != T{})
return true;
}
return false;
}
};
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC___SUPPORT_GPU_FIXEDBUFFER_H