23 #ifndef _LOCKFREE_CIRCULAR_QUEUE_HPP_ 24 #define _LOCKFREE_CIRCULAR_QUEUE_HPP_ 34 #include <type_traits> 60 inline std::size_t
size ();
62 inline bool consume (T &element);
66 inline bool produce (
const T &element);
112 #if defined (DEBUG_LFCQ) 114 enum class local_action;
126 inline void register_event (local_action action)
128 m_cursor = (m_cursor + 1) % LOCAL_HISTORY_SIZE;
129 m_events[m_cursor].action = action;
134 register_event (action);
135 m_events[m_cursor].m_consequence.cursor_value = cursor;
138 inline void register_event (local_action action, T data)
140 register_event (action);
141 m_events[m_cursor].m_consequence.data_value = data;
144 static const std::size_t LOCAL_HISTORY_SIZE = 64;
145 local_event m_events[LOCAL_HISTORY_SIZE];
146 std::size_t m_cursor;
151 inline bool consume_debug (T &element, local_history &my_history);
152 inline bool produce_debug (
const T &element, local_history &my_history);
153 inline bool force_produce_debug (
const T &element, local_history &my_history);
157 enum class local_action
164 INCREMENT_PRODUCE_CURSOR,
165 INCREMENT_CONSUME_CURSOR,
166 NOT_INCREMENT_PRODUCE_CURSOR,
167 NOT_INCREMENT_CONSUME_CURSOR,
181 consequence () : cursor_value (0) {}
188 : action (local_action::NO_ACTION)
193 static local_history m_shared_dummy_history;
281 did_block =
block (pc);
305 std::this_thread::yield ();
411 std::size_t next_pow = 1;
412 for (--size; size != 0; size /= 2)
422 return produce_cursor <= consume_cursor;
428 return consume_cursor +
m_capacity <= produce_cursor;
435 return cursor.load ();
443 return cursor.compare_exchange_strong (crt_value, crt_value + 1);
494 ref_blocked_cursor.store (nextgen_cursor);
509 #if defined (DEBUG_LFCQ) 520 my_history.register_event (local_action::LOOP_PRODUCE);
523 my_history.register_event (local_action::LOAD_PRODUCE_CURSOR, pc);
526 my_history.register_event (local_action::LOAD_CONSUME_CURSOR, cc);
531 my_history.register_event (local_action::QUEUE_FULL);
536 did_block =
block (pc);
537 my_history.register_event (did_block ? local_action::BLOCKED_CURSOR : local_action::NOT_BLOCKED_CURSOR, pc);
543 my_history.register_event (local_action::INCREMENT_PRODUCE_CURSOR, pc);
547 my_history.register_event (local_action::NOT_INCREMENT_PRODUCE_CURSOR, pc);
553 my_history.register_event (local_action::STORED_DATA, element);
556 my_history.register_event (local_action::UNBLOCKED_CURSOR, pc);
565 while (!produce_debug (element, my_history))
567 std::this_thread::yield ();
579 my_history.register_event (local_action::LOOP_CONSUME);
582 my_history.register_event (local_action::LOAD_CONSUME_CURSOR, cc);
585 my_history.register_event (local_action::LOAD_PRODUCE_CURSOR, pc);
590 my_history.register_event (local_action::QUEUE_EMPTY);
597 my_history.register_event (local_action::QUEUE_EMPTY);
603 my_history.register_event (local_action::LOADED_DATA, element);
608 my_history.register_event (local_action::INCREMENT_CONSUME_CURSOR, cc);
616 my_history.register_event (local_action::NOT_INCREMENT_CONSUME_CURSOR, cc);
627 #endif // _LOCKFREE_CIRCULAR_QUEUE_HPP_
std::atomic< cursor_type > atomic_cursor_type
atomic_cursor_type m_consume_cursor
void init_blocked_cursors(void)
void force_produce(const T &element)
bool test_empty_cursors(cursor_type produce_cursor, cursor_type consume_cursor) const
bool test_and_increment_cursor(atomic_cursor_type &cursor, cursor_type crt_value)
void store_data(cursor_type index, const T &data)
atomic_cursor_type atomic_flag_type
flag & clear(const T &flags)
bool is_blocked(cursor_type cursor) const
atomic_flag_type * m_blocked_cursors
std::uint64_t get_consumer_cursor()
void unblock(cursor_type cursor)
cursor_type load_cursor(atomic_cursor_type &cursor)
bool test_full_cursors(cursor_type produce_cursor, cursor_type consume_cursor) const
bool block(cursor_type cursor)
static const cursor_type BLOCK_FLAG
std::size_t get_cursor_index(cursor_type cursor) const
static bool is_flag_set(const T &where_to_check, const T &what_to_check)
T load_data(cursor_type consume_cursor) const
std::size_t next_pow2(std::size_t size) const
std::uint64_t cursor_type
bool produce(const T &element)
bool is_set(const T &flags)
atomic_cursor_type m_produce_cursor