OVR_Deque.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. /************************************************************************************
  2. Filename : OVR_Deque.h
  3. Content : Deque container
  4. Created : Nov. 15, 2013
  5. Authors : Dov Katz
  6. Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
  7. Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
  8. you may not use the Oculus VR Rift SDK except in compliance with the License,
  9. which is provided at the time of installation or download, or which
  10. otherwise accompanies this software in either electronic or hard copy form.
  11. You may obtain a copy of the License at
  12. http://www.oculusvr.com/licenses/LICENSE-3.2
  13. Unless required by applicable law or agreed to in writing, the Oculus VR SDK
  14. distributed under the License is distributed on an "AS IS" BASIS,
  15. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. See the License for the specific language governing permissions and
  17. limitations under the License.
  18. *************************************************************************************/
  19. #ifndef OVR_Deque_h
  20. #define OVR_Deque_h
  21. #include "OVR_ContainerAllocator.h"
  22. namespace OVR{
  23. template <class Elem, class Allocator = ContainerAllocator<Elem> >
  24. class Deque
  25. {
  26. public:
  27. enum
  28. {
  29. DefaultCapacity = 500
  30. };
  31. Deque(int capacity = DefaultCapacity);
  32. virtual ~Deque(void);
  33. virtual void PushBack (const Elem &Item); // Adds Item to the end
  34. virtual void PushFront (const Elem &Item); // Adds Item to the beginning
  35. virtual Elem PopBack (void); // Removes Item from the end
  36. virtual Elem PopFront (void); // Removes Item from the beginning
  37. virtual const Elem& PeekBack (int count = 0) const; // Returns count-th Item from the end
  38. virtual const Elem& PeekFront (int count = 0) const; // Returns count-th Item from the beginning
  39. virtual inline size_t GetSize (void) const; // Returns Number of Elements
  40. OVR_FORCE_INLINE int GetSizeI (void) const
  41. {
  42. return (int)GetSize();
  43. }
  44. virtual inline size_t GetCapacity(void) const; // Returns the maximum possible number of elements
  45. virtual void Clear (void); // Remove all elements
  46. virtual inline bool IsEmpty () const;
  47. virtual inline bool IsFull () const;
  48. protected:
  49. Elem *Data; // The actual Data array
  50. const int Capacity; // Deque capacity
  51. int Beginning; // Index of the first element
  52. int End; // Index of the next after last element
  53. // Instead of calculating the number of elements, using this variable
  54. // is much more convenient.
  55. int ElemCount;
  56. private:
  57. OVR_NON_COPYABLE(Deque);
  58. };
  59. template <class Elem, class Allocator = ContainerAllocator<Elem> >
  60. class InPlaceMutableDeque : public Deque<Elem, Allocator>
  61. {
  62. typedef Deque<Elem, Allocator> BaseType;
  63. public:
  64. InPlaceMutableDeque( int capacity = BaseType::DefaultCapacity ) : BaseType( capacity ) {}
  65. virtual ~InPlaceMutableDeque() {};
  66. using BaseType::PeekBack;
  67. using BaseType::PeekFront;
  68. virtual Elem& PeekBack (int count = 0); // Returns count-th Item from the end
  69. virtual Elem& PeekFront (int count = 0); // Returns count-th Item from the beginning
  70. };
  71. // Same as Deque, but allows to write more elements than maximum capacity
  72. // Old elements are lost as they are overwritten with the new ones
  73. template <class Elem, class Allocator = ContainerAllocator<Elem> >
  74. class CircularBuffer : public InPlaceMutableDeque<Elem, Allocator>
  75. {
  76. typedef InPlaceMutableDeque<Elem, Allocator> BaseType;
  77. public:
  78. CircularBuffer(int MaxSize = BaseType::DefaultCapacity) : BaseType(MaxSize) { };
  79. virtual ~CircularBuffer(){}
  80. // The following methods are inline as a workaround for a VS bug causing erroneous C4505 warnings
  81. // See: http://stackoverflow.com/questions/3051992/compiler-warning-at-c-template-base-class
  82. inline virtual void PushBack (const Elem &Item); // Adds Item to the end, overwriting the oldest element at the beginning if necessary
  83. inline virtual void PushFront (const Elem &Item); // Adds Item to the beginning, overwriting the oldest element at the end if necessary
  84. };
  85. //----------------------------------------------------------------------------------
  86. // Deque Constructor function
  87. template <class Elem, class Allocator>
  88. Deque<Elem, Allocator>::Deque(int capacity) :
  89. Capacity( capacity ), Beginning(0), End(0), ElemCount(0)
  90. {
  91. Data = (Elem*) Allocator::Alloc(Capacity * sizeof(Elem));
  92. }
  93. // Deque Destructor function
  94. template <class Elem, class Allocator>
  95. Deque<Elem, Allocator>::~Deque(void)
  96. {
  97. Clear();
  98. Allocator::Free(Data);
  99. }
  100. template <class Elem, class Allocator>
  101. void Deque<Elem, Allocator>::Clear()
  102. {
  103. if (!IsEmpty())
  104. {
  105. if (Beginning < End)
  106. {
  107. // no wrap-around
  108. Allocator::DestructArray(Data + Beginning, End - Beginning);
  109. }
  110. else
  111. {
  112. // wrap-around
  113. Allocator::DestructArray(Data + Beginning, Capacity - Beginning);
  114. Allocator::DestructArray(Data, End);
  115. }
  116. }
  117. Beginning = 0;
  118. End = 0;
  119. ElemCount = 0;
  120. }
  121. // Push functions
  122. template <class Elem, class Allocator>
  123. void Deque<Elem, Allocator>::PushBack(const Elem &Item)
  124. {
  125. // Error Check: Make sure we aren't
  126. // exceeding our maximum storage space
  127. OVR_ASSERT( ElemCount < Capacity );
  128. Allocator::Construct(Data + End, Item);
  129. ++End;
  130. ++ElemCount;
  131. // Check for wrap-around
  132. if (End >= Capacity)
  133. End -= Capacity;
  134. }
  135. template <class Elem, class Allocator>
  136. void Deque<Elem, Allocator>::PushFront(const Elem &Item)
  137. {
  138. // Error Check: Make sure we aren't
  139. // exceeding our maximum storage space
  140. OVR_ASSERT( ElemCount < Capacity );
  141. --Beginning;
  142. // Check for wrap-around
  143. if (Beginning < 0)
  144. Beginning += Capacity;
  145. Allocator::Construct(Data + Beginning, Item);
  146. ++ElemCount;
  147. }
  148. // Pop functions
  149. template <class Elem, class Allocator>
  150. Elem Deque<Elem, Allocator>::PopFront(void)
  151. {
  152. // Error Check: Make sure we aren't reading from an empty Deque
  153. OVR_ASSERT( ElemCount > 0 );
  154. Elem ReturnValue = Data[ Beginning ];
  155. Allocator::Destruct(Data + Beginning);
  156. ++Beginning;
  157. --ElemCount;
  158. // Check for wrap-around
  159. if (Beginning >= Capacity)
  160. Beginning -= Capacity;
  161. return ReturnValue;
  162. }
  163. template <class Elem, class Allocator>
  164. Elem Deque<Elem, Allocator>::PopBack(void)
  165. {
  166. // Error Check: Make sure we aren't reading from an empty Deque
  167. OVR_ASSERT( ElemCount > 0 );
  168. --End;
  169. --ElemCount;
  170. // Check for wrap-around
  171. if (End < 0)
  172. End += Capacity;
  173. Elem ReturnValue = Data[ End ];
  174. Allocator::Destruct(Data + End);
  175. return ReturnValue;
  176. }
  177. // Peek functions
  178. template <class Elem, class Allocator>
  179. const Elem& Deque<Elem, Allocator>::PeekFront(int count) const
  180. {
  181. // Error Check: Make sure we aren't reading from an empty Deque
  182. OVR_ASSERT( ElemCount > count );
  183. int idx = Beginning + count;
  184. if (idx >= Capacity)
  185. idx -= Capacity;
  186. return Data[ idx ];
  187. }
  188. template <class Elem, class Allocator>
  189. const Elem& Deque<Elem, Allocator>::PeekBack(int count) const
  190. {
  191. // Error Check: Make sure we aren't reading from an empty Deque
  192. OVR_ASSERT( ElemCount > count );
  193. int idx = End - count - 1;
  194. if (idx < 0)
  195. idx += Capacity;
  196. return Data[ idx ];
  197. }
  198. // Mutable Peek functions
  199. template <class Elem, class Allocator>
  200. Elem& InPlaceMutableDeque<Elem, Allocator>::PeekFront(int count)
  201. {
  202. // Error Check: Make sure we aren't reading from an empty Deque
  203. OVR_ASSERT( BaseType::ElemCount > count );
  204. int idx = BaseType::Beginning + count;
  205. if (idx >= BaseType::Capacity)
  206. idx -= BaseType::Capacity;
  207. return BaseType::Data[ idx ];
  208. }
  209. template <class Elem, class Allocator>
  210. Elem& InPlaceMutableDeque<Elem, Allocator>::PeekBack(int count)
  211. {
  212. // Error Check: Make sure we aren't reading from an empty Deque
  213. OVR_ASSERT( BaseType::ElemCount > count );
  214. int idx = BaseType::End - count - 1;
  215. if (idx < 0)
  216. idx += BaseType::Capacity;
  217. return BaseType::Data[ idx ];
  218. }
  219. template <class Elem, class Allocator>
  220. inline size_t Deque<Elem, Allocator>::GetCapacity(void) const
  221. {
  222. return Capacity;
  223. }
  224. template <class Elem, class Allocator>
  225. inline size_t Deque<Elem, Allocator>::GetSize(void) const
  226. {
  227. return ElemCount;
  228. }
  229. template <class Elem, class Allocator>
  230. inline bool Deque<Elem, Allocator>::IsEmpty(void) const
  231. {
  232. return ElemCount == 0;
  233. }
  234. template <class Elem, class Allocator>
  235. inline bool Deque<Elem, Allocator>::IsFull(void) const
  236. {
  237. return ElemCount == Capacity;
  238. }
  239. // ******* CircularBuffer<Elem> *******
  240. // Push functions
  241. template <class Elem, class Allocator>
  242. void CircularBuffer<Elem, Allocator>::PushBack(const Elem &Item)
  243. {
  244. if (this->IsFull())
  245. this->PopFront();
  246. BaseType::PushBack(Item);
  247. }
  248. template <class Elem, class Allocator>
  249. void CircularBuffer<Elem, Allocator>::PushFront(const Elem &Item)
  250. {
  251. if (this->IsFull())
  252. this->PopBack();
  253. BaseType::PushFront(Item);
  254. }
  255. };
  256. #endif