hmbdc
simplify-high-performance-messaging-programming
MonoLockFreeBuffer.hpp
1 #include "hmbdc/Copyright.hpp"
2 #pragma once
3 
4 #include "hmbdc/pattern/LockFreeBufferMisc.hpp"
5 #include "hmbdc/os/Allocators.hpp"
6 #include "hmbdc/Config.hpp"
7 #include "hmbdc/pattern/MemRingBuffer.hpp"
8 
9 #include <utility>
10 #include <functional>
11 #include <limits>
12 #include <stdexcept>
13 #include <cstddef>
14 
15 namespace hmbdc { namespace pattern {
17  using Sequence = HMBDC_SEQ_TYPE;
19  using value_type = void *;
21  enum {
22  max_parallel_consumer = 0xffff
23  };
24 
25  template <typename Allocator = os::DefaultAllocator>
26  MonoLockFreeBuffer(size_t, uint32_t, Allocator& allocator = os::DefaultAllocator::instance());
28 
29  size_t maxItemSize() const;
30  size_t capacity() const;
31  void put(void const*, size_t sizeHint = 0);
32  template <typename T> void put(T const& item) {put(&item, sizeof(item));}
33  template <typename T> void putSome(T const& item) {put(&item, std::min(sizeof(item), maxItemSize()));}
34  template <typename T, typename ...Args>
35  void putInPlace(Args&&... args) {
36  auto s = claim();
37  new (*s) T(std::forward<Args>(args)...);
38  commit(s);
39  }
40  template <typename T, typename ...Args>
41  bool tryPutInPlace(Args&&... args) {
42  auto s = tryClaim();
43  if (!s) return false;
44  new (*s) T(std::forward<Args>(args)...);
45  commit(s);
46  return true;
47  }
48 
49  bool tryPut(void const*, size_t sizeHint = 0);
50  bool isFull() const;
51  Sequence readSeq() const;
52  iterator claim();
53  iterator tryClaim();
54  iterator claim(size_t);
55  iterator tryClaim(size_t);
56  iterator killClaim();
57  iterator killClaim(size_t);
58  void commit(iterator);
59  void commit(iterator, size_t);
60  void take(void *, size_t = 0);
61  bool tryTake(void *, size_t = 0);
62  iterator peek();
63  size_t peek(iterator&, iterator&
64  , size_t maxPeekSize = std::numeric_limits<size_t>::max());
65  size_t peekSome(iterator&, iterator&
66  , size_t maxPeekSize = std::numeric_limits<size_t>::max());
67  /**
68  * @brief if size not matching - please refer to the impl for details
69  */
70  void wasteAfterPeek(iterator, size_t, bool = false);
71  size_t remainingSize() const;
72  size_t parallelConsumerAlive() const {return 1;}
73  void reset();
74 
75  static
76  size_t footprint(size_t, uint32_t);
77 private:
78  std::ptrdiff_t impl_;
79  std::function<void()> freer_;
80 };
81 }}
82 
83 
84 namespace hmbdc { namespace pattern {
85 using MMRB = MemRingBuffer<0u, typename MonoLockFreeBuffer::Sequence>;
86 
87 namespace {
88 inline
89 uint32_t itemSizePower2Num(size_t valueTypeSize) {
90  uint32_t res = 1ul;
91  valueTypeSize += sizeof(MMRB::Sequence);
92  while ((1ul << res) < valueTypeSize) res++;
93  return res;
94 }
95 }
96 
97 #ifdef impl_vptr
98 #undef impl_vptr
99 #endif
100 #define impl_vptr ((void*)(((char*)this) + impl_))
101 
102 inline
103 size_t
104 MonoLockFreeBuffer::
105 maxItemSize() const {
106  return static_cast<MMRB*>(impl_vptr)->VALUE_TYPE_SIZE;
107 }
108 
109 inline
110 size_t
111 MonoLockFreeBuffer::
112 capacity() const {
113  return static_cast<MMRB*>(impl_vptr)->CAPACITY;
114 }
115 
116 template <typename Allocator>
117 MonoLockFreeBuffer::
118 MonoLockFreeBuffer(size_t valueTypeSize, uint32_t ringSizePower2Num, Allocator& allocator)
119 // : impl_(new MMRB(itemSizePower2Num(valueTypeSize), ringSizePower2Num))
120 : impl_(((char*)allocator.template allocate<MMRB>(SMP_CACHE_BYTES
121  , itemSizePower2Num(valueTypeSize), ringSizePower2Num
122  , (allocator))) - (char*)this)
123 , freer_([this, &allocator](){allocator.unallocate(static_cast<MMRB*>(impl_vptr));})
124 {}
125 
126 inline
127 size_t
128 MonoLockFreeBuffer::
129 footprint(size_t valueTypeSize, uint32_t ringSizePower2Num){
130  return sizeof(MonoLockFreeBuffer) + SMP_CACHE_BYTES + MMRB::footprint(
131  itemSizePower2Num(valueTypeSize), ringSizePower2Num) + SMP_CACHE_BYTES;
132 }
133 
134 inline
135 MonoLockFreeBuffer::
136 ~MonoLockFreeBuffer() {
137  freer_();
138  // if (allocateFromHeap_) {
139  // delete static_cast<MMRB*>(impl_vptr);
140  // } else {
141  // static_cast<MMRB*>(impl_vptr)->~MMRB();
142  // }
143 }
144 
145 inline void MonoLockFreeBuffer::put(void const* item, size_t sizeHint) HMBDC_RESTRICT { static_cast<MMRB*>(impl_vptr)->put(item, sizeHint);}
146 inline bool MonoLockFreeBuffer::tryPut(void const* item, size_t sizeHint) HMBDC_RESTRICT {return static_cast<MMRB*>(impl_vptr)->tryPut(item, sizeHint);}
147 inline bool MonoLockFreeBuffer::isFull() const HMBDC_RESTRICT {return static_cast<MMRB*>(impl_vptr)->isFull();}
148 inline MonoLockFreeBuffer::Sequence MonoLockFreeBuffer::readSeq() const HMBDC_RESTRICT {return static_cast<MMRB*>(impl_vptr)->readSeq();}
149 inline MonoLockFreeBuffer::iterator MonoLockFreeBuffer::claim() HMBDC_RESTRICT {return static_cast<MMRB*>(impl_vptr)->claim();}
150 inline MonoLockFreeBuffer::iterator MonoLockFreeBuffer::tryClaim() HMBDC_RESTRICT {return static_cast<MMRB*>(impl_vptr)->tryClaim();}
151 inline MonoLockFreeBuffer::iterator MonoLockFreeBuffer::claim(size_t n) HMBDC_RESTRICT {return static_cast<MMRB*>(impl_vptr)->claim(n);}
152 inline MonoLockFreeBuffer::iterator MonoLockFreeBuffer::tryClaim(size_t n) HMBDC_RESTRICT {return static_cast<MMRB*>(impl_vptr)->tryClaim(n);}
153 inline void MonoLockFreeBuffer::commit(MonoLockFreeBuffer::iterator it) HMBDC_RESTRICT { static_cast<MMRB*>(impl_vptr)->commit(it);}
154 inline void MonoLockFreeBuffer::commit(iterator it, size_t n) HMBDC_RESTRICT { static_cast<MMRB*>(impl_vptr)->commit(it, n);}
155 inline void MonoLockFreeBuffer::take(void *i, size_t n) HMBDC_RESTRICT { static_cast<MMRB*>(impl_vptr)->take(i, n);}
156 inline bool MonoLockFreeBuffer::tryTake(void *i, size_t n) HMBDC_RESTRICT {return static_cast<MMRB*>(impl_vptr)->tryTake(i, n);}
157 inline MonoLockFreeBuffer::iterator MonoLockFreeBuffer::peek() HMBDC_RESTRICT {return static_cast<MMRB*>(impl_vptr)->peek();}
158 inline size_t MonoLockFreeBuffer::peek(iterator& b, iterator& e, size_t s) HMBDC_RESTRICT {return static_cast<MMRB*>(impl_vptr)->peek(b, e, s);}
159 inline size_t MonoLockFreeBuffer::peekSome(iterator& b, iterator& e, size_t s) HMBDC_RESTRICT {return static_cast<MMRB*>(impl_vptr)->peekSome(b, e, s);}
160 inline void MonoLockFreeBuffer::wasteAfterPeek(iterator b, size_t n, bool incomplete ) HMBDC_RESTRICT { static_cast<MMRB*>(impl_vptr)->wasteAfterPeek(b, n, incomplete);}
161 inline size_t MonoLockFreeBuffer::remainingSize() const HMBDC_RESTRICT {return static_cast<MMRB*>(impl_vptr)->remainingSize();}
162 inline void MonoLockFreeBuffer::reset() HMBDC_RESTRICT { static_cast<MMRB*>(impl_vptr)->reset();}
163 
164 template MonoLockFreeBuffer::MonoLockFreeBuffer(size_t, uint32_t, os::DefaultAllocator&);
165 template MonoLockFreeBuffer::MonoLockFreeBuffer(size_t, uint32_t, os::ShmBasePtrAllocator&);
166 }} // end namespace hmbdc::pattern
167 
168 #undef impl_vptr
Definition: MonoLockFreeBuffer.hpp:16
Definition: LockFreeBufferMisc.hpp:23
Definition: Base.hpp:12
void wasteAfterPeek(iterator, size_t, bool=false)
if size not matching - please refer to the impl for details
Definition: MonoLockFreeBuffer.hpp:160
Definition: LockFreeBufferMisc.hpp:89