/** * PANDA 3D SOFTWARE * Copyright (c) Carnegie Mellon University. All rights reserved. * * All use of this software is subject to the terms of the revised BSD * license. You should have received a copy of this license along * with this source code in a file named "LICENSE." * * @file circBuffer.I * @author drose * @date 1999-02-08 */ #include "pandabase.h" #include "config_express.h" #include "pnotify.h" /** * */ template INLINE CircBuffer:: CircBuffer() { _in = _out = 0; } /** * */ template INLINE CircBuffer:: ~CircBuffer() { } /** * Returns the number of items currently in the buffer. This can safely be * called without synchronization from either the reader or the writer thread, * but the size may of course vary without warning after the call. */ template INLINE int CircBuffer:: size() const { int diff = _in - _out; return (diff >= 0) ? diff : max_size + 1 + diff; } /** * Returns true if the buffer is empty. It is safe to call this without * synchronization primitives from either the reader or the writer thread, but * the result may vary without warning after the call. */ template INLINE bool CircBuffer:: empty() const { return _in == _out; } /** * Returns true if the buffer is full; if this is true, push_back() will fail. * It is safe to call this without synchronization primitives from either the * reader or the writer thread, but the result may vary without warning after * the call. */ template INLINE bool CircBuffer:: full() const { // return _in == _out-1 || (_in==max_size && _out==0); return ((_in + 1) % (max_size + 1)) == _out; } /** * Returns a reference to the first item in the queue. It is invalid to call * this if empty() is true. It is safe to call this without synchronization * only from the reading thread: the thread that calls pop_front(). */ template INLINE const Thing &CircBuffer:: front() const { nassertr(!empty(), _array[0]); return _array[_out]; } /** * Returns a reference to the first item in the queue. It is invalid to call * this if empty() is true. It is safe to call this without synchronization * only from the reading thread: the thread that calls pop_front(). */ template INLINE Thing &CircBuffer:: front() { nassertr(!empty(), _array[0]); return _array[_out]; } /** * Returns the nth element in the buffer. It is safe to call this without * synchronization only from the reading thread: the thread that calls * pop_front(). */ template INLINE const Thing &CircBuffer:: operator[] (int n) const { nassertr(!empty(), _array[0]); return _array[(_out + n) % (max_size + 1)]; } /** * Returns the nth element in the buffer. It is safe to call this without * synchronization only from the reading thread: the thread that calls * pop_front(). */ template INLINE Thing &CircBuffer:: operator[] (int n) { nassertr(!empty(), _array[0]); return _array[(_out + n) % (max_size + 1)]; } /** * Removes the first item from the buffer. */ template INLINE void CircBuffer:: pop_front() { nassertv(!empty()); // We need to clear out the old element to force its destructor to be // called; it might be important. This will generate yet another UMR // warning in Purify if the default constructor doesn't fully initialize the // class. _array[_out] = Thing(); _out = (_out+1)%(max_size+1); } /** * Returns a reference to the last item in the queue. It is invalid to call * this if empty() is true. It is safe to call this without synchronization * primitives only from the writing thread: the thread that calls push_back(). */ template INLINE const Thing &CircBuffer:: back() const { nassertr(!empty(), _array[0]); return _array[(_in + max_size) % (max_size + 1)]; } /** * Returns a reference to the last item in the queue. It is invalid to call * this if empty() is true. It is safe to call this without synchronization * primitives only from the writing thread: the thread that calls push_back(). */ template INLINE Thing &CircBuffer:: back() { nassertr(!empty(), _array[0]); return _array[(_in + max_size) % (max_size + 1)]; } /** * Adds an item to the end of the buffer. This may fail if full() is true. */ template INLINE void CircBuffer:: push_back(const Thing &t) { if (full()) { express_cat.error() << "Circular buffer is full; cannot add requests.\n"; } else { _array[_in] = t; _in = (_in+1)%(max_size+1); } } /** * Removes all items from the queue. */ template INLINE void CircBuffer:: clear() { _in = _out = 0; }