/* Copyright (c) 2003-2007 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef DLFIFOLIST_HPP #define DLFIFOLIST_HPP #include #include #include "Pool.hpp" /** * Template class used for implementing an * list of object retreived from a pool */ template class DLFifoListImpl { public: /** * List head */ struct Head { Head(); Uint32 firstItem; Uint32 lastItem; #ifdef VM_TRACE bool in_use; #endif inline bool isEmpty() const { return firstItem == RNIL;} }; DLFifoListImpl(P & thePool); bool seizeFirst(Ptr &); bool seizeLast(Ptr &); bool seize(Ptr & ptr) { return seizeLast(ptr);} void release(Ptr &); void release(); // release all void addFirst(Ptr &); void addLast(Ptr &); void add(Ptr & ptr) { addLast(ptr);} /** * Insert object ptr _before_ loc */ void insert(Ptr & ptr, Ptr& loc); void remove(); void remove(Ptr &); void remove(T*); /** * Update i & p value according to i */ void getPtr(Ptr &, Uint32 i) const; /** * Update p value for ptr according to i value */ void getPtr(Ptr &) const ; /** * Get pointer for i value */ T * getPtr(Uint32 i) const ; /** * Update ptr to first element in list * * Return i */ bool first(Ptr &) const ; /** * Update ptr to first element in list * * Return i */ bool last(Ptr &) const ; /** * Get next element * * NOTE ptr must be both p & i */ bool next(Ptr &) const ; /** * Get next element * * NOTE ptr must be both p & i */ bool prev(Ptr &) const ; /** * Check if next exists i.e. this is not last * * NOTE ptr must be both p & i */ bool hasNext(const Ptr &) const; /** * Check if next exists i.e. this is not last * * NOTE ptr must be both p & i */ bool hasPrev(const Ptr &) const; inline bool isEmpty() const { return head.firstItem == RNIL;} /** * Copy list (head) * Will construct to identical lists */ DLFifoListImpl& operator=(const DLFifoListImpl& src){ assert(&thePool == &src.thePool); this->head = src.head; return * this; } protected: Head head; P & thePool; }; template class LocalDLFifoListImpl : public DLFifoListImpl { public: LocalDLFifoListImpl(P & thePool, typename DLFifoListImpl::Head &_src) : DLFifoListImpl(thePool), src(_src) { this->head = src; #ifdef VM_TRACE assert(src.in_use == false); src.in_use = true; #endif } ~LocalDLFifoListImpl(){ #ifdef VM_TRACE assert(src.in_use == true); #endif src = this->head; } private: typename DLFifoListImpl::Head & src; }; template inline DLFifoListImpl::DLFifoListImpl(P & _pool): thePool(_pool) { } template inline DLFifoListImpl::Head::Head() { firstItem = RNIL; lastItem = RNIL; #ifdef VM_TRACE in_use = false; #endif } template inline bool DLFifoListImpl::seizeFirst(Ptr & p) { if (likely(thePool.seize(p))) { addFirst(p); return true; } p.p = NULL; return false; } template inline bool DLFifoListImpl::seizeLast(Ptr & p) { if (likely(thePool.seize(p))) { addLast(p); return true; } p.p = NULL; return false; } template inline void DLFifoListImpl::addFirst(Ptr & p) { Uint32 ff = head.firstItem; p.p->U::prevList = RNIL; p.p->U::nextList = ff; head.firstItem = p.i; if (ff == RNIL) { head.lastItem = p.i; } else { T * t2 = thePool.getPtr(ff); t2->U::prevList = p.i; } } template inline void DLFifoListImpl::addLast(Ptr & p) { T * t = p.p; Uint32 last = head.lastItem; head.lastItem = p.i; t->U::nextList = RNIL; t->U::prevList = last; if(last != RNIL) { T * t2 = thePool.getPtr(last); t2->U::nextList = p.i; } else { head.firstItem = p.i; } } template inline void DLFifoListImpl::insert(Ptr & ptr, Ptr & loc) { Uint32 prev= loc.p->U::prevList; if(loc.i == head.firstItem) { head.firstItem = ptr.i; assert(prev == RNIL); } else { T* t2 = thePool.getPtr(prev); t2->U::nextList = ptr.i; } loc.p->U::prevList = ptr.i; ptr.p->U::prevList = prev; ptr.p->U::nextList = loc.i; } template inline void DLFifoListImpl::remove() { head.firstItem = RNIL; head.lastItem = RNIL; } template inline void DLFifoListImpl::remove(Ptr & p) { remove(p.p); } template inline void DLFifoListImpl::remove(T * t) { Uint32 ni = t->U::nextList; Uint32 pi = t->U::prevList; if(ni != RNIL) { T * t = thePool.getPtr(ni); t->U::prevList = pi; } else { // We are releasing last head.lastItem = pi; } if(pi != RNIL) { T * t = thePool.getPtr(pi); t->U::nextList = ni; } else { // We are releasing first head.firstItem = ni; } } template inline void DLFifoListImpl::release() { Ptr ptr; Uint32 curr = head.firstItem; while(curr != RNIL) { thePool.getPtr(ptr, curr); curr = ptr.p->U::nextList; thePool.release(ptr); } head.firstItem = RNIL; head.lastItem = RNIL; } template inline void DLFifoListImpl::release(Ptr & p) { remove(p.p); thePool.release(p); } template inline void DLFifoListImpl::getPtr(Ptr & p, Uint32 i) const { p.i = i; p.p = thePool.getPtr(i); } template inline void DLFifoListImpl::getPtr(Ptr & p) const { thePool.getPtr(p); } template inline T * DLFifoListImpl::getPtr(Uint32 i) const { return thePool.getPtr(i); } /** * Update ptr to first element in list * * Return i */ template inline bool DLFifoListImpl::first(Ptr & p) const { p.i = head.firstItem; if(p.i != RNIL) { p.p = thePool.getPtr(p.i); return true; } p.p = NULL; return false; } template inline bool DLFifoListImpl::last(Ptr & p) const { p.i = head.lastItem; if(p.i != RNIL) { p.p = thePool.getPtr(p.i); return true; } p.p = NULL; return false; } template inline bool DLFifoListImpl::next(Ptr & p) const { p.i = p.p->U::nextList; if(p.i != RNIL) { p.p = thePool.getPtr(p.i); return true; } p.p = NULL; return false; } template inline bool DLFifoListImpl::prev(Ptr & p) const { p.i = p.p->U::prevList; if(p.i != RNIL) { p.p = thePool.getPtr(p.i); return true; } p.p = NULL; return false; } template inline bool DLFifoListImpl::hasNext(const Ptr & p) const { return p.p->U::nextList != RNIL; } template inline bool DLFifoListImpl::hasPrev(const Ptr & p) const { return p.p->U::prevList != RNIL; } // Specializations template class DLFifoList : public DLFifoListImpl, T, U> { public: DLFifoList(ArrayPool & p) : DLFifoListImpl, T, U>(p) {} }; template class LocalDLFifoList : public LocalDLFifoListImpl,T,U> { public: LocalDLFifoList(ArrayPool & p, typename DLFifoList::Head & _src) : LocalDLFifoListImpl,T,U>(p, _src) {} }; #endif