density
C++11 library for paged memory management, function queues, heterogeneous queues and lifo memory management
lf_heter_queue.h
1 
2 // Copyright Giuseppe Campana (giu.campana@gmail.com) 2016-2018.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 
7 #pragma once
8 #include <density/default_allocator.h>
10 #include <density/raw_atomic.h>
11 #include <density/runtime_type.h>
12 #include <limits>
13 #include <type_traits>
14 
15 #ifdef _MSC_VER
16 #pragma warning(push)
17 #pragma warning(disable : 4324) // structure was padded due to alignment specifier
18 #endif
19 
20 #include <density/detail/lf_queue_base.h>
21 #include <density/detail/lf_queue_head_multiple.h>
22 #include <density/detail/lf_queue_head_single.h>
23 #include <density/detail/lf_queue_tail_multiple_relaxed.h>
24 #include <density/detail/lf_queue_tail_multiple_seq_cst.h>
25 #include <density/detail/lf_queue_tail_single.h>
26 
27 namespace density
28 {
175  template <
176  typename RUNTIME_TYPE = runtime_type<>,
177  typename ALLOCATOR_TYPE = default_allocator,
179  concurrency_cardinality CONSUMER_CARDINALITY = concurrency_multiple,
180  consistency_model CONSISTENCY_MODEL = consistency_sequential>
182  : private detail::LFQueue_Head<
183  RUNTIME_TYPE,
184  ALLOCATOR_TYPE,
185  CONSUMER_CARDINALITY,
186  detail::LFQueue_Tail<RUNTIME_TYPE, ALLOCATOR_TYPE, PROD_CARDINALITY, CONSISTENCY_MODEL>>
187  {
188  private:
189  using Base = detail::LFQueue_Head<
190  RUNTIME_TYPE,
191  ALLOCATOR_TYPE,
192  CONSUMER_CARDINALITY,
193  detail::LFQueue_Tail<RUNTIME_TYPE, ALLOCATOR_TYPE, PROD_CARDINALITY, CONSISTENCY_MODEL>>;
194  using Base::try_inplace_allocate;
195  using typename Base::Allocation;
196  using typename Base::Consume;
197  using typename Base::ControlBlock;
198 
200  enum class PrivateType
201  {
202  };
203 
204  public:
206  constexpr static size_t min_alignment = Base::min_alignment;
207 
208  using runtime_type = RUNTIME_TYPE;
209  using value_type = std::pair<const runtime_type &, void * const>;
210  using allocator_type = ALLOCATOR_TYPE;
211  using pointer = value_type *;
212  using const_pointer = const value_type *;
213  using reference = value_type;
214  using const_reference = const value_type &;
215  using size_type = std::size_t;
216  using difference_type = std::ptrdiff_t;
217 
219  static constexpr bool concurrent_puts = PROD_CARDINALITY == concurrency_multiple;
220 
222  static constexpr bool concurrent_consumes = CONSUMER_CARDINALITY == concurrency_multiple;
223 
226  static constexpr bool concurrent_put_consumes = true;
227 
229  static constexpr bool is_seq_cst = CONSISTENCY_MODEL == consistency_sequential;
230 
231  static_assert(
232  is_power_of_2(ALLOCATOR_TYPE::page_alignment) &&
233  ALLOCATOR_TYPE::page_alignment >= ALLOCATOR_TYPE::page_size &&
234  (ALLOCATOR_TYPE::page_alignment % min_alignment) == 0,
235  "The alignment of the pages must be a power of 2, greater or equal to the size of the "
236  "pages, and a multiple of min_alignment");
237 
238  static_assert(
239  ALLOCATOR_TYPE::page_size > (min_alignment + alignof(ControlBlock)) * 4,
240  "Invalid page size");
241 
249  constexpr lf_heter_queue() noexcept = default;
250 
259  constexpr explicit lf_heter_queue(const ALLOCATOR_TYPE & i_source_allocator) noexcept
260  : Base(i_source_allocator)
261  {
262  }
263 
272  constexpr explicit lf_heter_queue(ALLOCATOR_TYPE && i_source_allocator) noexcept
273  : Base(std::move(i_source_allocator))
274  {
275  static_assert(std::is_nothrow_move_constructible<ALLOCATOR_TYPE>::value, "");
276  }
277 
287  lf_heter_queue(lf_heter_queue && i_source) noexcept = default;
288 
300  lf_heter_queue & operator=(lf_heter_queue && i_source) noexcept
301  {
302  swap(static_cast<Base &>(*this), static_cast<Base &>(i_source));
303  return *this;
304  }
305 
309  allocator_type get_allocator() noexcept { return *this; }
310 
314  allocator_type & get_allocator_ref() noexcept { return *this; }
315 
319  const allocator_type & get_allocator_ref() const noexcept { return *this; }
320 
324  friend void swap(lf_heter_queue & i_first, lf_heter_queue & i_second) noexcept
325  {
326  swap(static_cast<Base &>(i_first), static_cast<Base &>(i_second));
327  }
328 
335  {
336  clear();
337 
338  Consume consume;
339  consume.begin_iteration(this);
340  if (!consume.empty())
341  {
342  consume.clean_dead_elements();
343  }
344  }
345 
352  bool empty() const noexcept { return Consume().is_queue_empty(this); }
353 
361  void clear() noexcept
362  {
363  consume_operation consume;
364  while (try_start_consume(consume))
365  {
366  consume.commit();
367  }
368  }
369 
391  template <typename ELEMENT_COMPLETE_TYPE = void> class put_transaction
392  {
393  static_assert(
394  std::is_same<
395  ELEMENT_COMPLETE_TYPE,
396  typename std::decay<ELEMENT_COMPLETE_TYPE>::type>::value,
397  "");
398 
399  public:
401  put_transaction() noexcept = default;
402 
406  put_transaction(const put_transaction &) = delete;
407 
411  put_transaction & operator=(const put_transaction &) = delete;
412 
420  template <
421  typename OTHERTYPE,
422  typename = typename std::enable_if<
423  std::is_same<OTHERTYPE, ELEMENT_COMPLETE_TYPE>::value ||
424  std::is_void<ELEMENT_COMPLETE_TYPE>::value>::type>
426  : m_put(i_source.m_put), m_queue(i_source.m_queue)
427  {
428  i_source.m_put.m_user_storage = nullptr;
429  }
430 
436  template <
437  typename OTHERTYPE,
438  typename = typename std::enable_if<
439  std::is_same<OTHERTYPE, ELEMENT_COMPLETE_TYPE>::value ||
440  std::is_void<ELEMENT_COMPLETE_TYPE>::value>::type>
442  {
443  using std::swap;
444  swap(m_put, i_source.m_put);
445  swap(m_queue, i_source.m_queue);
446  return *this;
447  }
448 
452  friend void swap(put_transaction & i_first, put_transaction & i_second) noexcept
453  {
454  using std::swap;
455  swap(i_first.m_put, i_second.m_put);
456  swap(i_first.m_queue, i_second.m_queue);
457  }
458 
481  void * raw_allocate(size_t i_size, size_t i_alignment)
482  {
483  DENSITY_ASSERT(!empty());
484  auto push_data =
485  m_queue->template try_inplace_allocate_impl<detail::LfQueue_Throwing>(
486  detail::LfQueue_Dead, false, i_size, i_alignment);
487  return push_data.m_user_storage;
488  }
489 
514  template <typename INPUT_ITERATOR>
515  typename std::iterator_traits<INPUT_ITERATOR>::value_type *
516  raw_allocate_copy(INPUT_ITERATOR i_begin, INPUT_ITERATOR i_end)
517  {
518  using ValueType = typename std::iterator_traits<INPUT_ITERATOR>::value_type;
519  static_assert(
520  std::is_trivially_destructible<ValueType>::value,
521  "raw_allocate_copy provides a raw memory in-place allocation that does not "
522  "invoke "
523  "destructors when deallocating");
524 
525  auto const count_s = std::distance(i_begin, i_end);
526  auto const count = static_cast<size_t>(count_s);
527  DENSITY_ASSUME(static_cast<decltype(count_s)>(count) == count_s);
528 
529  auto const elements = static_cast<ValueType *>(
530  raw_allocate(sizeof(ValueType) * count, alignof(ValueType)));
531  for (auto curr = elements; i_begin != i_end; ++i_begin, ++curr)
532  new (curr) ValueType(*i_begin);
533  return elements;
534  }
535 
558  template <typename INPUT_RANGE>
559  auto raw_allocate_copy(const INPUT_RANGE & i_source_range)
560  -> decltype(std::declval<put_transaction>().raw_allocate_copy(
561  std::begin(i_source_range), std::end(i_source_range)))
562  {
563  return raw_allocate_copy(std::begin(i_source_range), std::end(i_source_range));
564  }
565 
597  progress_guarantee i_progress_guarantee, size_t i_size, size_t i_alignment) noexcept
598  {
599  DENSITY_ASSERT(!empty());
600  auto push_data = m_queue->try_inplace_allocate(
601  i_progress_guarantee, detail::LfQueue_Dead, false, i_size, i_alignment);
602  return push_data.m_user_storage;
603  }
604 
638  template <typename INPUT_ITERATOR>
639  typename std::iterator_traits<INPUT_ITERATOR>::value_type * try_raw_allocate_copy(
640  progress_guarantee i_progress_guarantee,
641  INPUT_ITERATOR i_begin,
642  INPUT_ITERATOR
643  i_end) noexcept(std::
644  is_nothrow_copy_constructible<typename std::iterator_traits<
645  INPUT_ITERATOR>::value_type>::value)
646  {
647  using ValueType = typename std::iterator_traits<INPUT_ITERATOR>::value_type;
648  static_assert(
649  std::is_trivially_destructible<ValueType>::value,
650  "raw_allocate_copy provides a raw memory in-place allocation that does not "
651  "invoke "
652  "destructors when deallocating");
653 
654  auto const count_s = std::distance(i_begin, i_end);
655  auto const count = static_cast<size_t>(count_s);
656  DENSITY_ASSUME(static_cast<decltype(count_s)>(count) == count_s);
657 
658  auto const elements = static_cast<ValueType *>(try_raw_allocate(
659  i_progress_guarantee, sizeof(ValueType) * count, alignof(ValueType)));
660  if (elements != nullptr)
661  {
662  for (auto curr = elements; i_begin != i_end; ++i_begin, ++curr)
663  new (curr) ValueType(*i_begin);
664  }
665  return elements;
666  }
667 
699  template <typename INPUT_RANGE>
701  progress_guarantee i_progress_guarantee,
702  const INPUT_RANGE & i_source_range) noexcept(noexcept(std::declval<put_transaction>()
703  .try_raw_allocate_copy(
704  i_progress_guarantee,
705  std::begin(i_source_range),
706  std::end(i_source_range))))
707  -> decltype(std::declval<put_transaction>().try_raw_allocate_copy(
708  i_progress_guarantee, std::begin(i_source_range), std::end(i_source_range)))
709  {
710  return try_raw_allocate_copy(
711  i_progress_guarantee, std::begin(i_source_range), std::end(i_source_range));
712  }
713 
722  void commit() noexcept
723  {
724  DENSITY_ASSERT(!empty());
725  Base::commit_put_impl(m_put);
726  m_put.m_user_storage = nullptr;
727  }
728 
739  void cancel() noexcept
740  {
741  DENSITY_ASSERT(!empty());
742  Base::cancel_put_impl(m_put);
743  m_put.m_user_storage = nullptr;
744  }
745 
749  bool empty() const noexcept { return m_put.m_user_storage == nullptr; }
750 
754  explicit operator bool() const noexcept { return m_put.m_user_storage != nullptr; }
755 
759  lf_heter_queue * queue() const noexcept
760  {
761  return m_put.m_user_storage != nullptr ? m_queue : nullptr;
762  }
763 
775  void * element_ptr() const noexcept
776  {
777  DENSITY_ASSERT(!empty());
778  return m_put.m_user_storage;
779  }
780 
794 #ifndef DOXYGEN_DOC_GENERATION
795  template <
796  typename EL = ELEMENT_COMPLETE_TYPE,
797  typename std::enable_if<!std::is_void<EL>::value>::type * = nullptr>
798  EL &
799 #else
800  ELEMENT_COMPLETE_TYPE &
801 #endif
802  element() const noexcept
803  {
804  return *static_cast<ELEMENT_COMPLETE_TYPE *>(element_ptr());
805  }
806 
813  const RUNTIME_TYPE & complete_type() const noexcept
814  {
815  DENSITY_ASSERT(!empty());
816  return *Base::type_after_control(m_put.m_control_block);
817  }
818 
823  {
824  if (m_put.m_user_storage != nullptr)
825  {
826  Base::cancel_put_impl(m_put);
827  }
828  }
829 
832  PrivateType, lf_heter_queue * i_queue, const Allocation & i_put) noexcept
833  : m_put(i_put), m_queue(i_queue)
834  {
835  }
836 
837  private:
838  Allocation m_put;
839  lf_heter_queue * m_queue;
840  template <typename OTHERTYPE> friend class put_transaction;
841  };
842 
861  {
862  public:
866  consume_operation() noexcept = default;
867 
871  consume_operation(const consume_operation &) = delete;
872 
876  consume_operation & operator=(const consume_operation &) = delete;
877 
881  consume_operation(consume_operation && i_source) noexcept = default;
882 
886  consume_operation & operator=(consume_operation && i_source) noexcept = default;
887 
892  {
893  if (!m_consume_data.empty())
894  {
895  m_consume_data.cancel_consume_impl();
896  }
897  }
898 
902  friend void swap(consume_operation & i_first, consume_operation & i_second) noexcept
903  {
904  i_first.m_consume_data.swap(i_second.m_consume_data);
905  }
906 
910  bool empty() const noexcept { return m_consume_data.empty(); }
911 
915  explicit operator bool() const noexcept { return !m_consume_data.empty(); }
916 
920  lf_heter_queue * queue() const noexcept
921  {
922  return static_cast<lf_heter_queue *>(m_consume_data.m_queue);
923  }
924 
933  void commit() noexcept
934  {
935  DENSITY_ASSERT(!empty());
936 
937  auto const & type = complete_type();
938  auto const element = element_ptr();
939  type.destroy(element);
940 
941  type.RUNTIME_TYPE::~RUNTIME_TYPE();
942 
943  m_consume_data.commit_consume_impl();
944  }
945 
963  void commit_nodestroy() noexcept
964  {
965  DENSITY_ASSERT(!empty());
966 
967  bool destroy_type = !std::is_trivially_destructible<RUNTIME_TYPE>::value;
968  if (destroy_type)
969  {
970  auto const & type = complete_type();
971  type.RUNTIME_TYPE::~RUNTIME_TYPE();
972  }
973 
974  m_consume_data.commit_consume_impl();
975  }
976 
987  void cancel() noexcept
988  {
989  DENSITY_ASSERT(!empty());
990  m_consume_data.cancel_consume_impl();
991  }
992 
998  const RUNTIME_TYPE & complete_type() const noexcept
999  {
1000  DENSITY_ASSERT(!empty());
1001  return *Base::type_after_control(m_consume_data.m_control);
1002  }
1003 
1011  void * unaligned_element_ptr() const noexcept
1012  {
1013  DENSITY_ASSERT(!empty());
1014  return Base::get_unaligned_element(
1015  m_consume_data.m_control, m_consume_data.external());
1016  }
1017 
1025  void * element_ptr() const noexcept
1026  {
1027  DENSITY_ASSERT(!empty());
1028  return Base::get_element(m_consume_data.m_control, m_consume_data.external());
1029  }
1030 
1037  template <typename COMPLETE_ELEMENT_TYPE>
1038  COMPLETE_ELEMENT_TYPE & element() const noexcept
1039  {
1040  DENSITY_ASSERT(!empty() && complete_type().template is<COMPLETE_ELEMENT_TYPE>());
1041  return *static_cast<COMPLETE_ELEMENT_TYPE *>(
1042  Base::get_element(m_consume_data.m_control, m_consume_data.external()));
1043  }
1044 
1046  consume_operation(PrivateType, lf_heter_queue * i_queue) noexcept
1047  {
1048  m_consume_data.start_consume_impl(i_queue);
1049  }
1050 
1052  bool start_consume_impl(PrivateType, lf_heter_queue * i_queue)
1053  {
1054  if (!m_consume_data.empty())
1055  {
1056  m_consume_data.cancel_consume_impl();
1057  }
1058 
1059  m_consume_data.start_consume_impl(i_queue);
1060 
1061  return !m_consume_data.empty();
1062  }
1063 
1064  private:
1065  Consume m_consume_data;
1066  };
1067 
1085  template <typename ELEMENT_TYPE> void push(ELEMENT_TYPE && i_source)
1086  {
1087  return emplace<typename std::decay<ELEMENT_TYPE>::type>(
1088  std::forward<ELEMENT_TYPE>(i_source));
1089  }
1090 
1107  template <typename ELEMENT_TYPE, typename... CONSTRUCTION_PARAMS>
1108  void emplace(CONSTRUCTION_PARAMS &&... i_construction_params)
1109  {
1110  start_emplace<ELEMENT_TYPE>(std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...)
1111  .commit();
1112  }
1113 
1130  void dyn_push(const runtime_type & i_type) { start_dyn_push(i_type).commit(); }
1131 
1150  void dyn_push_copy(const runtime_type & i_type, const void * i_source)
1151  {
1152  start_dyn_push_copy(i_type, i_source).commit();
1153  }
1154 
1173  void dyn_push_move(const runtime_type & i_type, void * i_source)
1174  {
1175  start_dyn_push_move(i_type, i_source).commit();
1176  }
1177 
1202  template <typename ELEMENT_TYPE>
1203  put_transaction<typename std::decay<ELEMENT_TYPE>::type>
1204  start_push(ELEMENT_TYPE && i_source)
1205  {
1206  return start_emplace<typename std::decay<ELEMENT_TYPE>::type>(
1207  std::forward<ELEMENT_TYPE>(i_source));
1208  }
1209 
1232  template <typename ELEMENT_TYPE, typename... CONSTRUCTION_PARAMS>
1233  put_transaction<ELEMENT_TYPE> start_emplace(CONSTRUCTION_PARAMS &&... i_construction_params)
1234  {
1235  auto push_data = Base::template try_inplace_allocate_impl<
1236  detail::LfQueue_Throwing,
1237  detail::LfQueue_Busy,
1238  true,
1239  detail::size_of<ELEMENT_TYPE>::value,
1240  alignof(ELEMENT_TYPE)>();
1241 
1242  runtime_type * type = nullptr;
1243  try
1244  {
1245  auto const type_storage = Base::type_after_control(push_data.m_control_block);
1246  DENSITY_ASSUME(type_storage != nullptr);
1247  type = new (type_storage) runtime_type(runtime_type::template make<ELEMENT_TYPE>());
1248 
1249  DENSITY_ASSUME(push_data.m_user_storage != nullptr);
1250  new (push_data.m_user_storage)
1251  ELEMENT_TYPE(std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...);
1252  }
1253  catch (...)
1254  {
1255  if (type != nullptr)
1256  type->RUNTIME_TYPE::~RUNTIME_TYPE();
1257 
1258  Base::cancel_put_nodestroy_impl(push_data);
1259  throw;
1260  }
1261 
1262  return put_transaction<ELEMENT_TYPE>(PrivateType(), this, push_data);
1263  }
1264 
1283  put_transaction<> start_dyn_push(const runtime_type & i_type)
1284  {
1285  auto push_data = Base::template try_inplace_allocate_impl<detail::LfQueue_Throwing>(
1286  detail::LfQueue_Busy, true, i_type.size(), i_type.alignment());
1287 
1288  runtime_type * type = nullptr;
1289  try
1290  {
1291  auto const type_storage = Base::type_after_control(push_data.m_control_block);
1292  DENSITY_ASSUME(type_storage != nullptr);
1293  type = new (type_storage) runtime_type(i_type);
1294 
1295  DENSITY_ASSUME(push_data.m_user_storage != nullptr);
1296  i_type.default_construct(push_data.m_user_storage);
1297  }
1298  catch (...)
1299  {
1300  if (type != nullptr)
1301  type->RUNTIME_TYPE::~RUNTIME_TYPE();
1302 
1303  Base::cancel_put_nodestroy_impl(push_data);
1304  throw;
1305  }
1306 
1307  return put_transaction<void>(PrivateType(), this, push_data);
1308  }
1309 
1310 
1331  put_transaction<> start_dyn_push_copy(const runtime_type & i_type, const void * i_source)
1332  {
1333  auto push_data = Base::template try_inplace_allocate_impl<detail::LfQueue_Throwing>(
1334  detail::LfQueue_Busy, true, i_type.size(), i_type.alignment());
1335 
1336  runtime_type * type = nullptr;
1337  try
1338  {
1339  auto const type_storage = Base::type_after_control(push_data.m_control_block);
1340  DENSITY_ASSUME(type_storage != nullptr);
1341  type = new (type_storage) runtime_type(i_type);
1342 
1343  DENSITY_ASSUME(push_data.m_user_storage != nullptr);
1344  i_type.copy_construct(push_data.m_user_storage, i_source);
1345  }
1346  catch (...)
1347  {
1348  if (type != nullptr)
1349  type->RUNTIME_TYPE::~RUNTIME_TYPE();
1350  Base::cancel_put_nodestroy_impl(push_data);
1351  throw;
1352  }
1353 
1354  return put_transaction<void>(PrivateType(), this, push_data);
1355  }
1356 
1377  put_transaction<> start_dyn_push_move(const runtime_type & i_type, void * i_source)
1378  {
1379  auto push_data = Base::template try_inplace_allocate_impl<detail::LfQueue_Throwing>(
1380  detail::LfQueue_Busy, true, i_type.size(), i_type.alignment());
1381  ;
1382  runtime_type * type = nullptr;
1383  try
1384  {
1385  auto const type_storage = Base::type_after_control(push_data.m_control_block);
1386  DENSITY_ASSUME(type_storage != nullptr);
1387  type = new (type_storage) runtime_type(i_type);
1388 
1389  DENSITY_ASSUME(push_data.m_user_storage != nullptr);
1390  i_type.move_construct(push_data.m_user_storage, i_source);
1391  }
1392  catch (...)
1393  {
1394  if (type != nullptr)
1395  type->RUNTIME_TYPE::~RUNTIME_TYPE();
1396  Base::cancel_put_nodestroy_impl(push_data);
1397  throw;
1398  }
1399 
1400  return put_transaction<void>(PrivateType(), this, push_data);
1401  }
1402 
1429  template <typename ELEMENT_TYPE>
1430  bool try_push(progress_guarantee i_progress_guarantee, ELEMENT_TYPE && i_source) noexcept(
1431  noexcept(std::declval<lf_heter_queue>()
1432  .template try_emplace<typename std::decay<ELEMENT_TYPE>::type>(
1433  i_progress_guarantee, std::forward<ELEMENT_TYPE>(i_source))))
1434  {
1435  return try_emplace<typename std::decay<ELEMENT_TYPE>::type>(
1436  i_progress_guarantee, std::forward<ELEMENT_TYPE>(i_source));
1437  }
1438 
1464  template <typename ELEMENT_TYPE, typename... CONSTRUCTION_PARAMS>
1465  bool
1466  try_emplace(progress_guarantee i_progress_guarantee, CONSTRUCTION_PARAMS &&... i_construction_params) noexcept(
1467  noexcept(std::declval<lf_heter_queue>().template try_start_emplace<ELEMENT_TYPE>(
1468  i_progress_guarantee, std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...)))
1469  {
1470  auto tranasction = try_start_emplace<ELEMENT_TYPE>(
1471  i_progress_guarantee, std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...);
1472  if (!tranasction)
1473  return false;
1474  tranasction.commit();
1475  return true;
1476  }
1477 
1502  bool try_dyn_push(progress_guarantee i_progress_guarantee, const runtime_type & i_type)
1503  {
1504  auto tranasction = try_start_dyn_push(i_progress_guarantee, i_type);
1505  if (!tranasction)
1506  return false;
1507  tranasction.commit();
1508  return true;
1509  }
1510 
1538  progress_guarantee i_progress_guarantee,
1539  const runtime_type & i_type,
1540  const void * i_source)
1541  {
1542  auto tranasction = try_start_dyn_push_copy(i_progress_guarantee, i_type, i_source);
1543  if (!tranasction)
1544  return false;
1545  tranasction.commit();
1546  return true;
1547  }
1548 
1576  progress_guarantee i_progress_guarantee, const runtime_type & i_type, void * i_source)
1577  {
1578  auto tranasction = try_start_dyn_push_move(i_progress_guarantee, i_type, i_source);
1579  if (!tranasction)
1580  return false;
1581  tranasction.commit();
1582  return true;
1583  }
1584 
1617  template <typename ELEMENT_TYPE>
1618  put_transaction<typename std::decay<ELEMENT_TYPE>::type> try_start_push(
1619  progress_guarantee i_progress_guarantee,
1620  ELEMENT_TYPE && i_source) noexcept(noexcept(std::declval<lf_heter_queue>()
1621  .template try_start_emplace<
1622  typename std::decay<ELEMENT_TYPE>::type>(
1623  i_progress_guarantee,
1624  std::forward<ELEMENT_TYPE>(i_source))))
1625  {
1626  return try_start_emplace<typename std::decay<ELEMENT_TYPE>::type>(
1627  i_progress_guarantee, std::forward<ELEMENT_TYPE>(i_source));
1628  }
1629 
1660  template <typename ELEMENT_TYPE, typename... CONSTRUCTION_PARAMS>
1661  put_transaction<ELEMENT_TYPE>
1662  try_start_emplace(progress_guarantee i_progress_guarantee, CONSTRUCTION_PARAMS &&... i_construction_params) noexcept(
1663  noexcept(ELEMENT_TYPE(std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...)) &&
1664  noexcept(runtime_type(runtime_type::template make<ELEMENT_TYPE>())))
1665  {
1666  auto push_data = Base::template try_inplace_allocate<
1667  detail::LfQueue_Busy,
1668  true,
1669  detail::size_of<ELEMENT_TYPE>::value,
1670  alignof(ELEMENT_TYPE)>(i_progress_guarantee);
1671  if (push_data.m_user_storage == nullptr)
1672  {
1673  return put_transaction<ELEMENT_TYPE>();
1674  }
1675 
1676  constexpr bool is_noexcept =
1677  std::is_nothrow_constructible<ELEMENT_TYPE, CONSTRUCTION_PARAMS...>::value &&
1678  noexcept(runtime_type(runtime_type::template make<ELEMENT_TYPE>()));
1679 
1680  runtime_type * type = nullptr;
1681 
1682  if (is_noexcept)
1683  {
1684  auto const type_storage = Base::type_after_control(push_data.m_control_block);
1685  DENSITY_ASSUME(type_storage != nullptr);
1686  type = new (type_storage) runtime_type(runtime_type::template make<ELEMENT_TYPE>());
1687 
1688  DENSITY_ASSUME(push_data.m_user_storage != nullptr);
1689  new (push_data.m_user_storage)
1690  ELEMENT_TYPE(std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...);
1691  }
1692  else
1693  {
1694  try
1695  {
1696  auto const type_storage = Base::type_after_control(push_data.m_control_block);
1697  DENSITY_ASSUME(type_storage != nullptr);
1698  type =
1699  new (type_storage) runtime_type(runtime_type::template make<ELEMENT_TYPE>());
1700 
1701  DENSITY_ASSUME(push_data.m_user_storage != nullptr);
1702  new (push_data.m_user_storage)
1703  ELEMENT_TYPE(std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...);
1704  }
1705  catch (...)
1706  {
1707  if (type != nullptr)
1708  type->RUNTIME_TYPE::~RUNTIME_TYPE();
1709 
1710  Base::cancel_put_nodestroy_impl(push_data);
1711  DENSITY_INTERNAL_RETHROW_FROM_NOEXCEPT
1712  }
1713  }
1714 
1715  return put_transaction<ELEMENT_TYPE>(PrivateType(), this, push_data);
1716  }
1717 
1744  put_transaction<>
1745  try_start_dyn_push(progress_guarantee i_progress_guarantee, const runtime_type & i_type)
1746  {
1747  auto push_data = try_inplace_allocate(
1748  i_progress_guarantee, detail::LfQueue_Busy, true, i_type.size(), i_type.alignment());
1749  if (push_data.m_user_storage == nullptr)
1750  {
1751  return put_transaction<>();
1752  }
1753 
1754  runtime_type * type = nullptr;
1755  try
1756  {
1757  auto const type_storage = Base::type_after_control(push_data.m_control_block);
1758  DENSITY_ASSUME(type_storage != nullptr);
1759  type = new (type_storage) runtime_type(i_type);
1760 
1761  DENSITY_ASSUME(push_data.m_user_storage != nullptr);
1762  i_type.default_construct(push_data.m_user_storage);
1763  }
1764  catch (...)
1765  {
1766  if (type != nullptr)
1767  type->RUNTIME_TYPE::~RUNTIME_TYPE();
1768 
1769  Base::cancel_put_nodestroy_impl(push_data);
1770  throw;
1771  }
1772 
1773  return put_transaction<void>(PrivateType(), this, push_data);
1774  }
1775 
1776 
1805  put_transaction<> try_start_dyn_push_copy(
1806  progress_guarantee i_progress_guarantee,
1807  const runtime_type & i_type,
1808  const void * i_source)
1809  {
1810  auto push_data = try_inplace_allocate(
1811  i_progress_guarantee, detail::LfQueue_Busy, true, i_type.size(), i_type.alignment());
1812  if (push_data.m_user_storage == nullptr)
1813  {
1814  return put_transaction<>();
1815  }
1816 
1817  runtime_type * type = nullptr;
1818  try
1819  {
1820  auto const type_storage = Base::type_after_control(push_data.m_control_block);
1821  DENSITY_ASSUME(type_storage != nullptr);
1822  type = new (type_storage) runtime_type(i_type);
1823 
1824  DENSITY_ASSUME(push_data.m_user_storage != nullptr);
1825  i_type.copy_construct(push_data.m_user_storage, i_source);
1826  }
1827  catch (...)
1828  {
1829  if (type != nullptr)
1830  type->RUNTIME_TYPE::~RUNTIME_TYPE();
1831  Base::cancel_put_nodestroy_impl(push_data);
1832  throw;
1833  }
1834 
1835  return put_transaction<void>(PrivateType(), this, push_data);
1836  }
1837 
1866  put_transaction<> try_start_dyn_push_move(
1867  progress_guarantee i_progress_guarantee, const runtime_type & i_type, void * i_source)
1868  {
1869  auto push_data = try_inplace_allocate(
1870  i_progress_guarantee, detail::LfQueue_Busy, true, i_type.size(), i_type.alignment());
1871  if (push_data.m_user_storage == nullptr)
1872  {
1873  return put_transaction<>();
1874  }
1875 
1876  runtime_type * type = nullptr;
1877  try
1878  {
1879  auto const type_storage = Base::type_after_control(push_data.m_control_block);
1880  DENSITY_ASSUME(type_storage != nullptr);
1881  type = new (type_storage) runtime_type(i_type);
1882 
1883  DENSITY_ASSUME(push_data.m_user_storage != nullptr);
1884  i_type.move_construct(push_data.m_user_storage, i_source);
1885  }
1886  catch (...)
1887  {
1888  if (type != nullptr)
1889  type->RUNTIME_TYPE::~RUNTIME_TYPE();
1890  Base::cancel_put_nodestroy_impl(push_data);
1891  throw;
1892  }
1893 
1894  return put_transaction<void>(PrivateType(), this, push_data);
1895  }
1896 
1907  bool try_pop() noexcept
1908  {
1909  if (auto operation = try_start_consume())
1910  {
1911  operation.commit();
1912  return true;
1913  }
1914  return false;
1915  }
1916 
1923  consume_operation try_start_consume() noexcept
1924  {
1925  return consume_operation(PrivateType(), this);
1926  }
1927 
1941  bool try_start_consume(consume_operation & i_consume) noexcept
1942  {
1943  return i_consume.start_consume_impl(PrivateType(), this);
1944  }
1945 
1946 
1968  template <typename ELEMENT_COMPLETE_TYPE = void> class reentrant_put_transaction
1969  {
1970  static_assert(
1971  std::is_same<
1972  ELEMENT_COMPLETE_TYPE,
1973  typename std::decay<ELEMENT_COMPLETE_TYPE>::type>::value,
1974  "");
1975 
1976  public:
1978  reentrant_put_transaction() noexcept = default;
1979 
1984 
1989 
1997  template <
1998  typename OTHERTYPE,
1999  typename = typename std::enable_if<
2000  std::is_same<OTHERTYPE, ELEMENT_COMPLETE_TYPE>::value ||
2001  std::is_void<ELEMENT_COMPLETE_TYPE>::value>::type>
2003  : m_put(i_source.m_put), m_queue(i_source.m_queue)
2004  {
2005  i_source.m_put.m_user_storage = nullptr;
2006  }
2007 
2013  template <
2014  typename OTHERTYPE,
2015  typename = typename std::enable_if<
2016  std::is_same<OTHERTYPE, ELEMENT_COMPLETE_TYPE>::value ||
2017  std::is_void<ELEMENT_COMPLETE_TYPE>::value>::type>
2020  {
2021  using std::swap;
2022  swap(m_put, i_source.m_put);
2023  swap(m_queue, i_source.m_queue);
2024  return *this;
2025  }
2026 
2030  friend void swap(
2031  reentrant_put_transaction & i_first, reentrant_put_transaction & i_second) noexcept
2032  {
2033  using std::swap;
2034  swap(i_first.m_put, i_second.m_put);
2035  swap(i_first.m_queue, i_second.m_queue);
2036  }
2037 
2060  void * raw_allocate(size_t i_size, size_t i_alignment)
2061  {
2062  DENSITY_ASSERT(!empty());
2063  auto push_data =
2064  m_queue->template try_inplace_allocate_impl<detail::LfQueue_Throwing>(
2065  detail::LfQueue_Dead, false, i_size, i_alignment);
2066  return push_data.m_user_storage;
2067  }
2068 
2093  template <typename INPUT_ITERATOR>
2094  typename std::iterator_traits<INPUT_ITERATOR>::value_type *
2095  raw_allocate_copy(INPUT_ITERATOR i_begin, INPUT_ITERATOR i_end)
2096  {
2097  using ValueType = typename std::iterator_traits<INPUT_ITERATOR>::value_type;
2098  static_assert(
2099  std::is_trivially_destructible<ValueType>::value,
2100  "raw_allocate_copy provides a raw memory in-place allocation that does not "
2101  "invoke "
2102  "destructors when deallocating");
2103 
2104  auto const count_s = std::distance(i_begin, i_end);
2105  auto const count = static_cast<size_t>(count_s);
2106  DENSITY_ASSUME(static_cast<decltype(count_s)>(count) == count_s);
2107 
2108  auto const elements = static_cast<ValueType *>(
2109  raw_allocate(sizeof(ValueType) * count, alignof(ValueType)));
2110  for (auto curr = elements; i_begin != i_end; ++i_begin, ++curr)
2111  new (curr) ValueType(*i_begin);
2112  return elements;
2113  }
2114 
2137  template <typename INPUT_RANGE>
2138  auto raw_allocate_copy(const INPUT_RANGE & i_source_range)
2139  -> decltype(std::declval<reentrant_put_transaction>().raw_allocate_copy(
2140  std::begin(i_source_range), std::end(i_source_range)))
2141  {
2142  return raw_allocate_copy(std::begin(i_source_range), std::end(i_source_range));
2143  }
2144 
2176  progress_guarantee i_progress_guarantee, size_t i_size, size_t i_alignment) noexcept
2177  {
2178  DENSITY_ASSERT(!empty());
2179  auto push_data = m_queue->try_inplace_allocate(
2180  i_progress_guarantee, detail::LfQueue_Dead, false, i_size, i_alignment);
2181  return push_data.m_user_storage;
2182  }
2183 
2217  template <typename INPUT_ITERATOR>
2218  typename std::iterator_traits<INPUT_ITERATOR>::value_type * try_raw_allocate_copy(
2219  progress_guarantee i_progress_guarantee,
2220  INPUT_ITERATOR i_begin,
2221  INPUT_ITERATOR
2222  i_end) noexcept(std::
2223  is_nothrow_copy_constructible<typename std::iterator_traits<
2224  INPUT_ITERATOR>::value_type>::value)
2225  {
2226  using ValueType = typename std::iterator_traits<INPUT_ITERATOR>::value_type;
2227  static_assert(
2228  std::is_trivially_destructible<ValueType>::value,
2229  "raw_allocate_copy provides a raw memory in-place allocation that does not "
2230  "invoke "
2231  "destructors when deallocating");
2232 
2233  auto const count_s = std::distance(i_begin, i_end);
2234  auto const count = static_cast<size_t>(count_s);
2235  DENSITY_ASSUME(static_cast<decltype(count_s)>(count) == count_s);
2236 
2237  auto const elements = static_cast<ValueType *>(try_raw_allocate(
2238  i_progress_guarantee, sizeof(ValueType) * count, alignof(ValueType)));
2239  if (elements != nullptr)
2240  {
2241  for (auto curr = elements; i_begin != i_end; ++i_begin, ++curr)
2242  new (curr) ValueType(*i_begin);
2243  }
2244  return elements;
2245  }
2246 
2278  template <typename INPUT_RANGE>
2280  progress_guarantee i_progress_guarantee,
2281  const INPUT_RANGE &
2282  i_source_range) noexcept(noexcept(std::declval<reentrant_put_transaction>()
2283  .try_raw_allocate_copy(
2284  i_progress_guarantee,
2285  std::begin(i_source_range),
2286  std::end(i_source_range))))
2287  -> decltype(std::declval<reentrant_put_transaction>().try_raw_allocate_copy(
2288  i_progress_guarantee, std::begin(i_source_range), std::end(i_source_range)))
2289  {
2290  return try_raw_allocate_copy(
2291  i_progress_guarantee, std::begin(i_source_range), std::end(i_source_range));
2292  }
2293 
2302  void commit() noexcept
2303  {
2304  DENSITY_ASSERT(!empty());
2305  Base::commit_put_impl(m_put);
2306  m_put.m_user_storage = nullptr;
2307  }
2308 
2319  void cancel() noexcept
2320  {
2321  DENSITY_ASSERT(!empty());
2322  Base::cancel_put_impl(m_put);
2323  m_put.m_user_storage = nullptr;
2324  }
2325 
2329  bool empty() const noexcept { return m_put.m_user_storage == nullptr; }
2330 
2334  explicit operator bool() const noexcept { return m_put.m_user_storage != nullptr; }
2335 
2339  lf_heter_queue * queue() const noexcept
2340  {
2341  return m_put.m_user_storage != nullptr ? m_queue : nullptr;
2342  }
2343 
2355  void * element_ptr() const noexcept
2356  {
2357  DENSITY_ASSERT(!empty());
2358  return m_put.m_user_storage;
2359  }
2360 
2374 #ifndef DOXYGEN_DOC_GENERATION
2375  template <
2376  typename EL = ELEMENT_COMPLETE_TYPE,
2377  typename std::enable_if<!std::is_void<EL>::value>::type * = nullptr>
2378  EL &
2379 #else
2380  ELEMENT_COMPLETE_TYPE &
2381 #endif
2382  element() const noexcept
2383  {
2384  return *static_cast<ELEMENT_COMPLETE_TYPE *>(element_ptr());
2385  }
2386 
2393  const RUNTIME_TYPE & complete_type() const noexcept
2394  {
2395  DENSITY_ASSERT(!empty());
2396  return *Base::type_after_control(m_put.m_control_block);
2397  }
2398 
2403  {
2404  if (m_put.m_user_storage != nullptr)
2405  {
2406  Base::cancel_put_impl(m_put);
2407  }
2408  }
2409 
2412  PrivateType, lf_heter_queue * i_queue, const Allocation & i_put) noexcept
2413  : m_put(i_put), m_queue(i_queue)
2414  {
2415  }
2416 
2417  private:
2418  Allocation m_put;
2419  lf_heter_queue * m_queue = nullptr;
2420  template <typename OTHERTYPE> friend class reentrant_put_transaction;
2421  };
2422 
2423 
2441  {
2442  public:
2446  reentrant_consume_operation() noexcept = default;
2447 
2452 
2457 
2461  reentrant_consume_operation(reentrant_consume_operation && i_source) noexcept = default;
2462 
2467  operator=(reentrant_consume_operation && i_source) noexcept = default;
2468 
2473  {
2474  if (!m_consume_data.empty())
2475  {
2476  m_consume_data.cancel_consume_impl();
2477  }
2478  }
2479 
2483  friend void swap(
2484  reentrant_consume_operation & i_first,
2485  reentrant_consume_operation & i_second) noexcept
2486  {
2487  i_first.m_consume_data.swap(i_second.m_consume_data);
2488  }
2489 
2493  bool empty() const noexcept { return m_consume_data.empty(); }
2494 
2498  explicit operator bool() const noexcept { return !m_consume_data.empty(); }
2499 
2503  lf_heter_queue * queue() const noexcept
2504  {
2505  return static_cast<lf_heter_queue *>(m_consume_data.m_queue);
2506  }
2507 
2516  void commit() noexcept
2517  {
2518  DENSITY_ASSERT(!empty());
2519 
2520  auto const & type = complete_type();
2521  auto const element = element_ptr();
2522  type.destroy(element);
2523 
2524  type.RUNTIME_TYPE::~RUNTIME_TYPE();
2525 
2526  m_consume_data.commit_consume_impl();
2527  }
2528 
2546  void commit_nodestroy() noexcept
2547  {
2548  DENSITY_ASSERT(!empty());
2549 
2550  bool destroy_type = !std::is_trivially_destructible<RUNTIME_TYPE>::value;
2551  if (destroy_type)
2552  {
2553  auto const & type = complete_type();
2554  type.RUNTIME_TYPE::~RUNTIME_TYPE();
2555  }
2556 
2557  m_consume_data.commit_consume_impl();
2558  }
2559 
2570  void cancel() noexcept
2571  {
2572  DENSITY_ASSERT(!empty());
2573  m_consume_data.cancel_consume_impl();
2574  }
2575 
2581  const RUNTIME_TYPE & complete_type() const noexcept
2582  {
2583  DENSITY_ASSERT(!empty());
2584  return *Base::type_after_control(m_consume_data.m_control);
2585  }
2586 
2594  void * unaligned_element_ptr() const noexcept
2595  {
2596  DENSITY_ASSERT(!empty());
2597  return Base::get_unaligned_element(
2598  m_consume_data.m_control, m_consume_data.external());
2599  }
2600 
2608  void * element_ptr() const noexcept
2609  {
2610  DENSITY_ASSERT(!empty());
2611  return Base::get_element(m_consume_data.m_control, m_consume_data.external());
2612  }
2613 
2620  template <typename COMPLETE_ELEMENT_TYPE>
2621  COMPLETE_ELEMENT_TYPE & element() const noexcept
2622  {
2623  DENSITY_ASSERT(!empty() && complete_type().template is<COMPLETE_ELEMENT_TYPE>());
2624  return *static_cast<COMPLETE_ELEMENT_TYPE *>(
2625  Base::get_element(m_consume_data.m_control, m_consume_data.external()));
2626  }
2627 
2629  reentrant_consume_operation(PrivateType, lf_heter_queue * i_queue) noexcept
2630  {
2631  m_consume_data.start_consume_impl(i_queue);
2632  }
2633 
2635  bool start_consume_impl(PrivateType, lf_heter_queue * i_queue)
2636  {
2637  if (!m_consume_data.empty())
2638  {
2639  m_consume_data.cancel_consume_impl();
2640  }
2641 
2642  m_consume_data.start_consume_impl(i_queue);
2643 
2644  return !m_consume_data.empty();
2645  }
2646 
2647  private:
2648  Consume m_consume_data;
2649  };
2650 
2656  template <typename ELEMENT_TYPE> void reentrant_push(ELEMENT_TYPE && i_source)
2657  {
2658  return reentrant_emplace<typename std::decay<ELEMENT_TYPE>::type>(
2659  std::forward<ELEMENT_TYPE>(i_source));
2660  }
2661 
2667  template <typename ELEMENT_TYPE, typename... CONSTRUCTION_PARAMS>
2668  void reentrant_emplace(CONSTRUCTION_PARAMS &&... i_construction_params)
2669  {
2670  start_reentrant_emplace<ELEMENT_TYPE>(
2671  std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...)
2672  .commit();
2673  }
2674 
2680  void reentrant_dyn_push(const runtime_type & i_type)
2681  {
2682  start_reentrant_dyn_push(i_type).commit();
2683  }
2684 
2690  void reentrant_dyn_push_copy(const runtime_type & i_type, const void * i_source)
2691  {
2692  start_reentrant_dyn_push_copy(i_type, i_source).commit();
2693  }
2694 
2700  void reentrant_dyn_push_move(const runtime_type & i_type, void * i_source)
2701  {
2702  start_reentrant_dyn_push_move(i_type, i_source).commit();
2703  }
2704 
2710  template <typename ELEMENT_TYPE>
2711  reentrant_put_transaction<typename std::decay<ELEMENT_TYPE>::type>
2712  start_reentrant_push(ELEMENT_TYPE && i_source)
2713  {
2714  return start_reentrant_emplace<typename std::decay<ELEMENT_TYPE>::type>(
2715  std::forward<ELEMENT_TYPE>(i_source));
2716  }
2717 
2723  template <typename ELEMENT_TYPE, typename... CONSTRUCTION_PARAMS>
2724  reentrant_put_transaction<ELEMENT_TYPE>
2725  start_reentrant_emplace(CONSTRUCTION_PARAMS &&... i_construction_params)
2726  {
2727  auto push_data = Base::template try_inplace_allocate_impl<
2728  detail::LfQueue_Throwing,
2729  detail::LfQueue_Busy,
2730  true,
2731  detail::size_of<ELEMENT_TYPE>::value,
2732  alignof(ELEMENT_TYPE)>();
2733 
2734  runtime_type * type = nullptr;
2735  try
2736  {
2737  auto const type_storage = Base::type_after_control(push_data.m_control_block);
2738  DENSITY_ASSUME(type_storage != nullptr);
2739  type = new (type_storage) runtime_type(runtime_type::template make<ELEMENT_TYPE>());
2740 
2741  DENSITY_ASSUME(push_data.m_user_storage != nullptr);
2742  new (push_data.m_user_storage)
2743  ELEMENT_TYPE(std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...);
2744  }
2745  catch (...)
2746  {
2747  if (type != nullptr)
2748  type->RUNTIME_TYPE::~RUNTIME_TYPE();
2749  Base::cancel_put_nodestroy_impl(push_data);
2750  throw;
2751  }
2752 
2753  return reentrant_put_transaction<ELEMENT_TYPE>(PrivateType(), this, push_data);
2754  }
2755 
2761  reentrant_put_transaction<> start_reentrant_dyn_push(const runtime_type & i_type)
2762  {
2763  auto push_data = Base::template try_inplace_allocate_impl<detail::LfQueue_Throwing>(
2764  detail::LfQueue_Busy, true, i_type.size(), i_type.alignment());
2765 
2766  runtime_type * type = nullptr;
2767  try
2768  {
2769  auto const type_storage = Base::type_after_control(push_data.m_control_block);
2770  DENSITY_ASSUME(type_storage != nullptr);
2771  type = new (type_storage) runtime_type(i_type);
2772 
2773  DENSITY_ASSUME(push_data.m_user_storage != nullptr);
2774  i_type.default_construct(push_data.m_user_storage);
2775  }
2776  catch (...)
2777  {
2778  if (type != nullptr)
2779  type->RUNTIME_TYPE::~RUNTIME_TYPE();
2780  Base::cancel_put_nodestroy_impl(push_data);
2781  throw;
2782  }
2783 
2784  return reentrant_put_transaction<void>(PrivateType(), this, push_data);
2785  }
2786 
2792  reentrant_put_transaction<>
2793  start_reentrant_dyn_push_copy(const runtime_type & i_type, const void * i_source)
2794  {
2795  auto push_data = Base::template try_inplace_allocate_impl<detail::LfQueue_Throwing>(
2796  detail::LfQueue_Busy, true, i_type.size(), i_type.alignment());
2797 
2798  runtime_type * type = nullptr;
2799  try
2800  {
2801  auto const type_storage = Base::type_after_control(push_data.m_control_block);
2802  DENSITY_ASSUME(type_storage != nullptr);
2803  type = new (type_storage) runtime_type(i_type);
2804 
2805  DENSITY_ASSUME(push_data.m_user_storage != nullptr);
2806  i_type.copy_construct(push_data.m_user_storage, i_source);
2807  }
2808  catch (...)
2809  {
2810  if (type != nullptr)
2811  type->RUNTIME_TYPE::~RUNTIME_TYPE();
2812  Base::cancel_put_nodestroy_impl(push_data);
2813  throw;
2814  }
2815 
2816  return reentrant_put_transaction<void>(PrivateType(), this, push_data);
2817  }
2818 
2824  reentrant_put_transaction<>
2825  start_reentrant_dyn_push_move(const runtime_type & i_type, void * i_source)
2826  {
2827  auto push_data = Base::template try_inplace_allocate_impl<detail::LfQueue_Throwing>(
2828  detail::LfQueue_Busy, true, i_type.size(), i_type.alignment());
2829 
2830  runtime_type * type = nullptr;
2831  try
2832  {
2833  auto const type_storage = Base::type_after_control(push_data.m_control_block);
2834  DENSITY_ASSUME(type_storage != nullptr);
2835  type = new (type_storage) runtime_type(i_type);
2836 
2837  DENSITY_ASSUME(push_data.m_user_storage != nullptr);
2838  i_type.move_construct(push_data.m_user_storage, i_source);
2839  }
2840  catch (...)
2841  {
2842  if (type != nullptr)
2843  type->RUNTIME_TYPE::~RUNTIME_TYPE();
2844  Base::cancel_put_nodestroy_impl(push_data);
2845  throw;
2846  }
2847 
2848  return reentrant_put_transaction<void>(PrivateType(), this, push_data);
2849  }
2850 
2856  template <typename ELEMENT_TYPE>
2858  progress_guarantee i_progress_guarantee,
2859  ELEMENT_TYPE && i_source) noexcept(noexcept(std::declval<lf_heter_queue>()
2860  .template try_reentrant_emplace<
2861  typename std::decay<ELEMENT_TYPE>::type>(
2862  i_progress_guarantee,
2863  std::forward<ELEMENT_TYPE>(i_source))))
2864  {
2865  return try_reentrant_emplace<typename std::decay<ELEMENT_TYPE>::type>(
2866  i_progress_guarantee, std::forward<ELEMENT_TYPE>(i_source));
2867  }
2868 
2874  template <typename ELEMENT_TYPE, typename... CONSTRUCTION_PARAMS>
2875  bool
2876  try_reentrant_emplace(progress_guarantee i_progress_guarantee, CONSTRUCTION_PARAMS &&... i_construction_params) noexcept(
2877  noexcept(
2878  std::declval<lf_heter_queue>().template try_start_reentrant_emplace<ELEMENT_TYPE>(
2879  i_progress_guarantee, std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...)))
2880  {
2881  auto tranasction = try_start_reentrant_emplace<ELEMENT_TYPE>(
2882  i_progress_guarantee, std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...);
2883  if (!tranasction)
2884  return false;
2885  tranasction.commit();
2886  return true;
2887  }
2888 
2895  progress_guarantee i_progress_guarantee, const runtime_type & i_type)
2896  {
2897  auto tranasction = try_start_reentrant_dyn_push(i_progress_guarantee, i_type);
2898  if (!tranasction)
2899  return false;
2900  tranasction.commit();
2901  return true;
2902  }
2903 
2910  progress_guarantee i_progress_guarantee,
2911  const runtime_type & i_type,
2912  const void * i_source)
2913  {
2914  auto tranasction =
2915  try_start_reentrant_dyn_push_copy(i_progress_guarantee, i_type, i_source);
2916  if (!tranasction)
2917  return false;
2918  tranasction.commit();
2919  return true;
2920  }
2921 
2928  progress_guarantee i_progress_guarantee, const runtime_type & i_type, void * i_source)
2929  {
2930  auto tranasction =
2931  try_start_reentrant_dyn_push_move(i_progress_guarantee, i_type, i_source);
2932  if (!tranasction)
2933  return false;
2934  tranasction.commit();
2935  return true;
2936  }
2937 
2943  template <typename ELEMENT_TYPE>
2944  reentrant_put_transaction<typename std::decay<ELEMENT_TYPE>::type> try_start_reentrant_push(
2945  progress_guarantee i_progress_guarantee,
2946  ELEMENT_TYPE && i_source) noexcept(noexcept(std::declval<lf_heter_queue>()
2947  .template try_start_reentrant_emplace<
2948  typename std::decay<ELEMENT_TYPE>::type>(
2949  i_progress_guarantee,
2950  std::forward<ELEMENT_TYPE>(i_source))))
2951  {
2952  return try_start_reentrant_emplace<typename std::decay<ELEMENT_TYPE>::type>(
2953  i_progress_guarantee, std::forward<ELEMENT_TYPE>(i_source));
2954  }
2955 
2961  template <typename ELEMENT_TYPE, typename... CONSTRUCTION_PARAMS>
2962  reentrant_put_transaction<ELEMENT_TYPE>
2963  try_start_reentrant_emplace(progress_guarantee i_progress_guarantee, CONSTRUCTION_PARAMS &&... i_construction_params) noexcept(
2964  noexcept(ELEMENT_TYPE(std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...)) &&
2965  noexcept(runtime_type(runtime_type::template make<ELEMENT_TYPE>())))
2966  {
2967  auto push_data = Base::template try_inplace_allocate<
2968  detail::LfQueue_Busy,
2969  true,
2970  detail::size_of<ELEMENT_TYPE>::value,
2971  alignof(ELEMENT_TYPE)>(i_progress_guarantee);
2972  if (push_data.m_user_storage == nullptr)
2973  {
2974  return reentrant_put_transaction<ELEMENT_TYPE>();
2975  }
2976 
2977  constexpr bool is_noexcept =
2978  std::is_nothrow_constructible<ELEMENT_TYPE, CONSTRUCTION_PARAMS...>::value &&
2979  noexcept(runtime_type(runtime_type::template make<ELEMENT_TYPE>()));
2980 
2981  runtime_type * type = nullptr;
2982 
2983  if (is_noexcept)
2984  {
2985  auto const type_storage = Base::type_after_control(push_data.m_control_block);
2986  DENSITY_ASSUME(type_storage != nullptr);
2987  type = new (type_storage) runtime_type(runtime_type::template make<ELEMENT_TYPE>());
2988 
2989  DENSITY_ASSUME(push_data.m_user_storage != nullptr);
2990  new (push_data.m_user_storage)
2991  ELEMENT_TYPE(std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...);
2992  }
2993  else
2994  {
2995  try
2996  {
2997  auto const type_storage = Base::type_after_control(push_data.m_control_block);
2998  DENSITY_ASSUME(type_storage != nullptr);
2999  type =
3000  new (type_storage) runtime_type(runtime_type::template make<ELEMENT_TYPE>());
3001 
3002  DENSITY_ASSUME(push_data.m_user_storage != nullptr);
3003  new (push_data.m_user_storage)
3004  ELEMENT_TYPE(std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...);
3005  }
3006  catch (...)
3007  {
3008  if (type != nullptr)
3009  type->RUNTIME_TYPE::~RUNTIME_TYPE();
3010 
3011  Base::cancel_put_nodestroy_impl(push_data);
3012  DENSITY_INTERNAL_RETHROW_FROM_NOEXCEPT
3013  }
3014  }
3015 
3016  return reentrant_put_transaction<ELEMENT_TYPE>(PrivateType(), this, push_data);
3017  }
3018 
3024  reentrant_put_transaction<> try_start_reentrant_dyn_push(
3025  progress_guarantee i_progress_guarantee, const runtime_type & i_type)
3026  {
3027  auto push_data = try_inplace_allocate(
3028  i_progress_guarantee, detail::LfQueue_Busy, true, i_type.size(), i_type.alignment());
3029  if (push_data.m_user_storage == nullptr)
3030  {
3031  return reentrant_put_transaction<>();
3032  };
3033 
3034  runtime_type * type = nullptr;
3035  try
3036  {
3037  auto const type_storage = Base::type_after_control(push_data.m_control_block);
3038  DENSITY_ASSUME(type_storage != nullptr);
3039  type = new (type_storage) runtime_type(i_type);
3040 
3041  DENSITY_ASSUME(push_data.m_user_storage != nullptr);
3042  i_type.default_construct(push_data.m_user_storage);
3043  }
3044  catch (...)
3045  {
3046  if (type != nullptr)
3047  type->RUNTIME_TYPE::~RUNTIME_TYPE();
3048 
3049  Base::cancel_put_nodestroy_impl(push_data);
3050  throw;
3051  }
3052 
3053  return reentrant_put_transaction<void>(PrivateType(), this, push_data);
3054  }
3055 
3061  reentrant_put_transaction<> try_start_reentrant_dyn_push_copy(
3062  progress_guarantee i_progress_guarantee,
3063  const runtime_type & i_type,
3064  const void * i_source)
3065  {
3066  auto push_data = try_inplace_allocate(
3067  i_progress_guarantee, detail::LfQueue_Busy, true, i_type.size(), i_type.alignment());
3068  if (push_data.m_user_storage == nullptr)
3069  {
3070  return reentrant_put_transaction<>();
3071  }
3072 
3073  runtime_type * type = nullptr;
3074  try
3075  {
3076  auto const type_storage = Base::type_after_control(push_data.m_control_block);
3077  DENSITY_ASSUME(type_storage != nullptr);
3078  type = new (type_storage) runtime_type(i_type);
3079 
3080  DENSITY_ASSUME(push_data.m_user_storage != nullptr);
3081  i_type.copy_construct(push_data.m_user_storage, i_source);
3082  }
3083  catch (...)
3084  {
3085  if (type != nullptr)
3086  type->RUNTIME_TYPE::~RUNTIME_TYPE();
3087  Base::cancel_put_nodestroy_impl(push_data);
3088  throw;
3089  }
3090 
3091  return reentrant_put_transaction<void>(PrivateType(), this, push_data);
3092  }
3093 
3099  reentrant_put_transaction<> try_start_reentrant_dyn_push_move(
3100  progress_guarantee i_progress_guarantee, const runtime_type & i_type, void * i_source)
3101  {
3102  auto push_data = try_inplace_allocate(
3103  i_progress_guarantee, detail::LfQueue_Busy, true, i_type.size(), i_type.alignment());
3104  if (push_data.m_user_storage == nullptr)
3105  {
3106  return reentrant_put_transaction<>();
3107  }
3108 
3109  runtime_type * type = nullptr;
3110  try
3111  {
3112  auto const type_storage = Base::type_after_control(push_data.m_control_block);
3113  DENSITY_ASSUME(type_storage != nullptr);
3114  type = new (type_storage) runtime_type(i_type);
3115 
3116  DENSITY_ASSUME(push_data.m_user_storage != nullptr);
3117  i_type.move_construct(push_data.m_user_storage, i_source);
3118  }
3119  catch (...)
3120  {
3121  if (type != nullptr)
3122  type->RUNTIME_TYPE::~RUNTIME_TYPE();
3123  Base::cancel_put_nodestroy_impl(push_data);
3124  throw;
3125  }
3126 
3127  return reentrant_put_transaction<void>(PrivateType(), this, push_data);
3128  }
3129 
3141  bool try_reentrant_pop() noexcept
3142  {
3143  if (auto operation = try_start_reentrant_consume())
3144  {
3145  operation.commit();
3146  return true;
3147  }
3148  return false;
3149  }
3150 
3151 
3160  reentrant_consume_operation try_start_reentrant_consume() noexcept
3161  {
3162  return reentrant_consume_operation(PrivateType(), this);
3163  }
3164 
3180  bool try_start_reentrant_consume(reentrant_consume_operation & i_consume) noexcept
3181  {
3182  return i_consume.start_consume_impl(PrivateType(), this);
3183  }
3184  };
3185 
3186 } // namespace density
3187 
3188 #ifdef _MSC_VER
3189 #pragma warning(pop)
3190 #endif
bool empty() const noexcept
Definition: lf_heter_queue.h:910
const RUNTIME_TYPE & complete_type() const noexcept
Definition: lf_heter_queue.h:2581
const RUNTIME_TYPE & complete_type() const noexcept
Definition: lf_heter_queue.h:813
void * element_ptr() const noexcept
Definition: lf_heter_queue.h:2608
void * element_ptr() const noexcept
Definition: lf_heter_queue.h:775
bool try_reentrant_emplace(progress_guarantee i_progress_guarantee, CONSTRUCTION_PARAMS &&...i_construction_params) noexcept( noexcept( std::declval< lf_heter_queue >().template try_start_reentrant_emplace< ELEMENT_TYPE >( i_progress_guarantee, std::forward< CONSTRUCTION_PARAMS >(i_construction_params)...)))
Definition: lf_heter_queue.h:2876
Definition: density_common.h:70
put_transaction & operator=(put_transaction< OTHERTYPE > &&i_source) noexcept
Definition: lf_heter_queue.h:441
bool try_dyn_push(progress_guarantee i_progress_guarantee, const runtime_type &i_type)
Definition: lf_heter_queue.h:1502
reentrant_put_transaction & operator=(reentrant_put_transaction< OTHERTYPE > &&i_source) noexcept
Definition: lf_heter_queue.h:2019
const RUNTIME_TYPE & complete_type() const noexcept
Definition: lf_heter_queue.h:998
reentrant_consume_operation try_start_reentrant_consume() noexcept
Definition: lf_heter_queue.h:3160
basic_default_allocator< default_page_capacity > default_allocator
Definition: default_allocator.h:152
void push(ELEMENT_TYPE &&i_source)
Definition: lf_heter_queue.h:1085
void reentrant_dyn_push(const runtime_type &i_type)
Definition: lf_heter_queue.h:2680
reentrant_put_transaction< ELEMENT_TYPE > try_start_reentrant_emplace(progress_guarantee i_progress_guarantee, CONSTRUCTION_PARAMS &&...i_construction_params) noexcept( noexcept(ELEMENT_TYPE(std::forward< CONSTRUCTION_PARAMS >(i_construction_params)...))&& noexcept(runtime_type(runtime_type::template make< ELEMENT_TYPE >())))
Definition: lf_heter_queue.h:2963
void * raw_allocate(size_t i_size, size_t i_alignment)
Definition: lf_heter_queue.h:2060
concurrency_cardinality
Definition: density_common.h:56
void commit() noexcept
Definition: lf_heter_queue.h:933
Definition: conc_function_queue.h:11
void dyn_push_copy(const runtime_type &i_type, const void *i_source)
Definition: lf_heter_queue.h:1150
void reentrant_dyn_push_move(const runtime_type &i_type, void *i_source)
Definition: lf_heter_queue.h:2700
put_transaction< ELEMENT_TYPE > start_emplace(CONSTRUCTION_PARAMS &&...i_construction_params)
Definition: lf_heter_queue.h:1233
bool empty() const noexcept
Definition: lf_heter_queue.h:2493
void reentrant_emplace(CONSTRUCTION_PARAMS &&...i_construction_params)
Definition: lf_heter_queue.h:2668
put_transaction try_start_dyn_push_copy(progress_guarantee i_progress_guarantee, const runtime_type &i_type, const void *i_source)
Definition: lf_heter_queue.h:1805
void * unaligned_element_ptr() const noexcept
Definition: lf_heter_queue.h:1011
void * unaligned_element_ptr() const noexcept
Definition: lf_heter_queue.h:2594
Definition: density_common.h:60
bool try_dyn_push_move(progress_guarantee i_progress_guarantee, const runtime_type &i_type, void *i_source)
Definition: lf_heter_queue.h:1575
void * element_ptr() const noexcept
Definition: lf_heter_queue.h:1025
put_transaction try_start_dyn_push(progress_guarantee i_progress_guarantee, const runtime_type &i_type)
Definition: lf_heter_queue.h:1745
Definition: runtime_type.h:1061
bool empty() const noexcept
Definition: lf_heter_queue.h:749
bool try_start_consume(consume_operation &i_consume) noexcept
Definition: lf_heter_queue.h:1941
put_transaction start_dyn_push_copy(const runtime_type &i_type, const void *i_source)
Definition: lf_heter_queue.h:1331
void cancel() noexcept
Definition: lf_heter_queue.h:2319
friend void swap(put_transaction &i_first, put_transaction &i_second) noexcept
Definition: lf_heter_queue.h:452
void reentrant_dyn_push_copy(const runtime_type &i_type, const void *i_source)
Definition: lf_heter_queue.h:2690
void emplace(CONSTRUCTION_PARAMS &&...i_construction_params)
Definition: lf_heter_queue.h:1108
void commit() noexcept
Definition: lf_heter_queue.h:722
consume_operation try_start_consume() noexcept
Definition: lf_heter_queue.h:1923
put_transaction< typename std::decay< ELEMENT_TYPE >::type > try_start_push(progress_guarantee i_progress_guarantee, ELEMENT_TYPE &&i_source) noexcept(noexcept(std::declval< lf_heter_queue >() .template try_start_emplace< typename std::decay< ELEMENT_TYPE >::type >( i_progress_guarantee, std::forward< ELEMENT_TYPE >(i_source))))
Definition: lf_heter_queue.h:1618
put_transaction start_dyn_push_move(const runtime_type &i_type, void *i_source)
Definition: lf_heter_queue.h:1377
put_transaction< typename std::decay< ELEMENT_TYPE >::type > start_push(ELEMENT_TYPE &&i_source)
Definition: lf_heter_queue.h:1204
void * raw_allocate(size_t i_size, size_t i_alignment)
Definition: lf_heter_queue.h:481
bool empty() const noexcept
Definition: lf_heter_queue.h:352
reentrant_put_transaction< typename std::decay< ELEMENT_TYPE >::type > try_start_reentrant_push(progress_guarantee i_progress_guarantee, ELEMENT_TYPE &&i_source) noexcept(noexcept(std::declval< lf_heter_queue >() .template try_start_reentrant_emplace< typename std::decay< ELEMENT_TYPE >::type >( i_progress_guarantee, std::forward< ELEMENT_TYPE >(i_source))))
Definition: lf_heter_queue.h:2944
void * try_raw_allocate(progress_guarantee i_progress_guarantee, size_t i_size, size_t i_alignment) noexcept
Definition: lf_heter_queue.h:2175
~reentrant_consume_operation()
Definition: lf_heter_queue.h:2472
void commit() noexcept
Definition: lf_heter_queue.h:2516
std::iterator_traits< INPUT_ITERATOR >::value_type * try_raw_allocate_copy(progress_guarantee i_progress_guarantee, INPUT_ITERATOR i_begin, INPUT_ITERATOR i_end) noexcept(std:: is_nothrow_copy_constructible< typename std::iterator_traits< INPUT_ITERATOR >::value_type >::value)
Definition: lf_heter_queue.h:639
bool try_dyn_push_copy(progress_guarantee i_progress_guarantee, const runtime_type &i_type, const void *i_source)
Definition: lf_heter_queue.h:1537
void cancel() noexcept
Definition: lf_heter_queue.h:987
put_transaction< ELEMENT_TYPE > try_start_emplace(progress_guarantee i_progress_guarantee, CONSTRUCTION_PARAMS &&...i_construction_params) noexcept( noexcept(ELEMENT_TYPE(std::forward< CONSTRUCTION_PARAMS >(i_construction_params)...))&& noexcept(runtime_type(runtime_type::template make< ELEMENT_TYPE >())))
Definition: lf_heter_queue.h:1662
#define DENSITY_ASSERT(...)
Definition: density_config.h:19
~put_transaction()
Definition: lf_heter_queue.h:822
ELEMENT_COMPLETE_TYPE & element() const noexcept
Definition: lf_heter_queue.h:2382
reentrant_put_transaction(reentrant_put_transaction< OTHERTYPE > &&i_source) noexcept
Definition: lf_heter_queue.h:2002
void dyn_push_move(const runtime_type &i_type, void *i_source)
Definition: lf_heter_queue.h:1173
~consume_operation()
Definition: lf_heter_queue.h:891
bool try_reentrant_dyn_push_move(progress_guarantee i_progress_guarantee, const runtime_type &i_type, void *i_source)
Definition: lf_heter_queue.h:2927
Definition: lf_heter_queue.h:860
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: lf_heter_queue.h:559
void commit_nodestroy() noexcept
Definition: lf_heter_queue.h:963
auto try_raw_allocate_copy(progress_guarantee i_progress_guarantee, const INPUT_RANGE &i_source_range) noexcept(noexcept(std::declval< put_transaction >() .try_raw_allocate_copy( i_progress_guarantee, std::begin(i_source_range), std::end(i_source_range)))) -> decltype(std::declval< put_transaction >().try_raw_allocate_copy( i_progress_guarantee, std::begin(i_source_range), std::end(i_source_range)))
Definition: lf_heter_queue.h:700
static constexpr size_t min_alignment
Definition: lf_heter_queue.h:206
bool try_start_reentrant_consume(reentrant_consume_operation &i_consume) noexcept
Definition: lf_heter_queue.h:3180
put_transaction start_dyn_push(const runtime_type &i_type)
Definition: lf_heter_queue.h:1283
reentrant_put_transaction start_reentrant_dyn_push_copy(const runtime_type &i_type, const void *i_source)
Definition: lf_heter_queue.h:2793
void cancel() noexcept
Definition: lf_heter_queue.h:739
progress_guarantee
Definition: density_common.h:84
void commit_nodestroy() noexcept
Definition: lf_heter_queue.h:2546
static constexpr bool concurrent_puts
Definition: lf_heter_queue.h:219
bool try_emplace(progress_guarantee i_progress_guarantee, CONSTRUCTION_PARAMS &&...i_construction_params) noexcept( noexcept(std::declval< lf_heter_queue >().template try_start_emplace< ELEMENT_TYPE >( i_progress_guarantee, std::forward< CONSTRUCTION_PARAMS >(i_construction_params)...)))
Definition: lf_heter_queue.h:1466
put_transaction(put_transaction< OTHERTYPE > &&i_source) noexcept
Definition: lf_heter_queue.h:425
reentrant_put_transaction start_reentrant_dyn_push_move(const runtime_type &i_type, void *i_source)
Definition: lf_heter_queue.h:2825
reentrant_put_transaction< ELEMENT_TYPE > start_reentrant_emplace(CONSTRUCTION_PARAMS &&...i_construction_params)
Definition: lf_heter_queue.h:2725
constexpr bool is_power_of_2(size_t i_number) noexcept
Definition: density_common.h:109
constexpr lf_heter_queue(ALLOCATOR_TYPE &&i_source_allocator) noexcept
Definition: lf_heter_queue.h:272
static constexpr bool concurrent_consumes
Definition: lf_heter_queue.h:222
friend void swap(reentrant_consume_operation &i_first, reentrant_consume_operation &i_second) noexcept
Definition: lf_heter_queue.h:2483
static constexpr bool concurrent_put_consumes
Definition: lf_heter_queue.h:226
friend void swap(reentrant_put_transaction &i_first, reentrant_put_transaction &i_second) noexcept
Definition: lf_heter_queue.h:2030
Definition: lf_heter_queue.h:181
bool empty() const noexcept
Definition: lf_heter_queue.h:2329
void dyn_push(const runtime_type &i_type)
Definition: lf_heter_queue.h:1130
reentrant_put_transaction try_start_reentrant_dyn_push_move(progress_guarantee i_progress_guarantee, const runtime_type &i_type, void *i_source)
Definition: lf_heter_queue.h:3099
ELEMENT_COMPLETE_TYPE & element() const noexcept
Definition: lf_heter_queue.h:802
auto try_raw_allocate_copy(progress_guarantee i_progress_guarantee, const INPUT_RANGE &i_source_range) noexcept(noexcept(std::declval< reentrant_put_transaction >() .try_raw_allocate_copy( i_progress_guarantee, std::begin(i_source_range), std::end(i_source_range)))) -> decltype(std::declval< reentrant_put_transaction >().try_raw_allocate_copy( i_progress_guarantee, std::begin(i_source_range), std::end(i_source_range)))
Definition: lf_heter_queue.h:2279
lf_heter_queue & operator=(lf_heter_queue &&i_source) noexcept
Definition: lf_heter_queue.h:300
lf_heter_queue * queue() const noexcept
Definition: lf_heter_queue.h:759
Definition: lf_heter_queue.h:391
lf_heter_queue * queue() const noexcept
Definition: lf_heter_queue.h:920
COMPLETE_ELEMENT_TYPE & element() const noexcept
Definition: lf_heter_queue.h:1038
static constexpr bool is_seq_cst
Definition: lf_heter_queue.h:229
~lf_heter_queue()
Definition: lf_heter_queue.h:334
allocator_type get_allocator() noexcept
Definition: lf_heter_queue.h:309
lf_heter_queue * queue() const noexcept
Definition: lf_heter_queue.h:2503
reentrant_put_transaction< typename std::decay< ELEMENT_TYPE >::type > start_reentrant_push(ELEMENT_TYPE &&i_source)
Definition: lf_heter_queue.h:2712
~reentrant_put_transaction()
Definition: lf_heter_queue.h:2402
const allocator_type & get_allocator_ref() const noexcept
Definition: lf_heter_queue.h:319
void clear() noexcept
Definition: lf_heter_queue.h:361
void * try_raw_allocate(progress_guarantee i_progress_guarantee, size_t i_size, size_t i_alignment) noexcept
Definition: lf_heter_queue.h:596
reentrant_put_transaction start_reentrant_dyn_push(const runtime_type &i_type)
Definition: lf_heter_queue.h:2761
bool try_reentrant_push(progress_guarantee i_progress_guarantee, ELEMENT_TYPE &&i_source) noexcept(noexcept(std::declval< lf_heter_queue >() .template try_reentrant_emplace< typename std::decay< ELEMENT_TYPE >::type >( i_progress_guarantee, std::forward< ELEMENT_TYPE >(i_source))))
Definition: lf_heter_queue.h:2857
put_transaction try_start_dyn_push_move(progress_guarantee i_progress_guarantee, const runtime_type &i_type, void *i_source)
Definition: lf_heter_queue.h:1866
reentrant_put_transaction try_start_reentrant_dyn_push_copy(progress_guarantee i_progress_guarantee, const runtime_type &i_type, const void *i_source)
Definition: lf_heter_queue.h:3061
bool try_pop() noexcept
Definition: lf_heter_queue.h:1907
reentrant_put_transaction try_start_reentrant_dyn_push(progress_guarantee i_progress_guarantee, const runtime_type &i_type)
Definition: lf_heter_queue.h:3024
void * element_ptr() const noexcept
Definition: lf_heter_queue.h:2355
const RUNTIME_TYPE & complete_type() const noexcept
Definition: lf_heter_queue.h:2393
lf_heter_queue * queue() const noexcept
Definition: lf_heter_queue.h:2339
std::iterator_traits< INPUT_ITERATOR >::value_type * try_raw_allocate_copy(progress_guarantee i_progress_guarantee, INPUT_ITERATOR i_begin, INPUT_ITERATOR i_end) noexcept(std:: is_nothrow_copy_constructible< typename std::iterator_traits< INPUT_ITERATOR >::value_type >::value)
Definition: lf_heter_queue.h:2218
consistency_model
Definition: density_common.h:65
std::iterator_traits< INPUT_ITERATOR >::value_type * raw_allocate_copy(INPUT_ITERATOR i_begin, INPUT_ITERATOR i_end)
Definition: lf_heter_queue.h:516
COMPLETE_ELEMENT_TYPE & element() const noexcept
Definition: lf_heter_queue.h:2621
void reentrant_push(ELEMENT_TYPE &&i_source)
Definition: lf_heter_queue.h:2656
bool try_reentrant_dyn_push(progress_guarantee i_progress_guarantee, const runtime_type &i_type)
Definition: lf_heter_queue.h:2894
friend void swap(consume_operation &i_first, consume_operation &i_second) noexcept
Definition: lf_heter_queue.h:902
#define DENSITY_ASSUME(bool_expr,...)
Definition: density_config.h:46
friend void swap(lf_heter_queue &i_first, lf_heter_queue &i_second) noexcept
Definition: lf_heter_queue.h:324
bool try_push(progress_guarantee i_progress_guarantee, ELEMENT_TYPE &&i_source) noexcept( noexcept(std::declval< lf_heter_queue >() .template try_emplace< typename std::decay< ELEMENT_TYPE >::type >( i_progress_guarantee, std::forward< ELEMENT_TYPE >(i_source))))
Definition: lf_heter_queue.h:1430
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: lf_heter_queue.h:2138
void commit() noexcept
Definition: lf_heter_queue.h:2302
allocator_type & get_allocator_ref() noexcept
Definition: lf_heter_queue.h:314
bool try_reentrant_pop() noexcept
Definition: lf_heter_queue.h:3141
void cancel() noexcept
Definition: lf_heter_queue.h:2570
constexpr lf_heter_queue() noexcept=default
std::iterator_traits< INPUT_ITERATOR >::value_type * raw_allocate_copy(INPUT_ITERATOR i_begin, INPUT_ITERATOR i_end)
Definition: lf_heter_queue.h:2095
bool try_reentrant_dyn_push_copy(progress_guarantee i_progress_guarantee, const runtime_type &i_type, const void *i_source)
Definition: lf_heter_queue.h:2909