Sirikata
libcore/include/sirikata/core/util/CircularBuffer.hpp
Go to the documentation of this file.
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_