| [1670] | 1 | // This may look like C code, but it is really -*- C++ -*- | 
|---|
| [1738] | 2 |  | 
|---|
|  | 3 | // ArchTOIPipe           (C)     CEA/DAPNIA/SPP IN2P3/LAL | 
|---|
|  | 4 | //                               Eric Aubourg | 
|---|
|  | 5 | //                               Christophe Magneville | 
|---|
|  | 6 | //                               Reza Ansari | 
|---|
| [1944] | 7 | // $Id: toisegment.h,v 1.18 2002-03-23 23:05:22 aubourg Exp $ | 
|---|
| [1738] | 8 |  | 
|---|
| [1670] | 9 | #ifndef TOISEGMENT_H | 
|---|
|  | 10 | #define TOISEGMENT_H | 
|---|
|  | 11 |  | 
|---|
| [1766] | 12 | #include "config.h" | 
|---|
|  | 13 | #include <vector> | 
|---|
|  | 14 | #include <set> | 
|---|
| [1671] | 15 |  | 
|---|
| [1670] | 16 | #include "toi.h" | 
|---|
|  | 17 |  | 
|---|
|  | 18 | // ------------ TOISegmented ------------------------------ | 
|---|
|  | 19 | // Classe de TOI pour echantillonage regulier, avec buffer | 
|---|
|  | 20 | // segmente pour optimiser le multithread et limiter les | 
|---|
|  | 21 | // verrous. | 
|---|
|  | 22 | // Il faut que les fournisseurs fassent arriver les donnees | 
|---|
|  | 23 | // par samplenum croissant et continu. | 
|---|
|  | 24 | // -------------------------------------------------------- | 
|---|
|  | 25 |  | 
|---|
|  | 26 | class TOISegmented : public TOIRegular { | 
|---|
|  | 27 | public: | 
|---|
| [1787] | 28 | TOISegmented(int bufsz=1024, int maxseg=20); | 
|---|
|  | 29 | TOISegmented(string nm, int bufsz=1024, int maxseg=20); | 
|---|
|  | 30 | TOISegmented(char* cnm, int bufsz=1024, int maxseg=20); | 
|---|
| [1670] | 31 | ~TOISegmented(); | 
|---|
|  | 32 |  | 
|---|
| [1689] | 33 | virtual double        getData(int i); | 
|---|
|  | 34 | virtual void          getData(int i, double& data,  uint_8& flag); | 
|---|
| [1743] | 35 | virtual void          getData(int i, int n, double* data, uint_8* flg=0); | 
|---|
| [1689] | 36 | virtual void          putData(int i, double  value, uint_8  flag=0); | 
|---|
| [1743] | 37 | virtual void          putData(int i, int n, double const* val, uint_8 const* flg=0); | 
|---|
| [1689] | 38 | virtual void          wontNeedBefore(int i); | 
|---|
|  | 39 | virtual void          putDone(); | 
|---|
| [1692] | 40 | virtual void          addConsumer(TOIProcessor*); | 
|---|
| [1689] | 41 |  | 
|---|
| [1690] | 42 | // Methodes ignorees car on reimplemente les methodes de base | 
|---|
| [1689] | 43 | virtual DataStatus    isDataAvail(int iStart, int iEnd); | 
|---|
|  | 44 | virtual DataStatus    isDataAvail(int i); | 
|---|
| [1754] | 45 | virtual DataStatus isDataAvailNL(int i); | 
|---|
| [1689] | 46 | virtual DataStatus    isDataAvailNL(int iStart, int iEnd); // abstract | 
|---|
|  | 47 | virtual void          waitForData(int iStart, int iEnd); | 
|---|
|  | 48 | virtual void          waitForData(int i); | 
|---|
|  | 49 | virtual void          waitForAnyData(); | 
|---|
|  | 50 | virtual int           nextDataAvail(int iAfter); // abstract | 
|---|
|  | 51 | virtual bool          hasSomeData(); // abstract | 
|---|
|  | 52 | virtual void          doGetData(int i, double& data, uint_8& flag); // abs | 
|---|
|  | 53 | virtual void          doPutData(int i, double value, uint_8 flag=0); // abs | 
|---|
|  | 54 |  | 
|---|
| [1670] | 55 |  | 
|---|
|  | 56 | protected: | 
|---|
| [1671] | 57 | class BufferSegment; | 
|---|
|  | 58 | class BufferView; | 
|---|
|  | 59 | class MasterView; | 
|---|
|  | 60 |  | 
|---|
| [1689] | 61 | MasterView* master; | 
|---|
| [1671] | 62 |  | 
|---|
| [1689] | 63 |  | 
|---|
| [1670] | 64 | class BufferSegment { | 
|---|
|  | 65 | public: | 
|---|
|  | 66 | BufferSegment(int sz); | 
|---|
|  | 67 | ~BufferSegment(); | 
|---|
|  | 68 | static const int NEW = 0; | 
|---|
| [1671] | 69 | static const int WRITE = 1;     // single-thread write access | 
|---|
|  | 70 | static const int COMMITTED = 2; // multiple read without lock are ok | 
|---|
| [1670] | 71 |  | 
|---|
|  | 72 | int getStatus() {return status;} | 
|---|
| [1671] | 73 | void incRefCount(); | 
|---|
|  | 74 | void decRefCount(); | 
|---|
|  | 75 | int  getRefCount(); | 
|---|
|  | 76 |  | 
|---|
| [1670] | 77 | void putData(int sn, double data, uint_8 flag); | 
|---|
| [1743] | 78 | void putData(int sn, int n, double const* data, uint_8 const* flag); | 
|---|
| [1670] | 79 | inline double getData(int sn); | 
|---|
|  | 80 | inline uint_8 getFlag(int sn); | 
|---|
| [1743] | 81 | void getData(int sn, int n, double* data, uint_8* flag); | 
|---|
| [1671] | 82 |  | 
|---|
|  | 83 | bool isPastEnd(int sn) { | 
|---|
| [1944] | 84 | return sn >= sn0+bufferSize; | 
|---|
| [1671] | 85 | } | 
|---|
| [1670] | 86 |  | 
|---|
|  | 87 | private: | 
|---|
|  | 88 | void checkCommitted() { | 
|---|
| [1944] | 89 | if (status != COMMITTED) { | 
|---|
|  | 90 | cerr << "TOISegment: Read on not committed buffer segment" << endl; | 
|---|
| [1670] | 91 | throw(ForbiddenError("TOISegment: Read on not committed buffer segment")); | 
|---|
| [1944] | 92 | } | 
|---|
| [1670] | 93 | } | 
|---|
|  | 94 |  | 
|---|
|  | 95 | void checkInRange(int sn) { | 
|---|
| [1944] | 96 | if (sn < sn0 || sn >= sn0+bufferSize) { | 
|---|
|  | 97 | cerr << "TOISegment: out of range access in buffer segment " << sn << " not in " | 
|---|
|  | 98 | << sn0 << " - " << sn0+bufferSize << endl; | 
|---|
| [1670] | 99 | throw(RangeCheckError("TOISegment: out of range access in buffer segment")); | 
|---|
| [1944] | 100 | } | 
|---|
| [1670] | 101 | } | 
|---|
|  | 102 |  | 
|---|
|  | 103 |  | 
|---|
|  | 104 | int status;      // NEW, WRITE, COMMITTED | 
|---|
|  | 105 | int bufferSize; | 
|---|
|  | 106 | int sn0;         // Samplenum du premier echantillon | 
|---|
|  | 107 |  | 
|---|
|  | 108 | int refcount;    // Nombre de vues qui utilisent | 
|---|
| [1686] | 109 | pthread_mutex_t refcount_mutex; // Pour modification refcount | 
|---|
| [1670] | 110 |  | 
|---|
|  | 111 | double* data; | 
|---|
|  | 112 | uint_8* flags; | 
|---|
| [1686] | 113 |  | 
|---|
|  | 114 | friend class BufferView; | 
|---|
|  | 115 | friend class MasterView; | 
|---|
| [1670] | 116 | }; | 
|---|
|  | 117 |  | 
|---|
| [1671] | 118 | // Master view, gere le lock, et l'ecriture | 
|---|
| [1670] | 119 | class MasterView { | 
|---|
|  | 120 | public: | 
|---|
| [1710] | 121 | MasterView(int bufsz=256, int maxseg=20, string nm=""); | 
|---|
| [1670] | 122 | ~MasterView(); | 
|---|
|  | 123 |  | 
|---|
| [1671] | 124 | void putData(int sn, double data, uint_8 flag); | 
|---|
| [1686] | 125 | double getData(int sn); | 
|---|
|  | 126 | uint_8 getFlag(int sn); | 
|---|
| [1743] | 127 | void   getData(int i, int n, double* data, uint_8* flg); | 
|---|
|  | 128 | void   putData(int i, int n, double const* val, uint_8 const* flg); | 
|---|
| [1689] | 129 | BufferView* getView(); // thread-specific | 
|---|
|  | 130 | void putDone(); | 
|---|
| [1686] | 131 |  | 
|---|
|  | 132 | protected: | 
|---|
| [1671] | 133 |  | 
|---|
|  | 134 | friend class BufferView; | 
|---|
| [1692] | 135 | friend class TOISegmented; | 
|---|
| [1710] | 136 | string name; | 
|---|
| [1689] | 137 | void signalWaitingViews(); // views are waiting on read | 
|---|
| [1692] | 138 | void signalWrite();        // we are waiting on write | 
|---|
| [1671] | 139 | void nextSegment(); | 
|---|
| [1689] | 140 | void waitForCleaning(); | 
|---|
| [1671] | 141 | BufferView* createView(); | 
|---|
|  | 142 | void updateView(BufferView*); // called on reader thread of the view | 
|---|
| [1670] | 143 |  | 
|---|
| [1671] | 144 | BufferSegment*   currentSegment; | 
|---|
|  | 145 |  | 
|---|
|  | 146 | int maxSegments; | 
|---|
| [1686] | 147 | int segmentSize; | 
|---|
|  | 148 | int sn0;                         // First sn in first segment | 
|---|
|  | 149 | vector<BufferSegment*> segments; // Committed segments | 
|---|
| [1692] | 150 | int nConsumers; | 
|---|
| [1671] | 151 |  | 
|---|
| [1686] | 152 | pthread_mutex_t  views_mutex; // lock for master buffer list access | 
|---|
| [1692] | 153 | pthread_cond_t   write_wait_condv; // waiting for cleaning (on writer thread) | 
|---|
| [1686] | 154 | pthread_key_t    buffer_key; // thread-specific buffer view | 
|---|
|  | 155 | static void BufferDestroy(void *); | 
|---|
| [1671] | 156 |  | 
|---|
| [1692] | 157 | pthread_mutex_t  read_wait_mutex; | 
|---|
|  | 158 | pthread_cond_t   read_wait_condv; | 
|---|
|  | 159 |  | 
|---|
| [1689] | 160 | bool   waitingOnWrite; // wait on writer thread | 
|---|
| [1711] | 161 | int    waitingViews; | 
|---|
| [1671] | 162 |  | 
|---|
| [1690] | 163 | set<BufferView*>  allViews; | 
|---|
| [1686] | 164 |  | 
|---|
|  | 165 | void checkDeadLock(); | 
|---|
| [1670] | 166 | }; | 
|---|
|  | 167 |  | 
|---|
|  | 168 |  | 
|---|
|  | 169 | // per-thread read-only view of a buffer set | 
|---|
|  | 170 | class BufferView { | 
|---|
|  | 171 | public: | 
|---|
| [1686] | 172 | BufferView(MasterView*); | 
|---|
| [1671] | 173 | ~BufferView(); | 
|---|
| [1686] | 174 |  | 
|---|
|  | 175 | double getData(int sn); | 
|---|
|  | 176 | uint_8 getFlag(int sn); | 
|---|
| [1743] | 177 | void   getData(int i, int n, double* data, uint_8* flg); | 
|---|
| [1689] | 178 |  | 
|---|
|  | 179 | void wontNeedBefore(int sn); | 
|---|
| [1670] | 180 |  | 
|---|
| [1686] | 181 | protected: | 
|---|
| [1774] | 182 | void wait(int sn);  // Passe en attente d'un nouveau segment -- lecture | 
|---|
| [1671] | 183 | void sync();  // recupere les nouveaux segments, resync avec master | 
|---|
| [1686] | 184 | void ensure(int sn); | 
|---|
|  | 185 |  | 
|---|
| [1692] | 186 | bool waiting; | 
|---|
| [1773] | 187 | int  waitingFor; | 
|---|
| [1692] | 188 |  | 
|---|
| [1671] | 189 | friend class MasterView; | 
|---|
|  | 190 | MasterView* master; | 
|---|
|  | 191 | vector<BufferSegment*> segments; // Committed | 
|---|
| [1686] | 192 | int sn0; | 
|---|
|  | 193 | int segmentSize; | 
|---|
| [1689] | 194 | int firstNeeded; | 
|---|
| [1670] | 195 | }; | 
|---|
| [1671] | 196 |  | 
|---|
|  | 197 |  | 
|---|
|  | 198 |  | 
|---|
| [1670] | 199 | }; | 
|---|
|  | 200 |  | 
|---|
| [1686] | 201 | /***********************************/ | 
|---|
|  | 202 | /* Inline methods -- BufferSegment */ | 
|---|
|  | 203 | /***********************************/ | 
|---|
| [1670] | 204 |  | 
|---|
|  | 205 | double TOISegmented::BufferSegment::getData(int sn) { | 
|---|
|  | 206 | checkCommitted(); | 
|---|
|  | 207 | checkInRange(sn); | 
|---|
|  | 208 | return data[sn-sn0]; | 
|---|
|  | 209 | } | 
|---|
|  | 210 |  | 
|---|
|  | 211 | uint_8 TOISegmented::BufferSegment::getFlag(int sn) { | 
|---|
|  | 212 | checkCommitted(); | 
|---|
|  | 213 | checkInRange(sn); | 
|---|
|  | 214 | return flags[sn-sn0]; | 
|---|
|  | 215 | } | 
|---|
|  | 216 |  | 
|---|
|  | 217 | #endif | 
|---|