| | |
| | | |
| | | namespace robust |
| | | { |
| | | /* |
| | | template <unsigned PowerSize = 4, class Int = int64_t> |
| | | class AtomicQueue |
| | | { |
| | | public: |
| | | typedef uint32_t size_type; |
| | | typedef Int Data; |
| | | typedef std::atomic<Data> AData; |
| | | static_assert(sizeof(Data) == sizeof(AData)); |
| | | enum { |
| | | power = PowerSize, |
| | | capacity = (1 << power), |
| | | mask = capacity - 1, |
| | | }; |
| | | |
| | | AtomicQueue() { memset(this, 0, sizeof(*this)); } |
| | | size_type head() const { return head_.load(); } |
| | | size_type tail() const { return tail_.load(); } |
| | | bool push(const Data d, bool try_more = false) |
| | | { |
| | | bool r = false; |
| | | size_type i = 0; |
| | | do { |
| | | auto pos = tail(); |
| | | if (tail_.compare_exchange_strong(pos, Next(pos))) { |
| | | auto cur = buf[pos].load(); |
| | | r = Empty(cur) && buf[pos].compare_exchange_strong(cur, Enc(d)); |
| | | } |
| | | } while (try_more && !r && ++i < capacity); |
| | | return r; |
| | | } |
| | | bool pop(Data &d, bool try_more = false) |
| | | { |
| | | bool r = false; |
| | | Data cur; |
| | | size_type i = 0; |
| | | do { |
| | | auto pos = head(); |
| | | if (head_.compare_exchange_strong(pos, Next(pos))) { |
| | | cur = buf[pos].load(); |
| | | r = !Empty(cur) && buf[pos].compare_exchange_strong(cur, 0); |
| | | } |
| | | } while (try_more && !r && ++i < capacity); |
| | | if (r) { d = Dec(cur); } |
| | | return r; |
| | | } |
| | | |
| | | private: |
| | | static_assert(std::is_integral<Data>::value, "Data must be integral type!"); |
| | | static_assert(std::is_signed<Data>::value, "Data must be signed type!"); |
| | | static_assert(PowerSize < 10, "RobustQ63 max size is 2^10!"); |
| | | |
| | | static inline bool Empty(const Data d) { return (d & 1) == 0; } // lowest bit 1 means data ok. |
| | | static inline Data Enc(const Data d) { return (d << 1) | 1; } // lowest bit 1 means data ok. |
| | | static inline Data Dec(const Data d) { return d >> 1; } // lowest bit 1 means data ok. |
| | | static size_type Next(const size_type index) { return (index + 1) & mask; } |
| | | |
| | | std::atomic<size_type> head_; |
| | | std::atomic<size_type> tail_; |
| | | AData buf[capacity]; |
| | | }; |
| | | //*/ |
| | | |
| | | // atomic queue, length is 1. |
| | | // lowest bit is used for data flag, 63 bit for data. |
| | | class AtomicQ63 |
| | | { |
| | | public: |
| | |
| | | AData buf; |
| | | }; |
| | | |
| | | // atomic request-reply process, one cycle a time. |
| | | class AtomicReqRep |
| | | { |
| | | public: |