00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00035 #ifndef _BUFFERRESERVOIR_H
00036 #define _BUFFERRESERVOIR_H
00037
00038
00039 #include <deque>
00040 #include <stdexcept>
00041
00042 namespace simth {
00043
00044
00049 class locking_error : public std::runtime_error
00050 {
00051 public:
00052 locking_error(const char* messages)
00053 : std::runtime_error(messages) {};
00054
00055 };
00056
00059 template<class T>
00060 class BufferReservoir
00061 {
00062 private:
00063 std::deque<T*> reservoir;
00064 size_t numFilled;
00065
00066 bool locked;
00067 bool isLocked() const {return locked;}
00068 void lock();
00069 void unlock();
00070
00071 void invariante();
00072 public:
00073
00074 BufferReservoir(size_t size = 0);
00075 ~BufferReservoir();
00076 T* const getFreeBuffer();
00077 T* const getFilledBuffer();
00078
00079 void giveBufferFree() {unlock();}
00080
00081 };
00082
00083 template<class T>
00084 inline BufferReservoir<T>::BufferReservoir(size_t size)
00085 : reservoir(std::deque(size)),numFilled(0), locked(false)
00086 {
00087 for(size_t i=0; i < reservoir.size();++i) {
00088 reservoir[i] = new T(0);
00089 }
00090 }
00091
00092 template<class T>
00093 inline BufferReservoir<T>::~BufferReservoir( )
00094 {
00095 if(std::uncaught_exception()) {
00096 try {
00097 for(size_t i=0; i < reservoir.size();++i) {
00098 delete reservoir[i];
00099 }
00100 }
00101 catch(...) {
00102 cerr<<"inline BufferReservoir::~BufferReservoir( ) : error 1";
00103 }
00104 }
00105 else {
00106 for(size_t i=0; i < reservoir.size();++i) {
00107 delete reservoir[i];
00108 }
00109 }
00110 }
00111
00112 template<class T>
00113 inline void BufferReservoir<T>::invariante()
00114 {
00115 if(DEBUG) {
00116 if(numFilled > reservoir.size()) {
00117 throw std::runtime_error("inline void BufferReservoir::invariante()"
00118 " : error 2");
00119 }
00120 }
00121 }
00122
00123 template<class T>
00124 inline T* const BufferReservoir<T>::getFreeBuffer()
00125 {
00126 invariante();
00127 if(numFilled == reservoir.size()) {
00128 T* helpPtr = new T(0);
00129 reservoir.push_back(helpPtr);
00130 }
00131 numFilled++;
00132
00133
00134 return reservoir[numFilled];
00135 }
00136
00137 template<class T>
00138 inline T* const BufferReservoir<T>::getFilledBuffer()
00139 {
00140 invariante();
00141 if(isLocked) {
00142 throw locking_error("BufferReservoir is Locked");
00143 }
00144 return reservoir.front();
00145 locked = true;
00146 }
00147
00148 template<class T>
00149 inline void BufferReservoir<T>::lock()
00150 {
00151 locked = true;
00152 }
00153
00154 template<class T>
00155 inline void BufferReservoir<T>::unlock()
00156 {
00157 if(isLocked()) {
00158 T* const helpPtr = reservoir.front();
00159 reservoir.pop_front();
00160 reservoir.push_back(helpPtr);
00161 locked=false;
00162 }
00163 else {
00164 throw std::runtime_error("inline void BufferReservoir::unlock() : "
00165 " BufferReservoir is not locked");
00166 }
00167 numFilled--;
00168 invariante();
00169 }
00170
00171
00172 }
00173
00174 #endif // _BUFFERRESERVOIR_H