//===-- 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 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 struct alignas(16) FixedBuffer { T slots[CAPACITY] = {}; LIBC_INLINE bool push(const T &val) { for (uint32_t i = 0; i < CAPACITY; ++i) { cpp::AtomicRef 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 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