📄 queuetemplate.h
字号:
//// Copyright (c) 2003 by Istv醤 V醨adi//// This file is part of dxr3Player, a DVD player written specifically // for the DXR3 (aka Hollywood+) decoder card.// 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; either version 2 of the License, or// (at your option) any later version.//// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA#ifndef DXR3PLAYER_SCHED_QUEUETEMPLATE_H#define DXR3PLAYER_SCHED_QUEUETEMPLATE_H//------------------------------------------------------------------------------#include "sched/Scheduler.h"#include "sched/WaitCondition.h"//------------------------------------------------------------------------------namespace sched {//------------------------------------------------------------------------------/** * Template for queues. */template <typename valueT>class QueueTemplate{public: /** * The value type. */ typedef valueT valueType;private: /** * The name of the queue. */ const char* name; /** * The capacity of the queue. */ size_t capacity; /** * The invalid value. */ valueT invalidValue; /** * The elements in the queue. */ valueT* elements; /** * The index of the first element inserted. */ size_t firstIndex; /** * The size of the queue. */ size_t size; /** * The condition signalling if one can put a value into the queue. */ WaitCondition canPut; /** * The condition signalling if one can get a value from the queue. */ WaitCondition canGet;public: /** * Construct a queue with the given capacity. It should be * positive. */ explicit QueueTemplate(const char* name, size_t capacity, valueT invalidValue = valueT()); /** * Destruct the queue. */ virtual ~QueueTemplate(); /** * Reset the queue. It removes all entries. */ virtual void reset(); /** * Check if the queue is empty or not. */ bool isEmpty() const; /** * Check if the queue is full or not. */ bool isFull() const; /** * Get the size of the queue, i.e. the number of elements in it. */ size_t getSize() const; /** * Put the given value into the queue. If there is space in the * queue, the value will be put into it and the function returns * immediately. Otherwise an interruptible wait begins. * * @param timeout if given, the waiting will last at most until * the given time has passed * * @return if the value could be put into the queue. */ bool put(valueT value, millis_t timeout = INVALID_MILLIS); /** * Put the given value into the queue. If there is space in the * queue, it yields the processor, and puts the value into the * queue, when it gets the control back. Otherwise an * interruptible wait begins. * * @param timeout if given, the waiting will last at most until * the given time has passed * * @return if the value could be put into the queue. */ bool putYielding(valueT value, millis_t timeout = INVALID_MILLIS); /** * Get a value from the queue. If the queue can be consumed, the * value will be returned immediately. Otherwise an interruptible * wait begins. * * @param timeout if given, the waiting will last at most until * the given time has passed * * @return the value if it could be retrieved or invalidValue if not. */ valueT get(millis_t timeout = INVALID_MILLIS); /** * Get a value from the queue. If the queue can be consumed, it * will yield the processor and return the value when it gets the * control back. Otherwise an interruptible wait begins. * * @param timeout if given, the waiting will last at most until * the given time has passed * * @return the value if it could be retrieved or invalidValue if not. */ valueT getYielding(millis_t timeout = INVALID_MILLIS); /** * Flush the queue. * * This implementation does nothing, but queues requiring a * minimal fill level before signalling the consumer may want to * use it to force this signalling, even before the minimal fill level. */ virtual void flush(); /** * Print the values. */ void printValues() const;protected: /** * Check if a new entry can be put in the queue. With this * implementation, it is possible if the queue is not full. */ virtual bool canProduce(); /** * Schedule the producer, if possible. */ void scheduleProducer(); /** * Check if the queue can be consumed. With this implementation, * the queue can be consumed if it is not empty. But other * implementations may have other requirements, such as achieving * a minimal number of entries. */ virtual bool canConsume(); /** * Schedule the consumer, if possible. */ void scheduleConsumer();private: /** * Enlarge the storage. */ void enlargeElements(); /** * Put the value into the queue. */ bool put(valueT value, millis_t timeout, bool yielding); /** * Get a value from the queue */ valueT get(millis_t timeout, bool yielding);};//------------------------------------------------------------------------------// Template definitions//------------------------------------------------------------------------------template <typename valueT>QueueTemplate<valueT>::QueueTemplate(const char* name, size_t capacity, valueT invalidValue) : name(name), capacity(capacity), invalidValue(invalidValue), elements(new valueT[capacity]), firstIndex(0), size(0), canPut(name, "canPut"), canGet(name, "canGet"){ assert(capacity>0);}//------------------------------------------------------------------------------template <typename valueT>QueueTemplate<valueT>::~QueueTemplate(){ delete[] elements;}//------------------------------------------------------------------------------template <typename valueT>void QueueTemplate<valueT>::reset(){ while(size>0) { (elements+firstIndex)->~valueT(); ++firstIndex; firstIndex%=capacity; --size; } scheduleProducer();}//------------------------------------------------------------------------------template <typename valueT>inline bool QueueTemplate<valueT>::isEmpty() const{ return size==0;}//------------------------------------------------------------------------------template <typename valueT>inline bool QueueTemplate<valueT>::isFull() const{ return size>=capacity;}//------------------------------------------------------------------------------template <typename valueT>inline size_t QueueTemplate<valueT>::getSize() const{ return size;}//------------------------------------------------------------------------------template <typename valueT>inline bool QueueTemplate<valueT>::put(valueT value, millis_t timeout){ return put(value, timeout, false);}//------------------------------------------------------------------------------template <typename valueT>inline bool QueueTemplate<valueT>::putYielding(valueT value, millis_t timeout){ return put(value, timeout, true);}//------------------------------------------------------------------------------template <typename valueT>inline valueT QueueTemplate<valueT>::get(millis_t timeout){ return get(timeout, false);}//------------------------------------------------------------------------------template <typename valueT>inline valueT QueueTemplate<valueT>::getYielding(millis_t timeout){ return get(timeout, true);}//------------------------------------------------------------------------------template <typename valueT>void QueueTemplate<valueT>::flush(){}//------------------------------------------------------------------------------template <typename valueT>void QueueTemplate<valueT>::printValues() const{ char buffer[256]; for(size_t i = 0; i<size; ++i) { elements[(i+firstIndex)%capacity]->getDescription(buffer, sizeof(buffer)); Log::debug(" element #%u: %s\n", i, buffer); }}//------------------------------------------------------------------------------template <typename valueT>bool QueueTemplate<valueT>::canProduce(){ return !isFull();}//------------------------------------------------------------------------------template <typename valueT>void QueueTemplate<valueT>::scheduleProducer(){ if (canProduce()) { canPut.set(); }}//------------------------------------------------------------------------------template <typename valueT>bool QueueTemplate<valueT>::canConsume(){ return !isEmpty();}//------------------------------------------------------------------------------template <typename valueT>void QueueTemplate<valueT>::scheduleConsumer(){ if (canConsume()) { canGet.set(); }}//------------------------------------------------------------------------------template <typename valueT>bool QueueTemplate<valueT>::put(valueT value, millis_t timeout, bool yielding){ if (canProduce() && yielding) { Scheduler::yield(name); } if (!canProduce()) { Scheduler::waitInterruptible(canPut, timeout); } if (!canProduce() || Scheduler::isInterrupted()) return false; size_t nextIndex = (firstIndex + size)%capacity; new (static_cast<void*>(elements + nextIndex)) valueT(value); ++size; scheduleConsumer(); return true;}//------------------------------------------------------------------------------template <typename valueT>valueT QueueTemplate<valueT>::get(millis_t timeout, bool yielding){ if (canConsume() && yielding) { Scheduler::yield(name); } if (!canConsume()) { Scheduler::waitInterruptible(canGet, timeout); } if (!canConsume() || Scheduler::isInterrupted()) return invalidValue; valueT v(elements[firstIndex]); (elements+firstIndex)->~valueT(); ++firstIndex; firstIndex%=capacity; --size; scheduleProducer(); return v;}//------------------------------------------------------------------------------} /* namespace sched *///------------------------------------------------------------------------------#endif // DXR3PLAYER_SCHED_QUEUETEMPLATE_H// Local variables:// mode: c++// End:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -