/* Copyright (c) 2003, 2006 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 SLFIFOLIST_HPP #define SLFIFOLIST_HPP #include #include #include "Pool.hpp" /** * Template class used for implementing an * list of object retreived from a pool */ template class SLFifoListImpl { public: /** * List head */ struct Head { Head(); Uint32 firstItem; Uint32 lastItem; #ifdef VM_TRACE bool in_use; #endif inline bool isEmpty() const { return firstItem == RNIL;} }; SLFifoListImpl(P & thePool); bool seizeFirst(Ptr &); bool seizeLast(Ptr &); bool seize(Ptr & ptr) { return seizeLast(ptr);} void releaseFirst(Ptr &); void addFirst(Ptr &); void addLast(Ptr &); void removeFirst(Ptr &); /** * 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 ; /** * Check if next exists i.e. this is not last * * NOTE ptr must be both p & i */ bool hasNext(const Ptr &) const; inline bool isEmpty() const { return head.firstItem == RNIL;} protected: Head head; P & thePool; }; template class LocalSLFifoListImpl : public SLFifoListImpl { public: LocalSLFifoListImpl(P & thePool, typename SLFifoListImpl::Head &_src) : SLFifoListImpl(thePool), src(_src) { this->head = src; #ifdef VM_TRACE assert(src.in_use == false); src.in_use = true; #endif } ~LocalSLFifoListImpl(){ #ifdef VM_TRACE assert(src.in_use == true); #endif src = this->head; } private: typename SLFifoListImpl::Head & src; }; template inline SLFifoListImpl::SLFifoListImpl(P & _pool): thePool(_pool) { } template inline SLFifoListImpl::Head::Head() { firstItem = RNIL; lastItem = RNIL; #ifdef VM_TRACE in_use = false; #endif } template inline bool SLFifoListImpl::seizeFirst(Ptr & p) { if (likely(thePool.seize(p))) { addFirst(p); return true; } p.p = NULL; return false; } template inline bool SLFifoListImpl::seizeLast(Ptr & p) { if (likely(thePool.seize(p))) { addLast(p); return true; } p.p = NULL; return false; } template inline void SLFifoListImpl::addFirst(Ptr & p) { Uint32 first = head.firstItem; head.firstItem = p.i; if (first == RNIL) { head.lastItem = p.i; } p.p->U::nextList = first; } template inline void SLFifoListImpl::addLast(Ptr & p) { T * t = p.p; Uint32 last = head.lastItem; t->U::nextList = RNIL; head.lastItem = p.i; if(last != RNIL) { T * t2 = thePool.getPtr(last); t2->U::nextList = p.i; } else { head.firstItem = p.i; } } template inline void SLFifoListImpl::removeFirst(Ptr & p) { Uint32 first = head.firstItem; Uint32 last = head.lastItem; assert(p.i == first); if (first != last) { head.firstItem = p.p->U::nextList; } else { head.firstItem = head.lastItem = RNIL; } } template inline void SLFifoListImpl::releaseFirst(Ptr & p) { removeFirst(p); thePool.release(p); } template inline void SLFifoListImpl::getPtr(Ptr & p, Uint32 i) const { p.i = i; p.p = thePool.getPtr(i); } template inline void SLFifoListImpl::getPtr(Ptr & p) const { thePool.getPtr(p); } template inline T * SLFifoListImpl::getPtr(Uint32 i) const { return thePool.getPtr(i); } /** * Update ptr to first element in list * * Return i */ template inline bool SLFifoListImpl::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 SLFifoListImpl::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 SLFifoListImpl::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 SLFifoListImpl::hasNext(const Ptr & p) const { return p.p->U::nextList != RNIL; } // Specializations template class SLFifoList : public SLFifoListImpl, T, U> { public: SLFifoList(ArrayPool & p) : SLFifoListImpl, T, U>(p) {} }; template class LocalSLFifoList : public LocalSLFifoListImpl,T,U> { public: LocalSLFifoList(ArrayPool & p, typename SLFifoList::Head & _src) : LocalSLFifoListImpl,T,U>(p, _src) {} }; #endif