115 lines
4.1 KiB
C++
115 lines
4.1 KiB
C++
#ifndef THWEAVER_FABRIC_H
|
|
#define THWEAVER_FABRIC_H
|
|
|
|
#include <array>
|
|
#include <atomic>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <new>
|
|
#include <weaver/results.h>
|
|
|
|
namespace THWeaver {
|
|
|
|
template <typename MessageType, std::size_t qsize_expt> class EndpointQueue {
|
|
public:
|
|
static constexpr size_t CLS =
|
|
std::hardware_destructive_interference_size;
|
|
static constexpr std::size_t QSIZE = 1 << qsize_expt;
|
|
static constexpr std::size_t QSIZE_MASK = QSIZE - 1;
|
|
|
|
EndpointQueue(const EndpointQueue<MessageType, qsize_expt> &) = delete;
|
|
EndpointQueue &
|
|
operator=(const EndpointQueue<MessageType, qsize_expt> &) = delete;
|
|
EndpointQueue(EndpointQueue<MessageType, qsize_expt> &&) = delete;
|
|
EndpointQueue &
|
|
operator=(EndpointQueue<MessageType, qsize_expt> &&) = delete;
|
|
|
|
void init() noexcept;
|
|
void flush() noexcept;
|
|
|
|
std::size_t size() const noexcept;
|
|
bool is_empty() const noexcept;
|
|
bool is_full() const noexcept;
|
|
|
|
std::size_t get_head() const noexcept;
|
|
std::size_t get_tail() const noexcept;
|
|
|
|
EndpointQueueSendResult send(MessageType &&message) noexcept;
|
|
EndpointQueueRecvResult recv(MessageType &buffer) noexcept;
|
|
void recv_unsafe(MessageType &buffer, std::size_t old_head) noexcept;
|
|
|
|
private:
|
|
alignas(CLS) std::array<MessageType, QSIZE> buffer;
|
|
alignas(CLS) std::atomic<std::size_t> head;
|
|
alignas(CLS) std::atomic<std::size_t> tail;
|
|
};
|
|
|
|
template <typename MessageType, std::size_t qsize_expt,
|
|
std::size_t IN_THREAD_CNT>
|
|
class FanInFabric {
|
|
public:
|
|
using BitmapType = uint64_t;
|
|
|
|
static constexpr size_t CLS =
|
|
std::hardware_destructive_interference_size;
|
|
static constexpr std::size_t QSIZE = 1 << qsize_expt;
|
|
static constexpr std::size_t QSIZE_MASK = QSIZE - 1;
|
|
static constexpr std::size_t BITMAP_SIZE = sizeof(BitmapType) * 8;
|
|
static constexpr BitmapType THREAD_BITMAP_MASK =
|
|
IN_THREAD_CNT == BITMAP_SIZE
|
|
? ~BitmapType(0)
|
|
: (BitmapType(1) << IN_THREAD_CNT) - 1;
|
|
|
|
static_assert(IN_THREAD_CNT <= BITMAP_SIZE, "Producer limit exceeded");
|
|
|
|
FanInFabric(const FanInFabric<MessageType, qsize_expt, IN_THREAD_CNT>
|
|
&) = delete;
|
|
FanInFabric &
|
|
operator=(const FanInFabric<MessageType, qsize_expt, IN_THREAD_CNT> &) =
|
|
delete;
|
|
FanInFabric(FanInFabric<MessageType, qsize_expt, IN_THREAD_CNT> &&) =
|
|
delete;
|
|
FanInFabric &
|
|
operator=(FanInFabric<MessageType, qsize_expt, IN_THREAD_CNT> &&) =
|
|
delete;
|
|
|
|
void init() noexcept;
|
|
template <std::size_t thread_id> void flush() noexcept;
|
|
void flush_all() noexcept;
|
|
|
|
template <std::size_t thread_id>
|
|
FanInFabricSendResult send(MessageType &&message) noexcept;
|
|
|
|
FanInFabricRecvBitmapResult
|
|
recv_bitmap_only(MessageType &buffer) noexcept;
|
|
FanInFabricRecvTryResult recv_try(MessageType &buffer) noexcept;
|
|
FanInFabricRecvAggrResult recv_aggr(MessageType &buffer) noexcept;
|
|
|
|
void full_scan(BitmapType &bitmap) noexcept;
|
|
|
|
template <std::size_t thread_id> std::size_t size() const noexcept;
|
|
template <std::size_t thread_id> bool is_empty() const noexcept;
|
|
template <std::size_t thread_id> bool is_full() const noexcept;
|
|
|
|
private:
|
|
std::array<EndpointQueue<MessageType, qsize_expt>, IN_THREAD_CNT>
|
|
in_queues;
|
|
|
|
alignas(CLS) std::atomic<BitmapType> hint;
|
|
struct alignas(CLS) DiscoveryList {
|
|
std::array<uint8_t, IN_THREAD_CNT> next;
|
|
std::array<uint8_t, IN_THREAD_CNT> prev;
|
|
uint8_t first;
|
|
uint8_t last;
|
|
void init() noexcept;
|
|
void move_first_to_last() noexcept;
|
|
void move_to_last(uint8_t index) noexcept;
|
|
} dl;
|
|
std::size_t rotation;
|
|
BitmapType rotate(BitmapType bitmap) const noexcept;
|
|
};
|
|
|
|
} // namespace THWeaver
|
|
|
|
#endif
|