#ifndef __EpochCounter_h_ #define __EpochCounter_h_ #include #include #include #include /* This helps us keep track of changes. If an object reads the value of a * candle, and later the value of that candle changes, the consumer should * reread the value of that candle. * * Each candle should have it's own epoch. Ideally a new candle would be * added and the candles before it would not change. The last candle might * change several times before a new candle is added after it. The consumer * should not recompute everything each time a new candle is added or the * last candle changes. * * Sometimes a candle other than the last one will change. In that case the * consumer should know exactly which candle changed. However, we have some * flexibility there. If the 3rd candle changes, it doesn't matter if the 4th * one changed or not. We assume that the consumer (presumably a GridReader) * will delete all data starting from the row that actually changed. It will * have to recompute the later rows. * * When the consumer is ready to read data it does the following: * 1) Read and record the current epoch. * 2) Find out which data has been invalided since the last time we recorded * the epoch. * 3) Read the new data. * * Initially, the various candles will be the producers, and the grids will * be the consumers. But the plan is for a grid to eventually be able to * reference another grid. There's no reason a grid couldn't own one of these. * There's no reason a grid couldn't be a producer and a consumer. * * There is only one current epoch. It is shared by all EpochCounters. A * consumer only needs to remember one epoch, even if the consumer reads from * multiple producers. * * It is safe to initialize an Epoch variable to 0. 0 is guaranteed to come * before any changes. */ class EpochCounter { public: typedef int64_t Epoch; private: static volatile Epoch _currentEpoch; static Epoch getNextEpoch(); std::map< Epoch, time_t > _startAfter; public: // This is the time associated with the epoch. The consumer should record // the current epoch when it reads from the producer. Later the consumer // will call this to find the first value which has changed. The producer // actually owns the EpochCounter object, but it will expose this function // to the consumer in some fashion. This function will return a very large // number (like MAXINT) if nothing has changed. time_t restartAt(Epoch epoch) const; // This is only used by the producer. Whenever the producer updates a data // item, it should use this function to record the change. Time is the time // associated with the data item (i.e. which candle). This will generate // a new epoch, and associate the new epoch with this time. void addEpoch(time_t time); // This is the current epoch. Read this before requesting data. Save the // value and use it later in restartAt(). This is thread safe. static Epoch getEpoch(); }; #endif