/* Copyright (C) 2014 InfiniDB, Inc. 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. */ /****************************************************************************** * $Id: datalistimpl.h 9655 2013-06-25 23:08:13Z xlou $ * *****************************************************************************/ /** @file * class XXX interface */ #include #include #include #include #include #include #include "datalist.h" #pragma once namespace joblist { /** @brief class DataListImpl * */ template class DataListImpl : public DataList { public: DataListImpl(uint32_t numConsumers); DataListImpl(const DataListImpl& dl); virtual ~DataListImpl(); DataListImpl& operator=(const DataListImpl& dl); // derived classes need to lock around these fcns virtual void insert(const element_t& e); virtual void insert(const std::vector& v); virtual uint64_t getIterator(); virtual bool next(uint64_t it, element_t* e); virtual void setNumConsumers(uint32_t); virtual uint32_t getNumConsumers() const; void resetNumConsumers(uint32_t numConsumers); protected: bool endOfData(uint64_t id) const; void eraseUpTo(uint64_t id); void reset(); virtual void shrink(); typename container_t::iterator iInsert(const element_t& e); container_t* c; typename container_t::iterator* cIterators; uint64_t numConsumers; uint64_t itIndex; private: explicit DataListImpl(); }; template DataListImpl::DataListImpl() : DataList(), c(0), cIterators(0), numConsumers(0), itIndex(0) { } template void DataListImpl::setNumConsumers(uint32_t nc) { resetNumConsumers(nc); } template uint32_t DataListImpl::getNumConsumers() const { return numConsumers; } template void DataListImpl::resetNumConsumers(uint32_t nc) { if (itIndex != 0) throw std::logic_error( "DataListImpl::resetNumConsumers(): attempt to change numConsumers " "after iterators have been issued"); uint32_t i; numConsumers = nc; delete[] cIterators; cIterators = new typename container_t::iterator[numConsumers]; for (i = 0; i < numConsumers; i++) cIterators[i] = c->end(); } template DataListImpl::DataListImpl(uint32_t nc) : DataList() { uint32_t i; numConsumers = nc; itIndex = 0; c = new container_t(); cIterators = new typename container_t::iterator[numConsumers]; for (i = 0; i < numConsumers; i++) cIterators[i] = c->end(); } template DataListImpl::DataListImpl(const DataListImpl& dl) : DataList(dl) { int i; c = dl.c; numConsumers = dl.numConsumers; itIndex = dl.itIndex; // delete [] cIterators; cIterators = new typename container_t::iterator[numConsumers]; for (i = 0; i < numConsumers; i++) cIterators[i] = dl.cIterators[i]; }; template DataListImpl::~DataListImpl() { delete c; delete[] cIterators; }; // lock at a higher level template DataListImpl& DataListImpl::operator=( const DataListImpl& dl) { uint64_t i; static_cast >(*this) = static_cast >(dl); delete c; c = dl.c; numConsumers = dl.numConsumers; itIndex = dl.itIndex; delete[] cIterators; cIterators = new typename container_t::iterator[numConsumers]; for (i = 0; i < numConsumers; i++) cIterators[i] = dl.cIterators[i]; return *this; }; template uint64_t DataListImpl::getIterator() { if (itIndex >= numConsumers) { std::ostringstream oss; oss << "DataListImpl::getIterator(): caller attempted to grab too many iterators: " << "have " << numConsumers << " asked for " << (itIndex + 1); throw std::logic_error(oss.str().c_str()); } cIterators[itIndex] = c->begin(); return itIndex++; } template inline void DataListImpl::insert(const element_t& e) { c->insert(c->end(), e); } template inline void DataListImpl::insert(const std::vector& v) { if (typeid(container_t) == typeid(std::vector)) { std::vector* vc = (std::vector*)c; vc->insert(vc->end(), v.begin(), v.end()); } else throw std::logic_error("insert(vector) isn't supported for non-vector-based DLs yet"); } template inline typename container_t::iterator DataListImpl::iInsert(const element_t& e) { return c->insert(c->end(), e); } template inline bool DataListImpl::next(uint64_t id, element_t* e) { // idbassert(id < numConsumers); if (c == 0 || cIterators[id] == c->end()) return false; *e = *(cIterators[id]); cIterators[id]++; return true; } template bool DataListImpl::endOfData(uint64_t id) const { idbassert(id < numConsumers); return (cIterators[id] == c->end()); } template void DataListImpl::eraseUpTo(uint64_t id) { idbassert(id < numConsumers); #ifdef DEBUG uint64_t i; typename container_t::iterator it; for (it = c->begin(), i = 0; it != cIterators[id]; it++, i++) ; std::cout << "DLI: erasing " << i << " elements" << std::endl; #endif c->erase(c->begin(), cIterators[id]); }; template void DataListImpl::reset() { uint64_t i; delete c; c = new container_t(); for (i = 0; i < numConsumers; i++) cIterators[i] = c->begin(); } template void DataListImpl::shrink() { delete c; c = 0; } } // namespace joblist