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