/* queue.h */ /** * Copyright - See the COPYRIGHT that is included with this distribution. * EPICS pvData is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. */ /** * @author mrk */ #ifndef QUEUE_H #define QUEUE_H #include #include #include #include namespace epics { namespace pvData { /** * @brief Template class for a bounded queue. * * An instance can make a queueElement be any class desired * but must create a std::vector of shared_ptr to queueElements. */ template class Queue { public: POINTER_DEFINITIONS(Queue); typedef std::tr1::shared_ptr queueElementPtr; typedef std::vector queueElementPtrArray; /** * Constructor * @param elementArray The vector of shared_ptr to queue elements. */ Queue(queueElementPtrArray & elementArray); /** * Destructor */ virtual ~Queue(); /** * Clear the queue. */ void clear(); /** * get the capacity of the queue, i. e. number of queue elements, * @return The capacity. */ int capacity(); /** * Get the number of free elements in the queue. * @return The number. */ int getNumberFree(); /** * Get the number of used elements in the queue. * This is the number that have been setUsed but not released. * @return The number. */ int getNumberUsed(); /** * Get the next free element. * @return a shared_ptr to the queue element. * This is null if queue was full. */ queueElementPtr & getFree(); /** * Set the element returned by getFree as used. * Until this is called getUsed will not return it. * @param element The element. It must be the element returned * by the most recent call to getUsed. */ void setUsed(queueElementPtr const &element); /** * Get the oldest used element; * @return a shared_ptr to the queue element. * This is null if no used element is available.` */ queueElementPtr & getUsed(); /** * Release the element obtained by the most recent call to getUsed. * @param element The element. */ void releaseUsed(queueElementPtr const &element); private: queueElementPtr nullElement; queueElementPtrArray elements; // TODO use size_t instead int size; int numberFree; int numberUsed; int nextGetFree; int nextSetUsed; int nextGetUsed; int nextReleaseUsed; }; template Queue::Queue(std::vector &xxx) : size(static_cast(xxx.size())), numberFree(size), numberUsed(0), nextGetFree(0), nextSetUsed(0), nextGetUsed(0), nextReleaseUsed(0) { elements.swap(xxx); } template Queue::~Queue(){} template int Queue::capacity(){return size;} template int Queue::getNumberFree(){return numberFree;} template int Queue::getNumberUsed(){return numberUsed;} template void Queue::clear() { numberFree = size; numberUsed = 0; nextGetFree = 0; nextSetUsed = 0; nextGetUsed = 0; nextReleaseUsed = 0; } template std::tr1::shared_ptr & Queue::getFree() { if(numberFree==0) return nullElement; numberFree--; int ind = nextGetFree; std::tr1::shared_ptr queueElement = elements[nextGetFree++]; if(nextGetFree>=size) nextGetFree = 0; return elements[ind]; } template void Queue::setUsed(std::tr1::shared_ptr const &element) { if(element!=elements[nextSetUsed++]) { throw std::logic_error("not correct queueElement"); } numberUsed++; if(nextSetUsed>=size) nextSetUsed = 0; } template std::tr1::shared_ptr & Queue::getUsed() { if(numberUsed==0) return nullElement; int ind = nextGetUsed; std::tr1::shared_ptr queueElement = elements[nextGetUsed++]; if(nextGetUsed>=size) nextGetUsed = 0; return elements[ind]; } template void Queue::releaseUsed(std::tr1::shared_ptr const &element) { if(element!=elements[nextReleaseUsed++]) { throw std::logic_error( "not queueElement returned by last call to getUsed"); } if(nextReleaseUsed>=size) nextReleaseUsed = 0; numberUsed--; numberFree++; } }} #endif /* QUEUE_H */