// 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;
 }
 /// 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();
 }
Example #3
0
 // returns true if the queue was empty
 enqueue_result enqueue(pointer new_element) {
     pointer e = m_stack.load();
     for (;;) {
         if (!e) {
             // if tail is nullptr, the queue has been closed
             m_delete(new_element);
             return enqueue_result::queue_closed;
         }
         new_element->next = is_dummy(e) ? nullptr : e;
         if (m_stack.compare_exchange_weak(e, new_element)) {
             return (e == reader_blocked_dummy())
                     ? enqueue_result::unblocked_reader
                     : enqueue_result::success;
         }
     }
 }
 /// Tries to enqueue a new element to the mailbox.
 /// @warning Call only from the reader (owner).
 enqueue_result enqueue(pointer new_element) {
   CAF_ASSERT(new_element != nullptr);
   pointer e = stack_.load();
   for (;;) {
     if (! e) {
       // if tail is nullptr, the queue has been closed
       delete_(new_element);
       return enqueue_result::queue_closed;
     }
     // a dummy is never part of a non-empty list
     new_element->next = is_dummy(e) ? nullptr : e;
     if (stack_.compare_exchange_strong(e, new_element)) {
       return  (e == reader_blocked_dummy()) ? enqueue_result::unblocked_reader
                                             : enqueue_result::success;
     }
     // continue with new value of e
   }
 }
Example #5
0
 inline bool is_dummy(pointer ptr) {
     return ptr == stack_empty_dummy() || ptr == reader_blocked_dummy();
 }
Example #6
0
 /**
  * @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());
 }
Example #7
0
 /**
  * @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();
 }
Example #8
0
 inline bool blocked() {
     return m_stack == reader_blocked_dummy();
 }
 /// Queries whether this has been marked as blocked, i.e.,
 /// the owner of the list is waiting for new data.
 bool blocked() {
   return stack_.load() == reader_blocked_dummy();
 }