| [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 | 
|---|
| [1787] | 7 | // $Id: toisegment.h,v 1.17 2001-11-26 15:13:48 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) { | 
|---|
|  | 84 | return sn >= sn+bufferSize; | 
|---|
|  | 85 | } | 
|---|
| [1670] | 86 |  | 
|---|
|  | 87 | private: | 
|---|
|  | 88 | void checkCommitted() { | 
|---|
|  | 89 | if (status != COMMITTED) | 
|---|
|  | 90 | throw(ForbiddenError("TOISegment: Read on not committed buffer segment")); | 
|---|
|  | 91 | } | 
|---|
|  | 92 |  | 
|---|
|  | 93 | void checkInRange(int sn) { | 
|---|
|  | 94 | if (sn < sn0 || sn >= sn+bufferSize) | 
|---|
|  | 95 | throw(RangeCheckError("TOISegment: out of range access in buffer segment")); | 
|---|
|  | 96 | } | 
|---|
|  | 97 |  | 
|---|
|  | 98 |  | 
|---|
|  | 99 | int status;      // NEW, WRITE, COMMITTED | 
|---|
|  | 100 | int bufferSize; | 
|---|
|  | 101 | int sn0;         // Samplenum du premier echantillon | 
|---|
|  | 102 |  | 
|---|
|  | 103 | int refcount;    // Nombre de vues qui utilisent | 
|---|
| [1686] | 104 | pthread_mutex_t refcount_mutex; // Pour modification refcount | 
|---|
| [1670] | 105 |  | 
|---|
|  | 106 | double* data; | 
|---|
|  | 107 | uint_8* flags; | 
|---|
| [1686] | 108 |  | 
|---|
|  | 109 | friend class BufferView; | 
|---|
|  | 110 | friend class MasterView; | 
|---|
| [1670] | 111 | }; | 
|---|
|  | 112 |  | 
|---|
| [1671] | 113 | // Master view, gere le lock, et l'ecriture | 
|---|
| [1670] | 114 | class MasterView { | 
|---|
|  | 115 | public: | 
|---|
| [1710] | 116 | MasterView(int bufsz=256, int maxseg=20, string nm=""); | 
|---|
| [1670] | 117 | ~MasterView(); | 
|---|
|  | 118 |  | 
|---|
| [1671] | 119 | void putData(int sn, double data, uint_8 flag); | 
|---|
| [1686] | 120 | double getData(int sn); | 
|---|
|  | 121 | uint_8 getFlag(int sn); | 
|---|
| [1743] | 122 | void   getData(int i, int n, double* data, uint_8* flg); | 
|---|
|  | 123 | void   putData(int i, int n, double const* val, uint_8 const* flg); | 
|---|
| [1689] | 124 | BufferView* getView(); // thread-specific | 
|---|
|  | 125 | void putDone(); | 
|---|
| [1686] | 126 |  | 
|---|
|  | 127 | protected: | 
|---|
| [1671] | 128 |  | 
|---|
|  | 129 | friend class BufferView; | 
|---|
| [1692] | 130 | friend class TOISegmented; | 
|---|
| [1710] | 131 | string name; | 
|---|
| [1689] | 132 | void signalWaitingViews(); // views are waiting on read | 
|---|
| [1692] | 133 | void signalWrite();        // we are waiting on write | 
|---|
| [1671] | 134 | void nextSegment(); | 
|---|
| [1689] | 135 | void waitForCleaning(); | 
|---|
| [1671] | 136 | BufferView* createView(); | 
|---|
|  | 137 | void updateView(BufferView*); // called on reader thread of the view | 
|---|
| [1670] | 138 |  | 
|---|
| [1671] | 139 | BufferSegment*   currentSegment; | 
|---|
|  | 140 |  | 
|---|
|  | 141 | int maxSegments; | 
|---|
| [1686] | 142 | int segmentSize; | 
|---|
|  | 143 | int sn0;                         // First sn in first segment | 
|---|
|  | 144 | vector<BufferSegment*> segments; // Committed segments | 
|---|
| [1692] | 145 | int nConsumers; | 
|---|
| [1671] | 146 |  | 
|---|
| [1686] | 147 | pthread_mutex_t  views_mutex; // lock for master buffer list access | 
|---|
| [1692] | 148 | pthread_cond_t   write_wait_condv; // waiting for cleaning (on writer thread) | 
|---|
| [1686] | 149 | pthread_key_t    buffer_key; // thread-specific buffer view | 
|---|
|  | 150 | static void BufferDestroy(void *); | 
|---|
| [1671] | 151 |  | 
|---|
| [1692] | 152 | pthread_mutex_t  read_wait_mutex; | 
|---|
|  | 153 | pthread_cond_t   read_wait_condv; | 
|---|
|  | 154 |  | 
|---|
| [1689] | 155 | bool   waitingOnWrite; // wait on writer thread | 
|---|
| [1711] | 156 | int    waitingViews; | 
|---|
| [1671] | 157 |  | 
|---|
| [1690] | 158 | set<BufferView*>  allViews; | 
|---|
| [1686] | 159 |  | 
|---|
|  | 160 | void checkDeadLock(); | 
|---|
| [1670] | 161 | }; | 
|---|
|  | 162 |  | 
|---|
|  | 163 |  | 
|---|
|  | 164 | // per-thread read-only view of a buffer set | 
|---|
|  | 165 | class BufferView { | 
|---|
|  | 166 | public: | 
|---|
| [1686] | 167 | BufferView(MasterView*); | 
|---|
| [1671] | 168 | ~BufferView(); | 
|---|
| [1686] | 169 |  | 
|---|
|  | 170 | double getData(int sn); | 
|---|
|  | 171 | uint_8 getFlag(int sn); | 
|---|
| [1743] | 172 | void   getData(int i, int n, double* data, uint_8* flg); | 
|---|
| [1689] | 173 |  | 
|---|
|  | 174 | void wontNeedBefore(int sn); | 
|---|
| [1670] | 175 |  | 
|---|
| [1686] | 176 | protected: | 
|---|
| [1774] | 177 | void wait(int sn);  // Passe en attente d'un nouveau segment -- lecture | 
|---|
| [1671] | 178 | void sync();  // recupere les nouveaux segments, resync avec master | 
|---|
| [1686] | 179 | void ensure(int sn); | 
|---|
|  | 180 |  | 
|---|
| [1692] | 181 | bool waiting; | 
|---|
| [1773] | 182 | int  waitingFor; | 
|---|
| [1692] | 183 |  | 
|---|
| [1671] | 184 | friend class MasterView; | 
|---|
|  | 185 | MasterView* master; | 
|---|
|  | 186 | vector<BufferSegment*> segments; // Committed | 
|---|
| [1686] | 187 | int sn0; | 
|---|
|  | 188 | int segmentSize; | 
|---|
| [1689] | 189 | int firstNeeded; | 
|---|
| [1670] | 190 | }; | 
|---|
| [1671] | 191 |  | 
|---|
|  | 192 |  | 
|---|
|  | 193 |  | 
|---|
| [1670] | 194 | }; | 
|---|
|  | 195 |  | 
|---|
| [1686] | 196 | /***********************************/ | 
|---|
|  | 197 | /* Inline methods -- BufferSegment */ | 
|---|
|  | 198 | /***********************************/ | 
|---|
| [1670] | 199 |  | 
|---|
|  | 200 | double TOISegmented::BufferSegment::getData(int sn) { | 
|---|
|  | 201 | checkCommitted(); | 
|---|
|  | 202 | checkInRange(sn); | 
|---|
|  | 203 | return data[sn-sn0]; | 
|---|
|  | 204 | } | 
|---|
|  | 205 |  | 
|---|
|  | 206 | uint_8 TOISegmented::BufferSegment::getFlag(int sn) { | 
|---|
|  | 207 | checkCommitted(); | 
|---|
|  | 208 | checkInRange(sn); | 
|---|
|  | 209 | return flags[sn-sn0]; | 
|---|
|  | 210 | } | 
|---|
|  | 211 |  | 
|---|
|  | 212 | #endif | 
|---|