/* 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 SLLIST_HPP #define SLLIST_HPP #include "ArrayPool.hpp" #include /** * Template class used for implementing an * list of object retreived from a pool */ template class SLListImpl { public: /** * List head */ struct HeadPOD { Uint32 firstItem; void init() { firstItem = RNIL;} }; struct Head : public HeadPOD { Head(); Head& operator= (const HeadPOD& src) { this->firstItem = src.firstItem; return *this; } }; SLListImpl(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); /** * Allocate nobjects from pool * * Return i value of first object allocated or RNIL if fails */ bool seizeN(Ptr &, Uint32 n); /** * Return all objects to the pool */ void release(); /** * Remove all object from list but don't return to pool */ void remove(); /** * 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 ; /** * Get next element * * NOTE ptr must be both p & i */ bool next(Ptr &) const ; /** * Check if next exists * * NOTE ptr must be both p & i */ bool hasNext(const Ptr &) const; /** * Add */ void add(Ptr & p){ p.p->U::nextList = head.firstItem; head.firstItem = p.i; } /** * 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 */ bool remove_front(Ptr &); Uint32 noOfElements() const { Uint32 c = 0; Uint32 i = head.firstItem; while(i != RNIL){ c++; const T * t = thePool.getPtr(i); i = t->U::nextList; } return c; } /** * Print * (Run operator NdbOut<< on every element) */ void print(NdbOut & out) { out << "firstItem = " << head.firstItem << endl; Uint32 i = head.firstItem; while(i != RNIL){ T * t = thePool.getPtr(i); t->print(out); out << " "; i = t->next; } } inline bool empty() const { return head.firstItem == RNIL;} protected: Head head; P & thePool; }; template class LocalSLListImpl : public SLListImpl { public: LocalSLListImpl(P & thePool, typename SLListImpl::HeadPOD & _src) : SLListImpl(thePool), src(_src) { this->head = src; } ~LocalSLListImpl(){ src = this->head; } private: typename SLListImpl::HeadPOD & src; }; template inline SLListImpl::SLListImpl(P & _pool): thePool(_pool) { } template inline SLListImpl::Head::Head() { this->init(); } template inline bool SLListImpl::seize(Ptr & p) { thePool.seize(p); T * t = p.p; Uint32 ff = head.firstItem; if(p.i != RNIL) { t->U::nextList = ff; head.firstItem = p.i; return true; } return false; } template inline bool SLListImpl::seizeId(Ptr & p, Uint32 ir) { thePool.seizeId(p, ir); T * t = p.p; Uint32 ff = head.firstItem; if(p.i != RNIL) { t->U::nextList = ff; head.firstItem = p.i; return true; } return false; } template inline bool SLListImpl::seizeN(Ptr & p, Uint32 n) { for(Uint32 i = 0; i < n; i++) { if(seize(p) == RNIL) { /** * Failure */ for(; i > 0; i--) { p.i = head.firstItem; thePool.getPtr(p); head.firstItem = p.p->U::nextList; thePool.release(p); } return false; } } /** * Success */ p.i = head.firstItem; p.p = thePool.getPtr(head.firstItem); return true; } template inline void SLListImpl::remove() { head.firstItem = RNIL; } template inline bool SLListImpl::remove_front(Ptr & p) { p.i = head.firstItem; if (p.i != RNIL) { p.p = thePool.getPtr(p.i); head.firstItem = p.p->U::nextList; return true; } return false; } template inline void SLListImpl::add(Uint32 first, Ptr & last) { last.p->U::nextList = head.firstItem; head.firstItem = first; } template inline void SLListImpl::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 SLListImpl::getPtr(Ptr & p, Uint32 i) const { p.i = i; p.p = thePool.getPtr(i); } template inline void SLListImpl::getPtr(Ptr & p) const { thePool.getPtr(p); } template inline T * SLListImpl::getPtr(Uint32 i) const { return thePool.getPtr(i); } /** * Update ptr to first element in list * * Return i */ template inline bool SLListImpl::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 SLListImpl::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 SLListImpl::hasNext(const Ptr & p) const { return p.p->U::nextList != RNIL; } // Specializations template class SLList : public SLListImpl, T, U> { public: SLList(ArrayPool & p) : SLListImpl, T, U>(p) {} }; template class LocalSLList : public LocalSLListImpl,T,U> { public: LocalSLList(ArrayPool & p, typename SLList::Head & _src) : LocalSLListImpl,T,U>(p, _src) {} }; #endif