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()