Sirikata
|
00001 // Copyright (c) 2011 Sirikata Authors. All rights reserved. 00002 // Use of this source code is governed by a BSD-style license that can 00003 // be found in the LICENSE file. 00004 00005 #ifndef _SIRIKATA_CORE_UTIL_CIRCULAR_BUFFER_HPP_ 00006 #define _SIRIKATA_CORE_UTIL_CIRCULAR_BUFFER_HPP_ 00007 00008 #include <sirikata/core/util/Platform.hpp> 00009 00010 00011 namespace Sirikata { 00012 00018 template<typename DataType> 00019 class CircularBuffer { 00020 public: 00024 typedef std::pair<bool, DataType> OptionalReturnData; 00025 00027 CircularBuffer(std::size_t cap) 00028 : mData(cap), 00029 mStart(0), mCount(0) 00030 { 00031 } 00035 CircularBuffer(std::size_t cap, const DataType& v) 00036 : mData(cap, v), 00037 mStart(0), mCount(cap) 00038 { 00039 } 00040 00041 std::size_t size() const { return mCount; } 00042 std::size_t capacity() const { return mData.size(); } 00043 bool empty() const { return mCount == 0; } 00044 bool full() const { return mCount == capacity(); } 00045 00047 OptionalReturnData push(const DataType& v) { 00048 OptionalReturnData ret(false, DataType()); 00049 if (full()) { 00050 ret.first = true; 00051 ret.second = pop(); 00052 } 00053 00054 mData[safeIdx(mStart, mCount)] = v; 00055 mCount++; 00056 00057 return ret; 00058 } 00059 00061 DataType pop() { 00062 std::size_t old_start_idx = mStart; 00063 mStart = safeIdx(mStart, 1); 00064 mCount = safeIdx(mCount, -1); 00065 return mData[old_start_idx]; 00066 } 00067 00068 const DataType& front() const { 00069 assert(!empty()); 00070 return mData[mStart]; 00071 } 00072 DataType& front() { 00073 assert(!empty()); 00074 return mData[mStart]; 00075 } 00076 00077 const DataType& back() const { 00078 assert(!empty()); 00079 return mData[safeIdx(mStart+mCount, -1)]; 00080 } 00081 DataType& back() { 00082 assert(!empty()); 00083 return mData[safeIdx(mStart+mCount, -1)]; 00084 } 00085 00086 DataType& operator[](std::size_t i) { 00087 assert(i < size()); 00088 return mData[safeIdx(mStart, i)]; 00089 } 00090 const DataType& operator[](std::size_t i) const { 00091 assert(i < size()); 00092 return mData[safeIdx(mStart, i)]; 00093 } 00094 00095 private: 00096 inline std::size_t safeIdx(std::size_t i, int32 offset) const { 00097 while(offset < 0) 00098 offset += capacity(); 00099 return ((i+offset) % capacity()); 00100 } 00101 00102 std::vector<DataType> mData; 00103 // The first valid element 00104 std::size_t mStart; 00105 // Current number of elements 00106 std::size_t mCount; 00107 }; // class CircularBuffer 00108 00109 } // namespace Sirikata 00110 00111 00112 #endif //_SIRIKATA_CORE_UTIL_CIRCULAR_BUFFER_HPP_