26 #ifndef INCLUDED_IPCRingBufferSharedObjects_h_GUID_890394B4_253B_4BAF_C813_E0E54D159128
27 #define INCLUDED_IPCRingBufferSharedObjects_h_GUID_890394B4_253B_4BAF_C813_E0E54D159128
37 #include <boost/noncopyable.hpp>
46 namespace bip = boost::interprocess;
50 typedef IPCRingBuffer::value_type BufferType;
54 template <
typename LockType>
55 BufferType *getBuf(LockType &lock)
const {
60 template <
typename ManagedMemory>
61 void allocateBuf(ManagedMemory &shm,
64 m_buf =
static_cast<BufferType *
>(shm.allocate_aligned(
65 opts.getEntrySize(), opts.getAlignment()));
68 template <
typename ManagedMemory>
void freeBuf(ManagedMemory &shm) {
69 if (
nullptr != m_buf) {
70 shm.deallocate(m_buf.get());
76 ipc_offset_ptr<BufferType> m_buf;
82 typedef uint16_t raw_index_type;
84 template <
typename ManagedMemory>
87 shm.template find<Bookkeeping>(bip::unique_instance);
91 template <
typename ManagedMemory>
94 return shm.template construct<Bookkeeping>(
95 bip::unique_instance)(shm, opts);
98 template <
typename ManagedMemory>
99 static void destroy(ManagedMemory &shm) {
100 auto self = find(shm);
101 if (
nullptr ==
self) {
105 shm.template destroy<Bookkeeping>(bip::unique_instance);
108 template <
typename ManagedMemory>
110 : m_capacity(opts.getEntries()),
111 elementArray(shm.template construct<ElementData>(
112 bip::unique_instance)[m_capacity]()),
113 m_beginSequenceNumber(0), m_nextSequenceNumber(0), m_begin(0),
114 m_size(0), m_bufLen(opts.getEntrySize()) {
116 auto lock = getExclusiveLock();
118 for (raw_index_type i = 0; i < m_capacity; ++i) {
120 getByRawIndex(i, lock).allocateBuf(shm, opts);
121 }
catch (std::bad_alloc &) {
122 OSVR_DEV_VERBOSE(
"Couldn't allocate buffer #"
124 <<
", truncating the ring buffer");
132 template <
typename ManagedMemory>
133 void freeBufs(ManagedMemory &shm) {
134 auto lock = getExclusiveLock();
136 for (raw_index_type i = 0; i < m_capacity; ++i) {
137 getByRawIndex(i, lock).freeBuf(shm);
139 shm.template destroy<ElementData>(bip::unique_instance);
149 template <
typename LockType>
150 ElementData &getByRawIndex(raw_index_type index, LockType &lock) {
152 return *(elementArray + (index % m_capacity));
154 template <
typename LockType>
155 ElementData *getBySequenceNumber(sequence_type num,
158 auto sequenceRelativeToBegin = num - m_beginSequenceNumber;
159 if (sequenceRelativeToBegin < m_size) {
160 raw_index_type idx((m_begin + sequenceRelativeToBegin) %
162 return &getByRawIndex(idx, lock);
167 template <
typename LockType>
bool empty(LockType &lock)
const {
171 template <
typename LockType>
172 sequence_type backSequenceNumber(LockType &lock) {
174 return m_nextSequenceNumber - 1;
177 template <
typename LockType> ElementData *back(LockType &lock) {
182 return &getByRawIndex(m_begin + m_size - 1, lock);
186 auto lock = getExclusiveLock();
187 auto sequenceNumber = m_nextSequenceNumber;
188 m_nextSequenceNumber++;
189 if (m_size == m_capacity) {
191 m_beginSequenceNumber++;
195 #ifdef OSVR_SHM_LOCK_DEBUGGING
197 "Attempting to get an exclusive lock on sequence "
198 << sequenceNumber <<
" aka index " << back(lock));
200 auto elementLock = back(lock)->getExclusiveLock();
203 back(lock)->getBuf(elementLock), sequenceNumber,
204 std::move(elementLock), std::move(lock),
nullptr});
209 raw_index_type m_capacity;
210 ipc_offset_ptr<ElementData> elementArray;
213 raw_index_type m_begin;
214 raw_index_type m_size;
221 #endif // INCLUDED_IPCRingBufferSharedObjects_h_GUID_890394B4_253B_4BAF_C813_E0E54D159128
Header wrapping the C99 standard stdint header.
uint32_t getBufferLength() const
Get capacity of elements.
uint32_t sequence_type
The sequence number is automatically incremented with each "put" into the buffer. Note that...
raw_index_type getCapacity() const
Get number of elements.
void verifyReaderLock(LockType &lock) const
Checks to make sure we at least have a reader (sharable) lock.
Internal, configured header file for verbosity macros.
IPCPutResultPtr produceElement()