| //===-- 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 |