mirror of https://github.com/stella-emu/stella.git
Added LinkedObjectPool class, which will be used by RewindManager.
Thomas, please contact me for example usage of this class.
This commit is contained in:
parent
bfb79fe289
commit
a8719f6bd6
|
@ -0,0 +1,133 @@
|
|||
//============================================================================
|
||||
//
|
||||
// SSSS tt lll lll
|
||||
// SS SS tt ll ll
|
||||
// SS tttttt eeee ll ll aaaa
|
||||
// SSSS tt ee ee ll ll aa
|
||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#ifndef LINKED_OBJECT_POOL_HXX
|
||||
#define LINKED_OBJECT_POOL_HXX
|
||||
|
||||
#include <list>
|
||||
#include "bspf.hxx"
|
||||
|
||||
/**
|
||||
* A fixed-size object-pool based doubly-linked list that makes use of
|
||||
* multiple STL lists, to reduce frequent (de)allocations.
|
||||
*
|
||||
* This structure acts like a queue (adds to end, removes from beginning),
|
||||
* but also allows for removal at any location in the queue.
|
||||
*
|
||||
* There are two internal lists; one stores active nodes, and the other
|
||||
* stores pool nodes that have been 'deleted' from the active list (note
|
||||
* that no actual deletion takes place; nodes are simply moved from one list
|
||||
* to another). Similarly, when a new node is added to the active list, it
|
||||
* is simply moved from the pool list to the active list.
|
||||
*
|
||||
* NOTE: For efficiency reasons, none of the methods check for overflow or
|
||||
* underflow; that is the responsibility of the caller.
|
||||
*
|
||||
* In the case of methods which wrap the C++ 'splice()' method, the
|
||||
* semantics of splice are followed wrt invalid/out-of-range/etc
|
||||
* iterators. See the applicable documentation for such behaviour.
|
||||
*
|
||||
* @author Stephen Anthony
|
||||
*/
|
||||
namespace Common {
|
||||
|
||||
template <class T, uInt32 CAPACITY = 100>
|
||||
class LinkedObjectPool
|
||||
{
|
||||
public:
|
||||
using iter = typename std::list<T>::iterator;
|
||||
using const_iter = typename std::list<T>::const_iterator;
|
||||
|
||||
/*
|
||||
* Create a pool of size CAPACITY; the active list starts out empty.
|
||||
*/
|
||||
LinkedObjectPool<T, CAPACITY>() {
|
||||
for(uInt32 i = 0; i < CAPACITY; ++i)
|
||||
myPool.emplace_back(T());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new node at the end of the active list, and return a reference to
|
||||
* that node. The reference may then be modified; ie, you're able to change
|
||||
* the data located at that node.
|
||||
*/
|
||||
T& addLast() {
|
||||
myList.splice(myList.end(), myPool, myPool.begin());
|
||||
return myList.back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a reference to the element at the first node.
|
||||
* The reference may not be modified.
|
||||
*/
|
||||
const T& first() const { return myList.front(); }
|
||||
|
||||
/**
|
||||
* Remove a single element at position of the iterator +- the offset.
|
||||
*/
|
||||
void remove(const_iter i, Int32 offset = 0) {
|
||||
myPool.splice(myPool.end(), myList,
|
||||
offset >= 0 ? std::next(i, offset) : std::prev(i, -offset));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a single element by index, offset from the beginning of the list.
|
||||
* (ie, '0' means first element, '1' is second, and so on).
|
||||
*/
|
||||
void remove(uInt32 index) {
|
||||
myPool.splice(myPool.end(), myList, std::next(myList.begin(), index));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to remove the first element in the list.
|
||||
*/
|
||||
void removeFirst() {
|
||||
myPool.splice(myPool.end(), myList, myList.begin());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to remove a range of elements from 'index' to the
|
||||
* end of the list.
|
||||
*/
|
||||
void removeLast(uInt32 index) {
|
||||
myPool.splice(myPool.end(), myList, std::next(myList.begin(), index), myList.end());
|
||||
}
|
||||
|
||||
/** Access the list with iterators, just as you would a normal C++ STL list */
|
||||
iter begin() { return myList.begin(); }
|
||||
iter end() { return myList.end(); }
|
||||
const_iter begin() const { return myList.cbegin(); }
|
||||
const_iter end() const { return myList.cend(); }
|
||||
|
||||
uInt32 size() const { return myList.size(); }
|
||||
bool empty() const { return size() == 0; }
|
||||
bool full() const { return size() >= CAPACITY; }
|
||||
|
||||
private:
|
||||
std::list<T> myList, myPool;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
LinkedObjectPool(const LinkedObjectPool&) = delete;
|
||||
LinkedObjectPool(LinkedObjectPool&&) = delete;
|
||||
LinkedObjectPool& operator=(const LinkedObjectPool&) = delete;
|
||||
LinkedObjectPool& operator=(LinkedObjectPool&&) = delete;
|
||||
};
|
||||
|
||||
} // Namespace Common
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue