/* 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 DLLIST_HPP #define DLLIST_HPP #include "ArrayPool.hpp" /** * Template class used for implementing an * list of object retreived from a pool */ template class DLListImpl { public: /** * List head */ struct HeadPOD { Uint32 firstItem; inline bool isEmpty() const { return firstItem == RNIL; } inline void init () { firstItem = RNIL; } }; struct Head : public HeadPOD { Head(); Head& operator=(const HeadPOD& src) { this->firstItem = src.firstItem; return *this; } }; DLListImpl(P& thePool); /** * Allocate an object from pool - update Ptr * * Return i */ bool seize(Ptr &); /** * Allocate object i from pool - update Ptr * * Return i */ bool seizeId(Ptr &, Uint32 i); /** * Check if i is allocated. */ bool findId(Uint32 i) const; /** * Return an object to pool */ void release(Uint32 i); /** * Return an object to pool */ void release(Ptr &); /** * Return all objects to the pool */ void release(); /** * Remove all objects from list */ void remove(); /** * Add object to list * * @NOTE MUST be seized from correct pool */ void add(Ptr &); /** * Add a list to list * @NOTE all elements _must_ be correctly initilized correctly wrt next/prev */ void add(Uint32 first, Ptr & last); /** * Remove object from list * * @NOTE Does not return it to pool */ void remove(Ptr &); /** * Remove object from list * * @NOTE Does not return it to pool */ 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 True if element exists, false otherwise */ bool first(Ptr &) const ; /** * Get next element * * @note ptr must have both p & i values * * @return True if element exists, false otherwise */ bool next(Ptr &) const ; /** * Check if next exists * * @note ptr must have both p & i values * @return True if element exists, false otherwise */ bool hasNext(const Ptr &) const; inline bool isEmpty() const { return head.firstItem == RNIL;} protected: Head head; P & thePool; }; template class LocalDLListImpl : public DLListImpl { public: LocalDLListImpl(P & thePool, typename DLListImpl::HeadPOD & _src) : DLListImpl(thePool), src(_src) { this->head = src; } ~LocalDLListImpl(){ src = this->head; } private: typename DLListImpl::HeadPOD & src; }; template inline DLListImpl::DLListImpl(P & _pool) : thePool(_pool) { } template inline DLListImpl::Head::Head() { this->init(); } /** * Allocate an object from pool - update Ptr * * Return i */ template inline bool DLListImpl::seize(Ptr & p) { if (likely(thePool.seize(p))) { add(p); return true; } return false; } /** * Allocate an object from pool - update Ptr * * Return i */ template inline bool DLListImpl::seizeId(Ptr & p, Uint32 ir) { if (likely(thePool.seizeId(p, ir))) { add(p); return true; } return false; } template inline bool DLListImpl::findId(Uint32 i) const { return thePool.findId(i); } template inline void DLListImpl::add(Ptr & p) { T * t = p.p; Uint32 ff = head.firstItem; t->U::nextList = ff; t->U::prevList = RNIL; head.firstItem = p.i; if(ff != RNIL) { T * t2 = thePool.getPtr(ff); t2->U::prevList = p.i; } } template inline void DLListImpl::add(Uint32 first, Ptr & lastPtr) { Uint32 ff = head.firstItem; head.firstItem = first; lastPtr.p->U::nextList = ff; if(ff != RNIL) { T * t2 = thePool.getPtr(ff); t2->U::prevList = lastPtr.i; } } template inline void DLListImpl::remove(Ptr & p) { remove(p.p); } template inline void DLListImpl::remove(T * p) { T * t = p; Uint32 ni = t->U::nextList; Uint32 pi = t->U::prevList; if(ni != RNIL){ T * tn = thePool.getPtr(ni); tn->U::prevList = pi; } if(pi != RNIL){ T * tp = thePool.getPtr(pi); tp->U::nextList = ni; } else { head.firstItem = ni; } } /** * Return an object to pool */ template inline void DLListImpl::release(Uint32 i) { Ptr p; p.i = i; p.p = thePool.getPtr(i); release(p); } /** * Return an object to pool */ template inline void DLListImpl::release(Ptr & p) { remove(p); thePool.release(p); } template inline void DLListImpl::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; } template inline void DLListImpl::remove() { head.firstItem = RNIL; } template inline void DLListImpl::getPtr(Ptr & p, Uint32 i) const { p.i = i; p.p = thePool.getPtr(i); } template inline void DLListImpl::getPtr(Ptr & p) const { thePool.getPtr(p); } template inline T * DLListImpl::getPtr(Uint32 i) const { return thePool.getPtr(i); } /** * Update ptr to first element in list * * Return i */ template inline bool DLListImpl::first(Ptr & p) const { Uint32 i = head.firstItem; p.i = i; if(i != RNIL) { p.p = thePool.getPtr(i); return true; } p.p = NULL; return false; } template inline bool DLListImpl::next(Ptr & p) const { Uint32 i = p.p->U::nextList; p.i = i; if(i != RNIL){ p.p = thePool.getPtr(i); return true; } p.p = NULL; return false; } template inline bool DLListImpl::hasNext(const Ptr & p) const { return p.p->U::nextList != RNIL; } // Specializations template class DLList : public DLListImpl, T, U> { public: DLList(ArrayPool & p) : DLListImpl, T, U>(p) {} }; template class LocalDLList : public LocalDLListImpl, T, U> { public: LocalDLList(ArrayPool & p, typename DLList::HeadPOD & _src) : LocalDLListImpl, T, U>(p, _src) {} }; #endif