density
C++11 library for paged memory management, function queues, heterogeneous queues and lifo memory management
function_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/detail/function_runtime_type.h>
9 #include <density/heter_queue.h>
10 
11 namespace density
12 {
13  template <
14  typename CALLABLE,
15  typename ALLOCATOR_TYPE = default_allocator,
18 
36 #ifndef DOXYGEN_DOC_GENERATION
37  template <
38  typename RET_VAL,
39  typename... PARAMS,
40  typename ALLOCATOR_TYPE,
41  function_type_erasure ERASURE>
42  class function_queue<RET_VAL(PARAMS...), ALLOCATOR_TYPE, ERASURE>
43 #else
44  template <
45  typename CALLABLE,
46  typename ALLOCATOR_TYPE = default_allocator,
48  class function_queue
49 #endif
50  {
51  private:
52  using UnderlyingQueue =
53  heter_queue<detail::FunctionRuntimeType<ERASURE, RET_VAL(PARAMS...)>, ALLOCATOR_TYPE>;
54  UnderlyingQueue m_queue;
55 
56  public:
58  static constexpr bool concurrent_puts = false;
59 
61  static constexpr bool concurrent_consumes = false;
62 
65  static constexpr bool concurrent_put_consumes = false;
66 
68  static constexpr bool is_seq_cst = true;
69 
73  constexpr function_queue() noexcept = default;
74 
78  function_queue(function_queue && i_source) noexcept = default;
79 
83  function_queue & operator=(function_queue && i_source) noexcept = default;
84 
88  friend void swap(function_queue & i_first, function_queue & i_second) noexcept
89  {
90  using std::swap;
91  swap(i_first.m_queue, i_second.m_queue);
92  }
93 
96  {
97  auto erasure = ERASURE;
98  if (erasure == function_manual_clear)
99  {
101  }
102  }
103 
105  template <typename ELEMENT_COMPLETE_TYPE>
106  using put_transaction =
107  typename UnderlyingQueue::template put_transaction<ELEMENT_COMPLETE_TYPE>;
108 
110  template <typename ELEMENT_COMPLETE_TYPE>
112  typename UnderlyingQueue::template reentrant_put_transaction<ELEMENT_COMPLETE_TYPE>;
113 
115  using consume_operation = typename UnderlyingQueue::consume_operation;
116 
118  using reentrant_consume_operation = typename UnderlyingQueue::reentrant_consume_operation;
119 
127  template <typename ELEMENT_COMPLETE_TYPE> void push(ELEMENT_COMPLETE_TYPE && i_source)
128  {
129  m_queue.push(std::forward<ELEMENT_COMPLETE_TYPE>(i_source));
130  }
131 
139  template <typename ELEMENT_COMPLETE_TYPE, typename... CONSTRUCTION_PARAMS>
140  void emplace(CONSTRUCTION_PARAMS &&... i_construction_params)
141  {
142  m_queue.template emplace<ELEMENT_COMPLETE_TYPE>(
143  std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...);
144  }
145 
153  template <typename ELEMENT_TYPE>
155  start_push(ELEMENT_TYPE && i_source)
156  {
157  return m_queue.start_push(std::forward<ELEMENT_TYPE>(i_source));
158  }
159 
160 
168  template <typename ELEMENT_TYPE, typename... CONSTRUCTION_PARAMS>
169  put_transaction<ELEMENT_TYPE> start_emplace(CONSTRUCTION_PARAMS &&... i_construction_params)
170  {
171  return m_queue.template start_emplace<ELEMENT_TYPE>(
172  std::forward<ELEMENT_TYPE>(i_construction_params)...);
173  }
174 
180  template <typename ELEMENT_COMPLETE_TYPE>
181  void reentrant_push(ELEMENT_COMPLETE_TYPE && i_source)
182  {
183  m_queue.reentrant_push(std::forward<ELEMENT_COMPLETE_TYPE>(i_source));
184  }
185 
193  template <typename ELEMENT_COMPLETE_TYPE, typename... CONSTRUCTION_PARAMS>
194  void reentrant_emplace(CONSTRUCTION_PARAMS &&... i_construction_params)
195  {
196  m_queue.template reentrant_emplace<ELEMENT_COMPLETE_TYPE>(
197  std::forward<CONSTRUCTION_PARAMS>(i_construction_params)...);
198  }
199 
207  template <typename ELEMENT_TYPE>
209  start_reentrant_push(ELEMENT_TYPE && i_source)
210  {
211  return m_queue.start_reentrant_push(std::forward<ELEMENT_TYPE>(i_source));
212  }
213 
214 
222  template <typename ELEMENT_TYPE, typename... CONSTRUCTION_PARAMS>
224  start_reentrant_emplace(CONSTRUCTION_PARAMS &&... i_construction_params)
225  {
226  return m_queue.template start_reentrant_emplace<ELEMENT_TYPE>(
227  std::forward<ELEMENT_TYPE>(i_construction_params)...);
228  }
229 
245  typename std::conditional<std::is_void<RET_VAL>::value, bool, optional<RET_VAL>>::type
246  try_consume(PARAMS... i_params)
247  {
248  return try_consume_impl(std::is_void<RET_VAL>(), std::forward<PARAMS>(i_params)...);
249  }
250 
271  typename std::conditional<std::is_void<RET_VAL>::value, bool, optional<RET_VAL>>::type
272  try_consume(consume_operation & i_consume, PARAMS... i_params)
273  {
274  return try_consume_impl_cached(
275  std::is_void<RET_VAL>(), i_consume, std::forward<PARAMS>(i_params)...);
276  }
277 
292  typename std::conditional<std::is_void<RET_VAL>::value, bool, optional<RET_VAL>>::type
293  try_reentrant_consume(PARAMS... i_params)
294  {
295  return try_reentrant_consume_impl(
296  std::is_void<RET_VAL>(), std::forward<PARAMS>(i_params)...);
297  }
298 
318  typename std::conditional<std::is_void<RET_VAL>::value, bool, optional<RET_VAL>>::type
319  try_reentrant_consume(reentrant_consume_operation & i_consume, PARAMS... i_params)
320  {
321  return try_reentrant_consume_impl_cached(
322  std::is_void<RET_VAL>(), i_consume, std::forward<PARAMS>(i_params)...);
323  }
324 
332  template <
333  function_type_erasure ERASURE_ = ERASURE,
334  typename std::enable_if<ERASURE_ != function_manual_clear>::type * = nullptr>
335  void clear() noexcept
336  {
337  auto erasure = ERASURE;
338  if (erasure == function_manual_clear)
339  {
340  DENSITY_ASSUME(false);
341  }
342  else
343  {
344  m_queue.clear();
345  }
346  }
347 
349  bool empty() noexcept { return m_queue.empty(); }
350 
351  private:
353  optional<RET_VAL> try_consume_impl(std::false_type, PARAMS... i_params)
354  {
355  if (auto cons = m_queue.try_start_consume())
356  {
357  auto && result = cons.complete_type().align_invoke_destroy(
358  cons.unaligned_element_ptr(), std::forward<PARAMS>(i_params)...);
359  cons.commit_nodestroy();
360  return optional<RET_VAL>(std::move(result));
361  }
362  else
363  {
364  return optional<RET_VAL>();
365  }
366  }
367 
369  bool try_consume_impl(std::true_type, PARAMS... i_params)
370  {
371  if (auto cons = m_queue.try_start_consume())
372  {
373  cons.complete_type().align_invoke_destroy(
374  cons.unaligned_element_ptr(), std::forward<PARAMS>(i_params)...);
375  cons.commit_nodestroy();
376  return true;
377  }
378  else
379  {
380  return false;
381  }
382  }
383 
385  optional<RET_VAL> try_consume_impl_cached(
386  std::false_type, consume_operation & i_consume, PARAMS... i_params)
387  {
388  if (m_queue.try_start_consume(i_consume))
389  {
390  auto && result = i_consume.complete_type().align_invoke_destroy(
391  i_consume.unaligned_element_ptr(), std::forward<PARAMS>(i_params)...);
392  i_consume.commit_nodestroy();
393  return optional<RET_VAL>(std::move(result));
394  }
395  else
396  {
397  return optional<RET_VAL>();
398  }
399  }
400 
402  bool
403  try_consume_impl_cached(std::true_type, consume_operation & i_consume, PARAMS... i_params)
404  {
405  if (m_queue.try_start_consume(i_consume))
406  {
407  i_consume.complete_type().align_invoke_destroy(
408  i_consume.unaligned_element_ptr(), std::forward<PARAMS>(i_params)...);
409  i_consume.commit_nodestroy();
410  return true;
411  }
412  else
413  {
414  return false;
415  }
416  }
417 
419  optional<RET_VAL> try_reentrant_consume_impl(std::false_type, PARAMS... i_params)
420  {
421  if (auto cons = m_queue.try_start_reentrant_consume())
422  {
423  auto && result = cons.complete_type().align_invoke_destroy(
424  cons.unaligned_element_ptr(), std::forward<PARAMS>(i_params)...);
425  cons.commit_nodestroy();
426  return optional<RET_VAL>(std::move(result));
427  }
428  else
429  {
430  return optional<RET_VAL>();
431  }
432  }
433 
435  bool try_reentrant_consume_impl(std::true_type, PARAMS... i_params)
436  {
437  if (auto cons = m_queue.try_start_reentrant_consume())
438  {
439  cons.complete_type().align_invoke_destroy(
440  cons.unaligned_element_ptr(), std::forward<PARAMS>(i_params)...);
441  cons.commit_nodestroy();
442  return true;
443  }
444  else
445  {
446  return false;
447  }
448  }
449 
451  optional<RET_VAL> try_reentrant_consume_impl_cached(
452  std::false_type, reentrant_consume_operation & i_consume, PARAMS... i_params)
453  {
454  if (m_queue.try_start_reentrant_consume(i_consume))
455  {
456  auto && result = i_consume.complete_type().align_invoke_destroy(
457  i_consume.unaligned_element_ptr(), std::forward<PARAMS>(i_params)...);
458  i_consume.commit_nodestroy();
459  return optional<RET_VAL>(std::move(result));
460  }
461  else
462  {
463  return optional<RET_VAL>();
464  }
465  }
466 
468  bool try_reentrant_consume_impl_cached(
469  std::true_type, reentrant_consume_operation & i_consume, PARAMS... i_params)
470  {
471  if (m_queue.try_start_reentrant_consume(i_consume))
472  {
473  i_consume.complete_type().align_invoke_destroy(
474  i_consume.unaligned_element_ptr(), std::forward<PARAMS>(i_params)...);
475  i_consume.commit_nodestroy();
476  return true;
477  }
478  else
479  {
480  return false;
481  }
482  }
483  };
484 
485 } // namespace density
bool empty() const noexcept
Definition: heter_queue.h:458
basic_default_allocator< default_page_capacity > default_allocator
Definition: default_allocator.h:152
Definition: conc_function_queue.h:11
void push(ELEMENT_COMPLETE_TYPE &&i_source)
Definition: function_queue.h:127
void emplace(CONSTRUCTION_PARAMS &&...i_construction_params)
Definition: function_queue.h:140
static constexpr bool concurrent_consumes
Definition: function_queue.h:61
reentrant_put_transaction< typename std::decay< ELEMENT_TYPE >::type > start_reentrant_push(ELEMENT_TYPE &&i_source)
Definition: function_queue.h:209
std::conditional< std::is_void< RET_VAL >::value, bool, optional< RET_VAL > >::type try_reentrant_consume(reentrant_consume_operation &i_consume, PARAMS...i_params)
Definition: function_queue.h:319
typename UnderlyingQueue::consume_operation consume_operation
Definition: function_queue.h:115
put_transaction< ELEMENT_TYPE > start_emplace(CONSTRUCTION_PARAMS &&...i_construction_params)
Definition: function_queue.h:169
void push(ELEMENT_TYPE &&i_source)
Definition: heter_queue.h:1089
typename UnderlyingQueue::template put_transaction< ELEMENT_COMPLETE_TYPE > put_transaction
Definition: function_queue.h:107
#define DENSITY_ASSERT(...)
Definition: density_config.h:19
reentrant_consume_operation try_start_reentrant_consume() noexcept
Definition: heter_queue.h:2322
reentrant_put_transaction< ELEMENT_TYPE > start_reentrant_emplace(CONSTRUCTION_PARAMS &&...i_construction_params)
Definition: function_queue.h:224
put_transaction< typename std::decay< ELEMENT_TYPE >::type > start_push(ELEMENT_TYPE &&i_source)
Definition: heter_queue.h:1208
void reentrant_push(ELEMENT_COMPLETE_TYPE &&i_source)
Definition: function_queue.h:181
Definition: density_common.h:99
std::conditional< std::is_void< RET_VAL >::value, bool, optional< RET_VAL > >::type try_consume(PARAMS...i_params)
Definition: function_queue.h:246
void clear() noexcept
Definition: heter_queue.h:480
Definition: density_common.h:101
constexpr function_queue() noexcept=default
typename UnderlyingQueue::reentrant_consume_operation reentrant_consume_operation
Definition: function_queue.h:118
std::conditional< std::is_void< RET_VAL >::value, bool, optional< RET_VAL > >::type try_consume(consume_operation &i_consume, PARAMS...i_params)
Definition: function_queue.h:272
bool empty() noexcept
Definition: function_queue.h:349
builtin_optional< TYPE > optional
Definition: density_config.h:218
put_transaction< typename std::decay< ELEMENT_TYPE >::type > start_push(ELEMENT_TYPE &&i_source)
Definition: function_queue.h:155
friend void swap(function_queue &i_first, function_queue &i_second) noexcept
Definition: function_queue.h:88
static constexpr bool concurrent_puts
Definition: function_queue.h:58
consume_operation try_start_consume() noexcept
Definition: heter_queue.h:1456
~function_queue()
Definition: function_queue.h:95
static constexpr bool concurrent_put_consumes
Definition: function_queue.h:65
std::conditional< std::is_void< RET_VAL >::value, bool, optional< RET_VAL > >::type try_reentrant_consume(PARAMS...i_params)
Definition: function_queue.h:293
void reentrant_emplace(CONSTRUCTION_PARAMS &&...i_construction_params)
Definition: function_queue.h:194
typename UnderlyingQueue::template reentrant_put_transaction< ELEMENT_COMPLETE_TYPE > reentrant_put_transaction
Definition: function_queue.h:112
void reentrant_push(ELEMENT_TYPE &&i_source)
Definition: heter_queue.h:2068
Definition: function_queue.h:17
function_type_erasure
Definition: density_common.h:97
reentrant_put_transaction< typename std::decay< ELEMENT_TYPE >::type > start_reentrant_push(ELEMENT_TYPE &&i_source)
Definition: heter_queue.h:2124
#define DENSITY_ASSUME(bool_expr,...)
Definition: density_config.h:46
void clear() noexcept
Definition: function_queue.h:335
static constexpr bool is_seq_cst
Definition: function_queue.h:68