ringbuffer.h revision e7201bd31b4c7beb1a2d0c4659477946e263d5cf
1/**************************************************************************** 2* Copyright (C) 2016 Intel Corporation. All Rights Reserved. 3* 4* Permission is hereby granted, free of charge, to any person obtaining a 5* copy of this software and associated documentation files (the "Software"), 6* to deal in the Software without restriction, including without limitation 7* the rights to use, copy, modify, merge, publish, distribute, sublicense, 8* and/or sell copies of the Software, and to permit persons to whom the 9* Software is furnished to do so, subject to the following conditions: 10* 11* The above copyright notice and this permission notice (including the next 12* paragraph) shall be included in all copies or substantial portions of the 13* Software. 14* 15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21* IN THE SOFTWARE. 22* 23* @file arena.h 24* 25* @brief RingBuffer 26* The RingBuffer class manages all aspects of the ring buffer including 27* the head/tail indices, etc. 28* 29******************************************************************************/ 30#pragma once 31 32template<typename T> 33class RingBuffer 34{ 35public: 36 RingBuffer() 37 : mpRingBuffer(nullptr), mNumEntries(0), mRingHead(0), mRingTail(0) 38 { 39 } 40 41 ~RingBuffer() 42 { 43 Destroy(); 44 } 45 46 void Init(uint32_t numEntries) 47 { 48 SWR_ASSERT(numEntries > 0); 49 mNumEntries = numEntries; 50 mpRingBuffer = (T*)_aligned_malloc(sizeof(T)*numEntries, 64); 51 SWR_ASSERT(mpRingBuffer != nullptr); 52 memset(mpRingBuffer, 0, sizeof(T)*numEntries); 53 } 54 55 void Destroy() 56 { 57 _aligned_free(mpRingBuffer); 58 mpRingBuffer = nullptr; 59 } 60 61 T& operator[](const uint32_t index) 62 { 63 SWR_ASSERT(index < mNumEntries); 64 return mpRingBuffer[index]; 65 } 66 67 INLINE void Enqueue() 68 { 69 mRingHead++; // There's only one producer. 70 } 71 72 INLINE void Dequeue() 73 { 74 InterlockedIncrement(&mRingTail); // There are multiple consumers. 75 } 76 77 INLINE bool IsEmpty() 78 { 79 return (GetHead() == GetTail()); 80 } 81 82 INLINE bool IsFull() 83 { 84 ///@note We don't handle wrap case due to using 64-bit indices. 85 /// It would take 11 million years to wrap at 50,000 DCs per sec. 86 /// If we used 32-bit indices then its about 23 hours to wrap. 87 uint64_t numEnqueued = GetHead() - GetTail(); 88 SWR_ASSERT(numEnqueued <= mNumEntries); 89 90 return (numEnqueued == mNumEntries); 91 } 92 93 INLINE uint64_t GetTail() volatile { return mRingTail; } 94 INLINE uint64_t GetHead() volatile { return mRingHead; } 95 96protected: 97 T* mpRingBuffer; 98 uint32_t mNumEntries; 99 100 OSALIGNLINE(volatile uint64_t) mRingHead; // Consumer Counter 101 OSALIGNLINE(volatile uint64_t) mRingTail; // Producer Counter 102}; 103