8 #include <density/heter_queue.h> 34 template <
typename RUNTIME_TYPE = runtime_type<>,
typename ALLOCATOR_TYPE = default_allocator>
40 enum class PrivateType
62 using runtime_type = RUNTIME_TYPE;
63 using value_type = std::pair<const runtime_type &, void * const>;
64 using allocator_type = ALLOCATOR_TYPE;
65 using pointer = value_type *;
66 using const_pointer =
const value_type *;
67 using reference = value_type;
68 using const_reference =
const value_type &;
69 using size_type = std::size_t;
70 using difference_type = std::ptrdiff_t;
96 constexpr explicit
conc_heter_queue(const ALLOCATOR_TYPE & i_source_allocator) noexcept
97 : m_queue(i_source_allocator)
112 : m_queue(
std::move(i_source_allocator))
126 : m_queue(
std::move(i_source.m_queue))
144 m_queue = std::move(i_source.m_queue);
154 return m_queue.get_allocator();
167 return m_queue.get_allocator_ref();
177 swap(i_first.m_queue, i_second.m_queue);
195 std::lock_guard<std::mutex> lock(m_mutex);
196 return m_queue.empty();
208 std::lock_guard<std::mutex> lock(m_mutex);
237 ELEMENT_COMPLETE_TYPE,
238 typename std::decay<ELEMENT_COMPLETE_TYPE>::type>::value,
264 typename =
typename std::enable_if<
265 std::is_same<OTHERTYPE, ELEMENT_COMPLETE_TYPE>::value ||
266 std::is_void<ELEMENT_COMPLETE_TYPE>::value>::type>
268 : m_lock(
std::move(i_source.m_lock)),
269 m_put_transaction(
std::move(i_source.m_put_transaction))
280 typename =
typename std::enable_if<
281 std::is_same<OTHERTYPE, ELEMENT_COMPLETE_TYPE>::value ||
282 std::is_void<ELEMENT_COMPLETE_TYPE>::value>::type>
296 swap(m_put_transaction, source.m_put_transaction);
297 swap(m_lock, source.m_lock);
308 swap(i_first.m_put_transaction, i_second.m_put_transaction);
309 swap(i_first.m_lock, i_second.m_lock);
336 return m_put_transaction.raw_allocate(i_size, i_alignment);
363 template <
typename INPUT_ITERATOR>
364 typename std::iterator_traits<INPUT_ITERATOR>::value_type *
367 return m_put_transaction.raw_allocate_copy(i_begin, i_end);
392 template <
typename INPUT_RANGE>
394 -> decltype(std::declval<put_transaction>().raw_allocate_copy(
395 std::begin(i_source_range), std::end(i_source_range)))
397 return m_put_transaction.raw_allocate_copy(
398 std::begin(i_source_range), std::end(i_source_range));
412 m_put_transaction.commit();
429 m_put_transaction.cancel();
436 bool empty() const noexcept {
return m_put_transaction.empty(); }
441 explicit operator bool() const noexcept {
return m_put_transaction.operator bool(); }
458 return m_put_transaction.element_ptr();
474 #ifndef DOXYGEN_DOC_GENERATION 476 typename EL = ELEMENT_COMPLETE_TYPE,
477 typename std::enable_if<!std::is_void<EL>::value>::type * =
nullptr>
480 ELEMENT_COMPLETE_TYPE &
484 return *
static_cast<ELEMENT_COMPLETE_TYPE *
>(m_put_transaction.element_ptr());
495 return m_put_transaction.complete_type();
503 if (m_lock.owns_lock())
505 m_put_transaction.cancel();
512 std::unique_lock<std::mutex> && i_lock,
514 i_put_transaction) noexcept
515 : m_lock(std::move(i_lock)), m_put_transaction(std::move(i_put_transaction))
517 if (!m_put_transaction)
522 std::unique_lock<std::mutex> m_lock;
572 m_lock = std::move(i_source.m_lock);
573 m_consume_operation = std::move(i_source.m_consume_operation);
582 if (m_lock.owns_lock())
591 std::swap(i_first.m_lock, i_second.m_lock);
592 std::swap(i_first.m_consume_operation, i_second.m_consume_operation);
598 bool empty() const noexcept {
return m_consume_operation.empty(); }
603 explicit operator bool() const noexcept {
return m_consume_operation.operator bool(); }
616 m_consume_operation.commit();
640 m_consume_operation.commit_nodestroy();
657 m_consume_operation.cancel();
668 return m_consume_operation.complete_type();
680 return m_consume_operation.unaligned_element_ptr();
690 void *
element_ptr() const noexcept {
return m_consume_operation.element_ptr(); }
698 template <
typename COMPLETE_ELEMENT_TYPE>
699 COMPLETE_ELEMENT_TYPE &
element() const noexcept
701 return m_consume_operation.template element<COMPLETE_ELEMENT_TYPE>();
707 std::unique_lock<std::mutex> && i_lock,
709 : m_lock(std::move(i_lock)), m_consume_operation(std::move(i_consume_operation))
716 if (m_lock.owns_lock())
719 m_lock = std::unique_lock<std::mutex>(i_queue->m_mutex);
728 std::unique_lock<std::mutex> m_lock;
749 template <
typename ELEMENT_TYPE>
void push(ELEMENT_TYPE && i_source)
751 return emplace<typename std::decay<ELEMENT_TYPE>::type>(
752 std::forward<ELEMENT_TYPE>(i_source));
771 template <
typename ELEMENT_TYPE,
typename... CONSTRUCTION_PARAMS>
772 void emplace(CONSTRUCTION_PARAMS &&... i_construction_params)
774 start_emplace<ELEMENT_TYPE>(std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...)
865 template <
typename ELEMENT_TYPE>
866 put_transaction<typename std::decay<ELEMENT_TYPE>::type>
869 return start_emplace<typename std::decay<ELEMENT_TYPE>::type>(
870 std::forward<ELEMENT_TYPE>(i_source));
895 template <
typename ELEMENT_TYPE,
typename... CONSTRUCTION_PARAMS>
896 put_transaction<ELEMENT_TYPE>
start_emplace(CONSTRUCTION_PARAMS &&... i_construction_params)
898 std::unique_lock<std::mutex> lock(m_mutex);
899 return put_transaction<ELEMENT_TYPE>(
902 m_queue.template start_emplace<ELEMENT_TYPE>(
903 std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...));
926 std::unique_lock<std::mutex> lock(m_mutex);
927 return put_transaction<>(
928 PrivateType(), std::move(lock), m_queue.start_dyn_push(i_type));
954 std::unique_lock<std::mutex> lock(m_mutex);
955 return put_transaction<>(
956 PrivateType(), std::move(lock), m_queue.start_dyn_push_copy(i_type, i_source));
981 std::unique_lock<std::mutex> lock(m_mutex);
982 return put_transaction<>(
983 PrivateType(), std::move(lock), m_queue.start_dyn_push_move(i_type, i_source));
1031 std::unique_lock<std::mutex> lock(m_mutex);
1032 auto consume = m_queue.try_start_consume();
1035 return consume_operation(PrivateType(), std::move(lock), std::move(consume));
1053 return i_consume.start_consume_impl(PrivateType(),
this);
1082 ELEMENT_COMPLETE_TYPE,
1083 typename std::decay<ELEMENT_COMPLETE_TYPE>::type>::value,
1109 typename =
typename std::enable_if<
1110 std::is_same<OTHERTYPE, ELEMENT_COMPLETE_TYPE>::value ||
1111 std::is_void<ELEMENT_COMPLETE_TYPE>::value>::type>
1113 : m_queue(i_source.m_queue),
1114 m_put_transaction(
std::move(i_source.m_put_transaction))
1116 i_source.m_queue =
nullptr;
1126 typename =
typename std::enable_if<
1127 std::is_same<OTHERTYPE, ELEMENT_COMPLETE_TYPE>::value ||
1128 std::is_void<ELEMENT_COMPLETE_TYPE>::value>::type>
1132 m_queue = i_source.m_queue;
1133 m_put_transaction = std::move(i_source.m_put_transaction);
1134 i_source.m_queue =
nullptr;
1144 std::swap(i_first.m_queue, i_second.m_queue);
1145 std::swap(i_first.m_put_transaction, i_second.m_put_transaction);
1173 std::lock_guard<std::mutex> lock(m_queue->m_mutex);
1174 return m_put_transaction.raw_allocate(i_size, i_alignment);
1201 template <
typename INPUT_ITERATOR>
1202 typename std::iterator_traits<INPUT_ITERATOR>::value_type *
1206 std::lock_guard<std::mutex> lock(m_queue->m_mutex);
1207 return m_put_transaction.raw_allocate_copy(i_begin, i_end);
1232 template <
typename INPUT_RANGE>
1234 -> decltype(std::declval<reentrant_put_transaction>().raw_allocate_copy(
1235 std::begin(i_source_range), std::end(i_source_range)))
1238 std::lock_guard<std::mutex> lock(m_queue->m_mutex);
1239 return m_put_transaction.raw_allocate_copy(
1240 std::begin(i_source_range), std::end(i_source_range));
1254 std::lock_guard<std::mutex> lock(m_queue->m_mutex);
1255 m_put_transaction.commit();
1273 std::lock_guard<std::mutex> lock(m_queue->m_mutex);
1274 m_put_transaction.cancel();
1281 bool empty() const noexcept {
return m_queue ==
nullptr; }
1286 explicit operator bool() const noexcept {
return m_queue !=
nullptr; }
1304 void *
element_ptr() const noexcept {
return m_put_transaction.element_ptr(); }
1319 #ifndef DOXYGEN_DOC_GENERATION 1321 typename EL = ELEMENT_COMPLETE_TYPE,
1322 typename std::enable_if<!std::is_void<EL>::value>::type * =
nullptr>
1325 ELEMENT_COMPLETE_TYPE &
1329 return *
static_cast<ELEMENT_COMPLETE_TYPE *
>(element_ptr());
1340 return m_put_transaction.complete_type();
1348 if (m_put_transaction)
1359 i_put_transaction) noexcept
1360 : m_queue(i_queue), m_put_transaction(std::move(i_put_transaction))
1435 std::swap(i_first.m_queue, i_second.m_queue);
1436 std::swap(i_first.m_consume_operation, i_second.m_consume_operation);
1442 bool empty() const noexcept {
return m_consume_operation.
empty(); }
1447 explicit operator bool() const noexcept {
return m_consume_operation.operator bool(); }
1465 std::lock_guard<std::mutex> lock(m_queue->m_mutex);
1466 m_consume_operation.commit();
1489 std::lock_guard<std::mutex> lock(m_queue->m_mutex);
1490 m_consume_operation.commit_nodestroy();
1506 std::lock_guard<std::mutex> lock(m_queue->m_mutex);
1507 m_consume_operation.cancel();
1547 template <
typename COMPLETE_ELEMENT_TYPE>
1550 return m_consume_operation.template element<COMPLETE_ELEMENT_TYPE>();
1558 : m_queue(i_queue), m_consume_operation(std::move(i_consume_operation))
1568 std::unique_lock<std::mutex> lock;
1569 if (m_queue !=
nullptr)
1571 lock = std::unique_lock<std::mutex>(m_queue->m_mutex);
1573 std::unique_lock<std::mutex> new_lock;
1574 if (m_queue != i_queue && i_queue !=
nullptr)
1576 new_lock = std::unique_lock<std::mutex>(i_queue->m_mutex);
1580 if (m_consume_operation)
1581 m_consume_operation.cancel();
1582 lock = std::move(new_lock);
1599 return reentrant_emplace<ELEMENT_TYPE>(std::forward<ELEMENT_TYPE>(i_source));
1607 template <
typename ELEMENT_TYPE,
typename... CONSTRUCTION_PARAMS>
1610 start_reentrant_emplace<typename std::decay<ELEMENT_TYPE>::type>(
1611 std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...)
1650 template <
typename ELEMENT_TYPE>
1651 reentrant_put_transaction<typename std::decay<ELEMENT_TYPE>::type>
1654 return start_reentrant_emplace<typename std::decay<ELEMENT_TYPE>::type>(
1655 std::forward<ELEMENT_TYPE>(i_source));
1663 template <
typename ELEMENT_TYPE,
typename... CONSTRUCTION_PARAMS>
1664 reentrant_put_transaction<ELEMENT_TYPE>
1667 std::lock_guard<std::mutex> lock(m_mutex);
1668 auto put_transaction = m_queue.template start_reentrant_emplace<ELEMENT_TYPE>(
1669 std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...);
1670 return reentrant_put_transaction<ELEMENT_TYPE>(
1671 PrivateType(),
this, std::move(put_transaction));
1681 std::lock_guard<std::mutex> lock(m_mutex);
1682 auto put_transaction = m_queue.start_reentrant_dyn_push(i_type);
1683 return reentrant_put_transaction<>(PrivateType(),
this, std::move(put_transaction));
1692 reentrant_put_transaction<>
1695 std::lock_guard<std::mutex> lock(m_mutex);
1696 auto put_transaction = m_queue.start_reentrant_dyn_push_copy(i_type, i_source);
1697 return reentrant_put_transaction<>(PrivateType(),
this, std::move(put_transaction));
1705 reentrant_put_transaction<>
1708 std::lock_guard<std::mutex> lock(m_mutex);
1709 auto put_transaction = m_queue.start_reentrant_dyn_push_move(i_type, i_source);
1710 return reentrant_put_transaction<>(PrivateType(),
this, std::move(put_transaction));
1762 std::lock_guard<std::mutex> lock(m_mutex);
1763 return reentrant_consume_operation(
1764 PrivateType(),
this, m_queue.try_start_reentrant_consume());
1784 return i_consume.start_consume_impl(PrivateType(),
this);
1788 mutable std::mutex m_mutex;
allocator_type & get_allocator_ref() noexcept
Definition: conc_heter_queue.h:160
const RUNTIME_TYPE & complete_type() const noexcept
Definition: conc_heter_queue.h:493
allocator_type get_allocator() noexcept(std::is_nothrow_copy_constructible< allocator_type >::value)
Definition: conc_heter_queue.h:152
~reentrant_put_transaction()
Definition: conc_heter_queue.h:1346
void cancel() noexcept
Definition: conc_heter_queue.h:654
Definition: conc_heter_queue.h:1388
Definition: conc_function_queue.h:11
put_transaction start_dyn_push_copy(const runtime_type &i_type, const void *i_source)
Definition: conc_heter_queue.h:952
reentrant_put_transaction< typename std::decay< ELEMENT_TYPE >::type > start_reentrant_push(ELEMENT_TYPE &&i_source)
Definition: conc_heter_queue.h:1652
bool try_reentrant_pop() noexcept
Definition: conc_heter_queue.h:1741
conc_heter_queue * queue() const noexcept
Definition: conc_heter_queue.h:1452
void commit() noexcept
Definition: conc_heter_queue.h:1462
void reentrant_push(ELEMENT_TYPE &&i_source)
Definition: conc_heter_queue.h:1597
~consume_operation()
Definition: conc_heter_queue.h:580
~put_transaction()
Definition: conc_heter_queue.h:501
void dyn_push_copy(const runtime_type &i_type, const void *i_source)
Definition: conc_heter_queue.h:814
void * element_ptr() const noexcept
Definition: conc_heter_queue.h:455
void * element_ptr() const noexcept
Definition: conc_heter_queue.h:1539
const RUNTIME_TYPE & complete_type() const noexcept
Definition: conc_heter_queue.h:1515
static constexpr size_t min_alignment
Definition: conc_heter_queue.h:60
constexpr conc_heter_queue(ALLOCATOR_TYPE &&i_source_allocator) noexcept
Definition: conc_heter_queue.h:111
void * raw_allocate(size_t i_size, size_t i_alignment)
Definition: conc_heter_queue.h:334
Definition: conc_heter_queue.h:1078
put_transaction< typename std::decay< ELEMENT_TYPE >::type > start_push(ELEMENT_TYPE &&i_source)
Definition: conc_heter_queue.h:867
void commit_nodestroy() noexcept
Definition: conc_heter_queue.h:1486
ELEMENT_COMPLETE_TYPE & element() const noexcept
Definition: conc_heter_queue.h:1327
void reentrant_pop() noexcept
Definition: conc_heter_queue.h:1728
Definition: runtime_type.h:1061
Definition: heter_queue.h:200
void commit() noexcept
Definition: conc_heter_queue.h:409
put_transaction start_dyn_push(const runtime_type &i_type)
Definition: conc_heter_queue.h:924
reentrant_put_transaction< ELEMENT_TYPE > start_reentrant_emplace(CONSTRUCTION_PARAMS &&...i_construction_params)
Definition: conc_heter_queue.h:1665
void * unaligned_element_ptr() const noexcept
Definition: conc_heter_queue.h:678
void reentrant_dyn_push_move(const runtime_type &i_type, void *i_source)
Definition: conc_heter_queue.h:1640
static constexpr bool is_seq_cst
Definition: conc_heter_queue.h:56
void commit() noexcept
Definition: conc_heter_queue.h:613
reentrant_consume_operation try_start_reentrant_consume() noexcept
Definition: conc_heter_queue.h:1760
Definition: conc_heter_queue.h:544
~conc_heter_queue()=default
void reentrant_dyn_push(const runtime_type &i_type)
Definition: conc_heter_queue.h:1620
constexpr conc_heter_queue() noexcept=default
static constexpr bool concurrent_put_consumes
Definition: conc_heter_queue.h:53
#define DENSITY_ASSERT(...)
Definition: density_config.h:19
bool empty() const noexcept
Definition: conc_heter_queue.h:598
COMPLETE_ELEMENT_TYPE & element() const noexcept
Definition: conc_heter_queue.h:1548
put_transaction(put_transaction< OTHERTYPE > &&i_source) noexcept
Definition: conc_heter_queue.h:267
reentrant_put_transaction start_reentrant_dyn_push_move(const runtime_type &i_type, void *i_source)
Definition: conc_heter_queue.h:1706
reentrant_put_transaction start_reentrant_dyn_push(const runtime_type &i_type)
Definition: conc_heter_queue.h:1679
Definition: heter_queue.h:843
void * element_ptr() const noexcept
Definition: conc_heter_queue.h:1304
reentrant_consume_operation try_start_reentrant_consume() noexcept
Definition: heter_queue.h:2322
bool empty() const noexcept
Definition: conc_heter_queue.h:1442
void cancel() noexcept
Definition: conc_heter_queue.h:1270
std::iterator_traits< INPUT_ITERATOR >::value_type * raw_allocate_copy(INPUT_ITERATOR i_begin, INPUT_ITERATOR i_end)
Definition: conc_heter_queue.h:365
consume_operation & operator=(consume_operation &&i_source) noexcept
Definition: conc_heter_queue.h:570
void reentrant_dyn_push_copy(const runtime_type &i_type, const void *i_source)
Definition: conc_heter_queue.h:1630
friend void swap(consume_operation &i_first, consume_operation &i_second) noexcept
Definition: conc_heter_queue.h:589
bool empty() const noexcept
Definition: conc_heter_queue.h:436
conc_heter_queue(conc_heter_queue &&i_source) noexcept
Definition: conc_heter_queue.h:125
void emplace(CONSTRUCTION_PARAMS &&...i_construction_params)
Definition: conc_heter_queue.h:772
~reentrant_consume_operation()
Definition: conc_heter_queue.h:1420
reentrant_put_transaction start_reentrant_dyn_push_copy(const runtime_type &i_type, const void *i_source)
Definition: conc_heter_queue.h:1693
Definition: conc_heter_queue.h:35
reentrant_put_transaction & operator=(reentrant_put_transaction< OTHERTYPE > &&i_source) noexcept
Definition: conc_heter_queue.h:1130
const allocator_type & get_allocator_ref() const noexcept
Definition: conc_heter_queue.h:165
void * unaligned_element_ptr() const noexcept
Definition: conc_heter_queue.h:1527
Definition: heter_queue.h:1831
friend void swap(conc_heter_queue< RUNTIME_TYPE, ALLOCATOR_TYPE > &i_first, conc_heter_queue< RUNTIME_TYPE, ALLOCATOR_TYPE > &i_second) noexcept
Definition: conc_heter_queue.h:173
conc_heter_queue & operator=(conc_heter_queue &&i_source) noexcept
Definition: conc_heter_queue.h:142
conc_heter_queue * queue() const noexcept
Definition: conc_heter_queue.h:1291
Definition: conc_heter_queue.h:233
bool empty() const noexcept
Definition: conc_heter_queue.h:1281
void reentrant_emplace(CONSTRUCTION_PARAMS &&...i_construction_params)
Definition: conc_heter_queue.h:1608
auto raw_allocate_copy(const INPUT_RANGE &i_source_range) -> decltype(std::declval< put_transaction >().raw_allocate_copy( std::begin(i_source_range), std::end(i_source_range)))
Definition: conc_heter_queue.h:393
std::iterator_traits< INPUT_ITERATOR >::value_type * raw_allocate_copy(INPUT_ITERATOR i_begin, INPUT_ITERATOR i_end)
Definition: conc_heter_queue.h:1203
ELEMENT_COMPLETE_TYPE & element() const noexcept
Definition: conc_heter_queue.h:482
const RUNTIME_TYPE & complete_type() const noexcept
Definition: conc_heter_queue.h:1338
static constexpr bool concurrent_puts
Definition: conc_heter_queue.h:46
consume_operation try_start_consume() noexcept
Definition: heter_queue.h:1456
COMPLETE_ELEMENT_TYPE & element() const noexcept
Definition: conc_heter_queue.h:699
void push(ELEMENT_TYPE &&i_source)
Definition: conc_heter_queue.h:749
auto raw_allocate_copy(const INPUT_RANGE &i_source_range) -> decltype(std::declval< reentrant_put_transaction >().raw_allocate_copy( std::begin(i_source_range), std::end(i_source_range)))
Definition: conc_heter_queue.h:1233
static constexpr bool concurrent_consumes
Definition: conc_heter_queue.h:49
reentrant_put_transaction(reentrant_put_transaction< OTHERTYPE > &&i_source) noexcept
Definition: conc_heter_queue.h:1112
friend void swap(reentrant_consume_operation &i_first, reentrant_consume_operation &i_second) noexcept
Definition: conc_heter_queue.h:1431
void commit_nodestroy() noexcept
Definition: conc_heter_queue.h:637
put_transaction & operator=(put_transaction< OTHERTYPE > &&i_source) noexcept
Definition: conc_heter_queue.h:283
void * element_ptr() const noexcept
Definition: conc_heter_queue.h:690
bool try_start_consume(consume_operation &i_consume) noexcept
Definition: conc_heter_queue.h:1051
void dyn_push_move(const runtime_type &i_type, void *i_source)
Definition: conc_heter_queue.h:837
void dyn_push(const runtime_type &i_type)
Definition: conc_heter_queue.h:794
consume_operation try_start_consume() noexcept
Definition: conc_heter_queue.h:1029
void cancel() noexcept
Definition: conc_heter_queue.h:1503
void cancel() noexcept
Definition: conc_heter_queue.h:426
const RUNTIME_TYPE & complete_type() const noexcept
Definition: conc_heter_queue.h:666
bool try_pop() noexcept
Definition: conc_heter_queue.h:1013
void commit() noexcept
Definition: conc_heter_queue.h:1251
void * raw_allocate(size_t i_size, size_t i_alignment)
Definition: conc_heter_queue.h:1170
static constexpr size_t min_alignment
Definition: heter_queue.h:218
#define DENSITY_ASSUME(bool_expr,...)
Definition: density_config.h:46
void clear() noexcept
Definition: conc_heter_queue.h:206
void pop() noexcept
Definition: conc_heter_queue.h:1001
bool empty() const noexcept
Definition: conc_heter_queue.h:193
friend void swap(reentrant_put_transaction &i_first, reentrant_put_transaction &i_second) noexcept
Definition: conc_heter_queue.h:1141
bool try_start_reentrant_consume(reentrant_consume_operation &i_consume) noexcept
Definition: conc_heter_queue.h:1782
friend void swap(put_transaction &i_first, put_transaction &i_second) noexcept
Definition: conc_heter_queue.h:305
put_transaction< ELEMENT_TYPE > start_emplace(CONSTRUCTION_PARAMS &&...i_construction_params)
Definition: conc_heter_queue.h:896
put_transaction start_dyn_push_move(const runtime_type &i_type, void *i_source)
Definition: conc_heter_queue.h:979