// atomically sets stack_ back and enqueues all elements to the cache bool fetch_new_data(pointer end_ptr) { CAF_ASSERT(end_ptr == nullptr || end_ptr == stack_empty_dummy()); pointer e = stack_.load(); // must not be called on a closed queue CAF_ASSERT(e != nullptr); // fetching data while blocked is an error CAF_ASSERT(e != reader_blocked_dummy()); // it's enough to check this once, since only the owner is allowed // to close the queue and only the owner is allowed to call this // member function while (e != end_ptr) { if (stack_.compare_exchange_weak(e, end_ptr)) { // fetching data while blocked is an error CAF_ASSERT(e != reader_blocked_dummy()); if (is_dummy(e)) { // only use-case for this is closing a queue CAF_ASSERT(end_ptr == nullptr); return false; } while (e) { CAF_ASSERT(! is_dummy(e)); auto next = e->next; e->next = head_; head_ = e; e = next; } return true; } // next iteration } return false; }
// atomically sets m_stack back and enqueues all elements to the cache bool fetch_new_data(pointer end_ptr) { CPPA_REQUIRE(m_head == nullptr); CPPA_REQUIRE(!end_ptr || end_ptr == stack_empty_dummy()); pointer e = m_stack.load(); // must not be called on a closed queue CPPA_REQUIRE(e != nullptr); // it's enough to check this once, since only the owner is allowed // to close the queue and only the owner is allowed to call this // member function while (e != end_ptr) { if (m_stack.compare_exchange_weak(e, end_ptr)) { if (is_dummy(e)) { // only use-case for this is closing a queue CPPA_REQUIRE(end_ptr == nullptr); return false; } while (e) { CPPA_REQUIRE(!is_dummy(e)); auto next = e->next; e->next = m_head; m_head = e; e = next; } return true; } // next iteration } return false; }
/// Tries to set this queue from state `empty` to state `blocked`. bool try_block() { auto e = stack_empty_dummy(); bool res = stack_.compare_exchange_strong(e, reader_blocked_dummy()); CAF_ASSERT(e != nullptr); // return true in case queue was already blocked return res || e == reader_blocked_dummy(); }
inline bool is_dummy(pointer ptr) { return ptr == stack_empty_dummy() || ptr == reader_blocked_dummy(); }
inline bool fetch_new_data() { return fetch_new_data(stack_empty_dummy()); }
inline single_reader_queue() : m_head(nullptr) { m_stack = stack_empty_dummy(); }
/** * @brief Tries to set this queue from state @p blocked to state @p empty. * @returns @p true if the state change was successful, otherwise @p false. * @note This function does never fail spuriously. */ inline bool try_unblock() { auto e = reader_blocked_dummy(); return m_stack.compare_exchange_strong(e, stack_empty_dummy()); }
/** * @brief Tries to set this queue from state @p empty to state @p blocked. * @returns @p true if the state change was successful or if the mailbox * was already blocked, otherwise @p false. * @note This function does never fail spuriously. */ inline bool try_block() { auto e = stack_empty_dummy(); bool res = m_stack.compare_exchange_strong(e, reader_blocked_dummy()); // return true in case queue was already blocked return res || e == reader_blocked_dummy(); }
single_reader_queue() : head_(nullptr) { stack_ = stack_empty_dummy(); }