• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
32 template<typename T>
33 class RingBuffer
34 {
35 public:
RingBuffer()36     RingBuffer()
37         : mpRingBuffer(nullptr), mNumEntries(0), mRingHead(0), mRingTail(0)
38     {
39     }
40 
~RingBuffer()41     ~RingBuffer()
42     {
43         Destroy();
44     }
45 
Init(uint32_t numEntries)46     void Init(uint32_t numEntries)
47     {
48         SWR_ASSERT(numEntries > 0);
49         SWR_ASSERT(((1ULL << 32) % numEntries) == 0, "%d is not evenly divisible into 2 ^ 32.  Wrap errors will occur!", numEntries);
50         mNumEntries = numEntries;
51         mpRingBuffer = (T*)AlignedMalloc(sizeof(T)*numEntries, 64);
52         SWR_ASSERT(mpRingBuffer != nullptr);
53         memset(mpRingBuffer, 0, sizeof(T)*numEntries);
54     }
55 
Destroy()56     void Destroy()
57     {
58         AlignedFree(mpRingBuffer);
59         mpRingBuffer = nullptr;
60     }
61 
62     T& operator[](const uint32_t index)
63     {
64         SWR_ASSERT(index < mNumEntries);
65         return mpRingBuffer[index];
66     }
67 
Enqueue()68     INLINE void Enqueue()
69     {
70         mRingHead++; // There's only one producer.
71         // Assert to find wrap-around cases, NEVER ENABLE DURING CHECKIN!!
72         // SWR_REL_ASSERT(mRingHead);
73     }
74 
Dequeue()75     INLINE void Dequeue()
76     {
77         InterlockedIncrement(&mRingTail); // There are multiple consumers.
78     }
79 
IsEmpty()80     INLINE bool IsEmpty()
81     {
82         return (GetHead() == GetTail());
83     }
84 
IsFull()85     INLINE bool IsFull()
86     {
87         uint32_t numEnqueued = GetHead() - GetTail();
88         SWR_ASSERT(numEnqueued <= mNumEntries);
89 
90         return (numEnqueued == mNumEntries);
91     }
92 
GetTail()93     INLINE uint32_t GetTail() volatile { return mRingTail; }
GetHead()94     INLINE uint32_t GetHead() volatile { return mRingHead; }
95 
96 protected:
97     T* mpRingBuffer;
98     uint32_t mNumEntries;
99 
100     OSALIGNLINE(volatile uint32_t) mRingHead;  // Consumer Counter
101     OSALIGNLINE(volatile uint32_t) mRingTail;  // Producer Counter
102 };
103