diff options
Diffstat (limited to 'indra/llcommon/lltracerecording.h')
-rw-r--r-- | indra/llcommon/lltracerecording.h | 1306 |
1 files changed, 653 insertions, 653 deletions
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index 61b9096ae2..985f06cd59 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -38,680 +38,680 @@ class LLStopWatchControlsMixinCommon { public: - virtual ~LLStopWatchControlsMixinCommon() {} - - enum EPlayState - { - STOPPED, - PAUSED, - STARTED - }; - - void start(); // moves to started state, resetting if stopped - void stop(); // moves to stopped state - void pause(); // moves to paused state, unless stopped - void unpause(); // moves to started state if paused - void resume(); // moves to started state, without resetting - void restart(); // moves to started state, always resetting - void reset(); // resets - - bool isStarted() const { return mPlayState == STARTED; } - bool isPaused() const { return mPlayState == PAUSED; } - bool isStopped() const { return mPlayState == STOPPED; } - - EPlayState getPlayState() const { return mPlayState; } - // force play state to specific value by calling appropriate handle* methods - void setPlayState(EPlayState state); + virtual ~LLStopWatchControlsMixinCommon() {} + + enum EPlayState + { + STOPPED, + PAUSED, + STARTED + }; + + void start(); // moves to started state, resetting if stopped + void stop(); // moves to stopped state + void pause(); // moves to paused state, unless stopped + void unpause(); // moves to started state if paused + void resume(); // moves to started state, without resetting + void restart(); // moves to started state, always resetting + void reset(); // resets + + bool isStarted() const { return mPlayState == STARTED; } + bool isPaused() const { return mPlayState == PAUSED; } + bool isStopped() const { return mPlayState == STOPPED; } + + EPlayState getPlayState() const { return mPlayState; } + // force play state to specific value by calling appropriate handle* methods + void setPlayState(EPlayState state); protected: - LLStopWatchControlsMixinCommon() - : mPlayState(STOPPED) - {} + LLStopWatchControlsMixinCommon() + : mPlayState(STOPPED) + {} private: - // override these methods to provide started/stopped semantics + // override these methods to provide started/stopped semantics - // activate behavior (without reset) - virtual void handleStart() = 0; - // deactivate behavior - virtual void handleStop() = 0; - // clear accumulated state, may be called while started - virtual void handleReset() = 0; + // activate behavior (without reset) + virtual void handleStart() = 0; + // deactivate behavior + virtual void handleStop() = 0; + // clear accumulated state, may be called while started + virtual void handleReset() = 0; - EPlayState mPlayState; + EPlayState mPlayState; }; template<typename DERIVED> class LLStopWatchControlsMixin -: public LLStopWatchControlsMixinCommon +: public LLStopWatchControlsMixinCommon { public: - typedef LLStopWatchControlsMixin<DERIVED> self_t; - virtual void splitTo(DERIVED& other) - { - EPlayState play_state = getPlayState(); - stop(); - other.reset(); + typedef LLStopWatchControlsMixin<DERIVED> self_t; + virtual void splitTo(DERIVED& other) + { + EPlayState play_state = getPlayState(); + stop(); + other.reset(); - handleSplitTo(other); + handleSplitTo(other); - other.setPlayState(play_state); - } + other.setPlayState(play_state); + } - virtual void splitFrom(DERIVED& other) - { - static_cast<self_t&>(other).handleSplitTo(*static_cast<DERIVED*>(this)); - } + virtual void splitFrom(DERIVED& other) + { + static_cast<self_t&>(other).handleSplitTo(*static_cast<DERIVED*>(this)); + } private: - self_t& operator = (const self_t& other) - { - // don't do anything, derived class must implement logic - } - - // atomically stop this object while starting the other - // no data can be missed in between stop and start - virtual void handleSplitTo(DERIVED& other) {}; + self_t& operator = (const self_t& other) + { + // don't do anything, derived class must implement logic + } + + // atomically stop this object while starting the other + // no data can be missed in between stop and start + virtual void handleSplitTo(DERIVED& other) {}; }; namespace LLTrace { - template<typename T> - class StatType; - - template<typename T> - class CountStatHandle; - - template<typename T> - class SampleStatHandle; - - template<typename T> - class EventStatHandle; - - template<typename T> - struct RelatedTypes - { - typedef F64 fractional_t; - typedef T sum_t; - }; - - template<typename T, typename UNIT_T> - struct RelatedTypes<LLUnit<T, UNIT_T> > - { - typedef LLUnit<typename RelatedTypes<T>::fractional_t, UNIT_T> fractional_t; - typedef LLUnit<typename RelatedTypes<T>::sum_t, UNIT_T> sum_t; - }; - - template<> - struct RelatedTypes<bool> - { - typedef F64 fractional_t; - typedef S32 sum_t; - }; - - class Recording - : public LLStopWatchControlsMixin<Recording> - { - public: - Recording(EPlayState state = LLStopWatchControlsMixinCommon::STOPPED); - - Recording(const Recording& other); - ~Recording(); - - Recording& operator = (const Recording& other); - - // accumulate data from subsequent, non-overlapping recording - void appendRecording(Recording& other); - - // grab latest recorded data - void update(); - - // ensure that buffers are exclusively owned by this recording - void makeUnique() { mBuffers.makeUnique(); } - - // Timer accessors - bool hasValue(const StatType<TimeBlockAccumulator>& stat); - F64Seconds getSum(const StatType<TimeBlockAccumulator>& stat); - F64Seconds getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat); - S32 getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat); - - F64Seconds getPerSec(const StatType<TimeBlockAccumulator>& stat); - F64Seconds getPerSec(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat); - F32 getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& stat); - - // CountStatHandle accessors - bool hasValue(const StatType<CountAccumulator>& stat); - F64 getSum(const StatType<CountAccumulator>& stat); - template <typename T> - typename RelatedTypes<T>::sum_t getSum(const CountStatHandle<T>& stat) - { - return (typename RelatedTypes<T>::sum_t)getSum(static_cast<const StatType<CountAccumulator>&> (stat)); - } - - F64 getPerSec(const StatType<CountAccumulator>& stat); - template <typename T> - typename RelatedTypes<T>::fractional_t getPerSec(const CountStatHandle<T>& stat) - { - return (typename RelatedTypes<T>::fractional_t)getPerSec(static_cast<const StatType<CountAccumulator>&> (stat)); - } - - S32 getSampleCount(const StatType<CountAccumulator>& stat); - - - // SampleStatHandle accessors - bool hasValue(const StatType<SampleAccumulator>& stat); - - F64 getMin(const StatType<SampleAccumulator>& stat); - template <typename T> - T getMin(const SampleStatHandle<T>& stat) - { - return (T)getMin(static_cast<const StatType<SampleAccumulator>&> (stat)); - } - - F64 getMax(const StatType<SampleAccumulator>& stat); - template <typename T> - T getMax(const SampleStatHandle<T>& stat) - { - return (T)getMax(static_cast<const StatType<SampleAccumulator>&> (stat)); - } - - F64 getMean(const StatType<SampleAccumulator>& stat); - template <typename T> - typename RelatedTypes<T>::fractional_t getMean(SampleStatHandle<T>& stat) - { - return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const StatType<SampleAccumulator>&> (stat)); - } - - F64 getStandardDeviation(const StatType<SampleAccumulator>& stat); - template <typename T> - typename RelatedTypes<T>::fractional_t getStandardDeviation(const SampleStatHandle<T>& stat) - { - return (typename RelatedTypes<T>::fractional_t)getStandardDeviation(static_cast<const StatType<SampleAccumulator>&> (stat)); - } - - F64 getLastValue(const StatType<SampleAccumulator>& stat); - template <typename T> - T getLastValue(const SampleStatHandle<T>& stat) - { - return (T)getLastValue(static_cast<const StatType<SampleAccumulator>&> (stat)); - } - - S32 getSampleCount(const StatType<SampleAccumulator>& stat); - - // EventStatHandle accessors - bool hasValue(const StatType<EventAccumulator>& stat); - - F64 getSum(const StatType<EventAccumulator>& stat); - template <typename T> - typename RelatedTypes<T>::sum_t getSum(const EventStatHandle<T>& stat) - { - return (typename RelatedTypes<T>::sum_t)getSum(static_cast<const StatType<EventAccumulator>&> (stat)); - } - - F64 getMin(const StatType<EventAccumulator>& stat); - template <typename T> - T getMin(const EventStatHandle<T>& stat) - { - return (T)getMin(static_cast<const StatType<EventAccumulator>&> (stat)); - } - - F64 getMax(const StatType<EventAccumulator>& stat); - template <typename T> - T getMax(const EventStatHandle<T>& stat) - { - return (T)getMax(static_cast<const StatType<EventAccumulator>&> (stat)); - } - - F64 getMean(const StatType<EventAccumulator>& stat); - template <typename T> - typename RelatedTypes<T>::fractional_t getMean(EventStatHandle<T>& stat) - { - return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const StatType<EventAccumulator>&> (stat)); - } - - F64 getStandardDeviation(const StatType<EventAccumulator>& stat); - template <typename T> - typename RelatedTypes<T>::fractional_t getStandardDeviation(const EventStatHandle<T>& stat) - { - return (typename RelatedTypes<T>::fractional_t)getStandardDeviation(static_cast<const StatType<EventAccumulator>&> (stat)); - } - - F64 getLastValue(const StatType<EventAccumulator>& stat); - template <typename T> - T getLastValue(const EventStatHandle<T>& stat) - { - return (T)getLastValue(static_cast<const StatType<EventAccumulator>&> (stat)); - } - - S32 getSampleCount(const StatType<EventAccumulator>& stat); - - F64Seconds getDuration() const { return mElapsedSeconds; } - - protected: - friend class ThreadRecorder; - - // implementation for LLStopWatchControlsMixin - /*virtual*/ void handleStart(); - /*virtual*/ void handleStop(); - /*virtual*/ void handleReset(); - /*virtual*/ void handleSplitTo(Recording& other); - - // returns data for current thread - class ThreadRecorder* getThreadRecorder(); - - LLTimer mSamplingTimer; - F64Seconds mElapsedSeconds; - LLCopyOnWritePointer<AccumulatorBufferGroup> mBuffers; - AccumulatorBufferGroup* mActiveBuffers; - - }; - - class LL_COMMON_API PeriodicRecording - : public LLStopWatchControlsMixin<PeriodicRecording> - { - public: - PeriodicRecording(size_t num_periods, EPlayState state = STOPPED); - ~PeriodicRecording(); - - void nextPeriod(); - auto getNumRecordedPeriods() - { - // current period counts if not active - return mNumRecordedPeriods + (isStarted() ? 0 : 1); - } - - F64Seconds getDuration() const; - - void appendPeriodicRecording(PeriodicRecording& other); - void appendRecording(Recording& recording); - Recording& getLastRecording(); - const Recording& getLastRecording() const; - Recording& getCurRecording(); - const Recording& getCurRecording() const; - Recording& getPrevRecording(size_t offset); - const Recording& getPrevRecording(size_t offset) const; - Recording snapshotCurRecording() const; - - template <typename T> - auto getSampleCount(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - num_periods = llmin(num_periods, getNumRecordedPeriods()); - - size_t num_samples = 0; - for (size_t i = 1; i <= num_periods; i++) - { - Recording& recording = getPrevRecording(i); - num_samples += recording.getSampleCount(stat); - } - return num_samples; - } - - // - // PERIODIC MIN - // - - // catch all for stats that have a defined sum - template <typename T> - typename T::value_t getPeriodMin(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - num_periods = llmin(num_periods, getNumRecordedPeriods()); - - bool has_value = false; - typename T::value_t min_val(std::numeric_limits<typename T::value_t>::max()); - for (size_t i = 1; i <= num_periods; i++) - { - Recording& recording = getPrevRecording(i); - if (recording.hasValue(stat)) - { - min_val = llmin(min_val, recording.getSum(stat)); - has_value = true; - } - } - - return has_value - ? min_val - : T::getDefaultValue(); - } - - template<typename T> - T getPeriodMin(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - return T(getPeriodMin(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); - } - - F64 getPeriodMin(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); - template<typename T> - T getPeriodMin(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - return T(getPeriodMin(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods)); - } - - F64 getPeriodMin(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); - template<typename T> - T getPeriodMin(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - return T(getPeriodMin(static_cast<const StatType<EventAccumulator>&>(stat), num_periods)); - } - - template <typename T> - typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - num_periods = llmin(num_periods, getNumRecordedPeriods()); - - typename RelatedTypes<typename T::value_t>::fractional_t min_val(std::numeric_limits<F64>::max()); - for (size_t i = 1; i <= num_periods; i++) - { - Recording& recording = getPrevRecording(i); - min_val = llmin(min_val, recording.getPerSec(stat)); - } - return (typename RelatedTypes<typename T::value_t>::fractional_t) min_val; - } - - template<typename T> - typename RelatedTypes<T>::fractional_t getPeriodMinPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - return typename RelatedTypes<T>::fractional_t(getPeriodMinPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); - } - - // - // PERIODIC MAX - // - - // catch all for stats that have a defined sum - template <typename T> - typename T::value_t getPeriodMax(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - num_periods = llmin(num_periods, getNumRecordedPeriods()); - - bool has_value = false; - typename T::value_t max_val(std::numeric_limits<typename T::value_t>::min()); - for (size_t i = 1; i <= num_periods; i++) - { - Recording& recording = getPrevRecording(i); - if (recording.hasValue(stat)) - { - max_val = llmax(max_val, recording.getSum(stat)); - has_value = true; - } - } - - return has_value - ? max_val - : T::getDefaultValue(); - } - - template<typename T> - T getPeriodMax(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - return T(getPeriodMax(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); - } - - F64 getPeriodMax(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); - template<typename T> - T getPeriodMax(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - return T(getPeriodMax(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods)); - } - - F64 getPeriodMax(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); - template<typename T> - T getPeriodMax(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - return T(getPeriodMax(static_cast<const StatType<EventAccumulator>&>(stat), num_periods)); - } - - template <typename T> - typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - num_periods = llmin(num_periods, getNumRecordedPeriods()); - - F64 max_val = std::numeric_limits<F64>::min(); - for (size_t i = 1; i <= num_periods; i++) - { - Recording& recording = getPrevRecording(i); - max_val = llmax(max_val, recording.getPerSec(stat)); - } - return (typename RelatedTypes<typename T::value_t>::fractional_t)max_val; - } - - template<typename T> - typename RelatedTypes<T>::fractional_t getPeriodMaxPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - return typename RelatedTypes<T>::fractional_t(getPeriodMaxPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); - } - - // - // PERIODIC MEAN - // - - // catch all for stats that have a defined sum - template <typename T> - typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const StatType<T >& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - num_periods = llmin(num_periods, getNumRecordedPeriods()); - - typename RelatedTypes<typename T::value_t>::fractional_t mean(0); - - for (size_t i = 1; i <= num_periods; i++) - { - Recording& recording = getPrevRecording(i); - if (recording.getDuration() > (F32Seconds)0.f) - { - mean += recording.getSum(stat); - } - } - return (num_periods - ? typename RelatedTypes<typename T::value_t>::fractional_t(mean / num_periods) - : typename RelatedTypes<typename T::value_t>::fractional_t(NaN)); - } - - template<typename T> - typename RelatedTypes<T>::fractional_t getPeriodMean(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); - } - F64 getPeriodMean(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); - template<typename T> - typename RelatedTypes<T>::fractional_t getPeriodMean(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods)); - } - - F64 getPeriodMean(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); - template<typename T> - typename RelatedTypes<T>::fractional_t getPeriodMean(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<EventAccumulator>&>(stat), num_periods)); - } - - template <typename T> - typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - num_periods = llmin(num_periods, getNumRecordedPeriods()); - - typename RelatedTypes<typename T::value_t>::fractional_t mean = 0; - - for (size_t i = 1; i <= num_periods; i++) - { - Recording& recording = getPrevRecording(i); - if (recording.getDuration() > (F32Seconds)0.f) - { - mean += recording.getPerSec(stat); - } - } - - return (num_periods - ? typename RelatedTypes<typename T::value_t>::fractional_t(mean / num_periods) - : typename RelatedTypes<typename T::value_t>::fractional_t(NaN)); - } - - template<typename T> - typename RelatedTypes<T>::fractional_t getPeriodMeanPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); - } - - F64 getPeriodMedian( const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); - - template <typename T> - typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMedianPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - num_periods = llmin(num_periods, getNumRecordedPeriods()); - - std::vector <typename RelatedTypes<typename T::value_t>::fractional_t> buf; - for (size_t i = 1; i <= num_periods; i++) - { - Recording& recording = getPrevRecording(i); - if (recording.getDuration() > (F32Seconds)0.f) - { - buf.push_back(recording.getPerSec(stat)); - } - } - std::sort(buf.begin(), buf.end()); - - return typename RelatedTypes<T>::fractional_t((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]); - } - - template<typename T> - typename RelatedTypes<T>::fractional_t getPeriodMedianPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - return typename RelatedTypes<T>::fractional_t(getPeriodMedianPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); - } - - // - // PERIODIC STANDARD DEVIATION - // - - F64 getPeriodStandardDeviation(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); - - template<typename T> - typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods)); - } - - F64 getPeriodStandardDeviation(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); - template<typename T> - typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) - { - LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; - return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<EventAccumulator>&>(stat), num_periods)); - } - - private: - // implementation for LLStopWatchControlsMixin - /*virtual*/ void handleStart(); - /*virtual*/ void handleStop(); - /*virtual*/ void handleReset(); - /*virtual*/ void handleSplitTo(PeriodicRecording& other); - - // helper methods for wraparound ring-buffer arithmetic - inline - size_t wrapi(size_t i) const - { - return i % mRecordingPeriods.size(); - } - - inline - size_t nexti(size_t i, size_t offset=1) const - { - return wrapi(i + offset); - } - - inline - size_t previ(size_t i, size_t offset=1) const - { - auto num_periods = mRecordingPeriods.size(); - // constrain offset - offset = llclamp(offset, 0, num_periods - 1); - // add size() so expression can't go (unsigned) "negative" - return wrapi(i + num_periods - offset); - } - - inline - void inci(size_t& i, size_t offset=1) const - { - i = nexti(i, offset); - } - - private: - std::vector<Recording> mRecordingPeriods; - const bool mAutoResize; - size_t mCurPeriod; - size_t mNumRecordedPeriods; - }; - - PeriodicRecording& get_frame_recording(); - - class ExtendableRecording - : public LLStopWatchControlsMixin<ExtendableRecording> - { - public: - void extend(); - - Recording& getAcceptedRecording() { return mAcceptedRecording; } - const Recording& getAcceptedRecording() const {return mAcceptedRecording;} - - Recording& getPotentialRecording() { return mPotentialRecording; } - const Recording& getPotentialRecording() const { return mPotentialRecording;} - - private: - // implementation for LLStopWatchControlsMixin - /*virtual*/ void handleStart(); - /*virtual*/ void handleStop(); - /*virtual*/ void handleReset(); - /*virtual*/ void handleSplitTo(ExtendableRecording& other); - - private: - Recording mAcceptedRecording; - Recording mPotentialRecording; - }; - - class ExtendablePeriodicRecording - : public LLStopWatchControlsMixin<ExtendablePeriodicRecording> - { - public: - ExtendablePeriodicRecording(); - void extend(); - - PeriodicRecording& getResults() { return mAcceptedRecording; } - const PeriodicRecording& getResults() const {return mAcceptedRecording;} - - void nextPeriod() { mPotentialRecording.nextPeriod(); } - - private: - // implementation for LLStopWatchControlsMixin - /*virtual*/ void handleStart(); - /*virtual*/ void handleStop(); - /*virtual*/ void handleReset(); - /*virtual*/ void handleSplitTo(ExtendablePeriodicRecording& other); - - private: - PeriodicRecording mAcceptedRecording; - PeriodicRecording mPotentialRecording; - }; + template<typename T> + class StatType; + + template<typename T> + class CountStatHandle; + + template<typename T> + class SampleStatHandle; + + template<typename T> + class EventStatHandle; + + template<typename T> + struct RelatedTypes + { + typedef F64 fractional_t; + typedef T sum_t; + }; + + template<typename T, typename UNIT_T> + struct RelatedTypes<LLUnit<T, UNIT_T> > + { + typedef LLUnit<typename RelatedTypes<T>::fractional_t, UNIT_T> fractional_t; + typedef LLUnit<typename RelatedTypes<T>::sum_t, UNIT_T> sum_t; + }; + + template<> + struct RelatedTypes<bool> + { + typedef F64 fractional_t; + typedef S32 sum_t; + }; + + class Recording + : public LLStopWatchControlsMixin<Recording> + { + public: + Recording(EPlayState state = LLStopWatchControlsMixinCommon::STOPPED); + + Recording(const Recording& other); + ~Recording(); + + Recording& operator = (const Recording& other); + + // accumulate data from subsequent, non-overlapping recording + void appendRecording(Recording& other); + + // grab latest recorded data + void update(); + + // ensure that buffers are exclusively owned by this recording + void makeUnique() { mBuffers.makeUnique(); } + + // Timer accessors + bool hasValue(const StatType<TimeBlockAccumulator>& stat); + F64Seconds getSum(const StatType<TimeBlockAccumulator>& stat); + F64Seconds getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat); + S32 getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat); + + F64Seconds getPerSec(const StatType<TimeBlockAccumulator>& stat); + F64Seconds getPerSec(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat); + F32 getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& stat); + + // CountStatHandle accessors + bool hasValue(const StatType<CountAccumulator>& stat); + F64 getSum(const StatType<CountAccumulator>& stat); + template <typename T> + typename RelatedTypes<T>::sum_t getSum(const CountStatHandle<T>& stat) + { + return (typename RelatedTypes<T>::sum_t)getSum(static_cast<const StatType<CountAccumulator>&> (stat)); + } + + F64 getPerSec(const StatType<CountAccumulator>& stat); + template <typename T> + typename RelatedTypes<T>::fractional_t getPerSec(const CountStatHandle<T>& stat) + { + return (typename RelatedTypes<T>::fractional_t)getPerSec(static_cast<const StatType<CountAccumulator>&> (stat)); + } + + S32 getSampleCount(const StatType<CountAccumulator>& stat); + + + // SampleStatHandle accessors + bool hasValue(const StatType<SampleAccumulator>& stat); + + F64 getMin(const StatType<SampleAccumulator>& stat); + template <typename T> + T getMin(const SampleStatHandle<T>& stat) + { + return (T)getMin(static_cast<const StatType<SampleAccumulator>&> (stat)); + } + + F64 getMax(const StatType<SampleAccumulator>& stat); + template <typename T> + T getMax(const SampleStatHandle<T>& stat) + { + return (T)getMax(static_cast<const StatType<SampleAccumulator>&> (stat)); + } + + F64 getMean(const StatType<SampleAccumulator>& stat); + template <typename T> + typename RelatedTypes<T>::fractional_t getMean(SampleStatHandle<T>& stat) + { + return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const StatType<SampleAccumulator>&> (stat)); + } + + F64 getStandardDeviation(const StatType<SampleAccumulator>& stat); + template <typename T> + typename RelatedTypes<T>::fractional_t getStandardDeviation(const SampleStatHandle<T>& stat) + { + return (typename RelatedTypes<T>::fractional_t)getStandardDeviation(static_cast<const StatType<SampleAccumulator>&> (stat)); + } + + F64 getLastValue(const StatType<SampleAccumulator>& stat); + template <typename T> + T getLastValue(const SampleStatHandle<T>& stat) + { + return (T)getLastValue(static_cast<const StatType<SampleAccumulator>&> (stat)); + } + + S32 getSampleCount(const StatType<SampleAccumulator>& stat); + + // EventStatHandle accessors + bool hasValue(const StatType<EventAccumulator>& stat); + + F64 getSum(const StatType<EventAccumulator>& stat); + template <typename T> + typename RelatedTypes<T>::sum_t getSum(const EventStatHandle<T>& stat) + { + return (typename RelatedTypes<T>::sum_t)getSum(static_cast<const StatType<EventAccumulator>&> (stat)); + } + + F64 getMin(const StatType<EventAccumulator>& stat); + template <typename T> + T getMin(const EventStatHandle<T>& stat) + { + return (T)getMin(static_cast<const StatType<EventAccumulator>&> (stat)); + } + + F64 getMax(const StatType<EventAccumulator>& stat); + template <typename T> + T getMax(const EventStatHandle<T>& stat) + { + return (T)getMax(static_cast<const StatType<EventAccumulator>&> (stat)); + } + + F64 getMean(const StatType<EventAccumulator>& stat); + template <typename T> + typename RelatedTypes<T>::fractional_t getMean(EventStatHandle<T>& stat) + { + return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const StatType<EventAccumulator>&> (stat)); + } + + F64 getStandardDeviation(const StatType<EventAccumulator>& stat); + template <typename T> + typename RelatedTypes<T>::fractional_t getStandardDeviation(const EventStatHandle<T>& stat) + { + return (typename RelatedTypes<T>::fractional_t)getStandardDeviation(static_cast<const StatType<EventAccumulator>&> (stat)); + } + + F64 getLastValue(const StatType<EventAccumulator>& stat); + template <typename T> + T getLastValue(const EventStatHandle<T>& stat) + { + return (T)getLastValue(static_cast<const StatType<EventAccumulator>&> (stat)); + } + + S32 getSampleCount(const StatType<EventAccumulator>& stat); + + F64Seconds getDuration() const { return mElapsedSeconds; } + + protected: + friend class ThreadRecorder; + + // implementation for LLStopWatchControlsMixin + /*virtual*/ void handleStart(); + /*virtual*/ void handleStop(); + /*virtual*/ void handleReset(); + /*virtual*/ void handleSplitTo(Recording& other); + + // returns data for current thread + class ThreadRecorder* getThreadRecorder(); + + LLTimer mSamplingTimer; + F64Seconds mElapsedSeconds; + LLCopyOnWritePointer<AccumulatorBufferGroup> mBuffers; + AccumulatorBufferGroup* mActiveBuffers; + + }; + + class LL_COMMON_API PeriodicRecording + : public LLStopWatchControlsMixin<PeriodicRecording> + { + public: + PeriodicRecording(size_t num_periods, EPlayState state = STOPPED); + ~PeriodicRecording(); + + void nextPeriod(); + auto getNumRecordedPeriods() + { + // current period counts if not active + return mNumRecordedPeriods + (isStarted() ? 0 : 1); + } + + F64Seconds getDuration() const; + + void appendPeriodicRecording(PeriodicRecording& other); + void appendRecording(Recording& recording); + Recording& getLastRecording(); + const Recording& getLastRecording() const; + Recording& getCurRecording(); + const Recording& getCurRecording() const; + Recording& getPrevRecording(size_t offset); + const Recording& getPrevRecording(size_t offset) const; + Recording snapshotCurRecording() const; + + template <typename T> + auto getSampleCount(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + num_periods = llmin(num_periods, getNumRecordedPeriods()); + + size_t num_samples = 0; + for (size_t i = 1; i <= num_periods; i++) + { + Recording& recording = getPrevRecording(i); + num_samples += recording.getSampleCount(stat); + } + return num_samples; + } + + // + // PERIODIC MIN + // + + // catch all for stats that have a defined sum + template <typename T> + typename T::value_t getPeriodMin(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + num_periods = llmin(num_periods, getNumRecordedPeriods()); + + bool has_value = false; + typename T::value_t min_val(std::numeric_limits<typename T::value_t>::max()); + for (size_t i = 1; i <= num_periods; i++) + { + Recording& recording = getPrevRecording(i); + if (recording.hasValue(stat)) + { + min_val = llmin(min_val, recording.getSum(stat)); + has_value = true; + } + } + + return has_value + ? min_val + : T::getDefaultValue(); + } + + template<typename T> + T getPeriodMin(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + return T(getPeriodMin(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); + } + + F64 getPeriodMin(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); + template<typename T> + T getPeriodMin(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + return T(getPeriodMin(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods)); + } + + F64 getPeriodMin(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); + template<typename T> + T getPeriodMin(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + return T(getPeriodMin(static_cast<const StatType<EventAccumulator>&>(stat), num_periods)); + } + + template <typename T> + typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + num_periods = llmin(num_periods, getNumRecordedPeriods()); + + typename RelatedTypes<typename T::value_t>::fractional_t min_val(std::numeric_limits<F64>::max()); + for (size_t i = 1; i <= num_periods; i++) + { + Recording& recording = getPrevRecording(i); + min_val = llmin(min_val, recording.getPerSec(stat)); + } + return (typename RelatedTypes<typename T::value_t>::fractional_t) min_val; + } + + template<typename T> + typename RelatedTypes<T>::fractional_t getPeriodMinPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + return typename RelatedTypes<T>::fractional_t(getPeriodMinPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); + } + + // + // PERIODIC MAX + // + + // catch all for stats that have a defined sum + template <typename T> + typename T::value_t getPeriodMax(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + num_periods = llmin(num_periods, getNumRecordedPeriods()); + + bool has_value = false; + typename T::value_t max_val(std::numeric_limits<typename T::value_t>::min()); + for (size_t i = 1; i <= num_periods; i++) + { + Recording& recording = getPrevRecording(i); + if (recording.hasValue(stat)) + { + max_val = llmax(max_val, recording.getSum(stat)); + has_value = true; + } + } + + return has_value + ? max_val + : T::getDefaultValue(); + } + + template<typename T> + T getPeriodMax(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + return T(getPeriodMax(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); + } + + F64 getPeriodMax(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); + template<typename T> + T getPeriodMax(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + return T(getPeriodMax(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods)); + } + + F64 getPeriodMax(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); + template<typename T> + T getPeriodMax(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + return T(getPeriodMax(static_cast<const StatType<EventAccumulator>&>(stat), num_periods)); + } + + template <typename T> + typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + num_periods = llmin(num_periods, getNumRecordedPeriods()); + + F64 max_val = std::numeric_limits<F64>::min(); + for (size_t i = 1; i <= num_periods; i++) + { + Recording& recording = getPrevRecording(i); + max_val = llmax(max_val, recording.getPerSec(stat)); + } + return (typename RelatedTypes<typename T::value_t>::fractional_t)max_val; + } + + template<typename T> + typename RelatedTypes<T>::fractional_t getPeriodMaxPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + return typename RelatedTypes<T>::fractional_t(getPeriodMaxPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); + } + + // + // PERIODIC MEAN + // + + // catch all for stats that have a defined sum + template <typename T> + typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const StatType<T >& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + num_periods = llmin(num_periods, getNumRecordedPeriods()); + + typename RelatedTypes<typename T::value_t>::fractional_t mean(0); + + for (size_t i = 1; i <= num_periods; i++) + { + Recording& recording = getPrevRecording(i); + if (recording.getDuration() > (F32Seconds)0.f) + { + mean += recording.getSum(stat); + } + } + return (num_periods + ? typename RelatedTypes<typename T::value_t>::fractional_t(mean / num_periods) + : typename RelatedTypes<typename T::value_t>::fractional_t(NaN)); + } + + template<typename T> + typename RelatedTypes<T>::fractional_t getPeriodMean(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); + } + F64 getPeriodMean(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); + template<typename T> + typename RelatedTypes<T>::fractional_t getPeriodMean(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods)); + } + + F64 getPeriodMean(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); + template<typename T> + typename RelatedTypes<T>::fractional_t getPeriodMean(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<EventAccumulator>&>(stat), num_periods)); + } + + template <typename T> + typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + num_periods = llmin(num_periods, getNumRecordedPeriods()); + + typename RelatedTypes<typename T::value_t>::fractional_t mean = 0; + + for (size_t i = 1; i <= num_periods; i++) + { + Recording& recording = getPrevRecording(i); + if (recording.getDuration() > (F32Seconds)0.f) + { + mean += recording.getPerSec(stat); + } + } + + return (num_periods + ? typename RelatedTypes<typename T::value_t>::fractional_t(mean / num_periods) + : typename RelatedTypes<typename T::value_t>::fractional_t(NaN)); + } + + template<typename T> + typename RelatedTypes<T>::fractional_t getPeriodMeanPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); + } + + F64 getPeriodMedian( const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); + + template <typename T> + typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMedianPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + num_periods = llmin(num_periods, getNumRecordedPeriods()); + + std::vector <typename RelatedTypes<typename T::value_t>::fractional_t> buf; + for (size_t i = 1; i <= num_periods; i++) + { + Recording& recording = getPrevRecording(i); + if (recording.getDuration() > (F32Seconds)0.f) + { + buf.push_back(recording.getPerSec(stat)); + } + } + std::sort(buf.begin(), buf.end()); + + return typename RelatedTypes<T>::fractional_t((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]); + } + + template<typename T> + typename RelatedTypes<T>::fractional_t getPeriodMedianPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + return typename RelatedTypes<T>::fractional_t(getPeriodMedianPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); + } + + // + // PERIODIC STANDARD DEVIATION + // + + F64 getPeriodStandardDeviation(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); + + template<typename T> + typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods)); + } + + F64 getPeriodStandardDeviation(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); + template<typename T> + typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) + { + LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; + return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<EventAccumulator>&>(stat), num_periods)); + } + + private: + // implementation for LLStopWatchControlsMixin + /*virtual*/ void handleStart(); + /*virtual*/ void handleStop(); + /*virtual*/ void handleReset(); + /*virtual*/ void handleSplitTo(PeriodicRecording& other); + + // helper methods for wraparound ring-buffer arithmetic + inline + size_t wrapi(size_t i) const + { + return i % mRecordingPeriods.size(); + } + + inline + size_t nexti(size_t i, size_t offset=1) const + { + return wrapi(i + offset); + } + + inline + size_t previ(size_t i, size_t offset=1) const + { + auto num_periods = mRecordingPeriods.size(); + // constrain offset + offset = llclamp(offset, 0, num_periods - 1); + // add size() so expression can't go (unsigned) "negative" + return wrapi(i + num_periods - offset); + } + + inline + void inci(size_t& i, size_t offset=1) const + { + i = nexti(i, offset); + } + + private: + std::vector<Recording> mRecordingPeriods; + const bool mAutoResize; + size_t mCurPeriod; + size_t mNumRecordedPeriods; + }; + + PeriodicRecording& get_frame_recording(); + + class ExtendableRecording + : public LLStopWatchControlsMixin<ExtendableRecording> + { + public: + void extend(); + + Recording& getAcceptedRecording() { return mAcceptedRecording; } + const Recording& getAcceptedRecording() const {return mAcceptedRecording;} + + Recording& getPotentialRecording() { return mPotentialRecording; } + const Recording& getPotentialRecording() const { return mPotentialRecording;} + + private: + // implementation for LLStopWatchControlsMixin + /*virtual*/ void handleStart(); + /*virtual*/ void handleStop(); + /*virtual*/ void handleReset(); + /*virtual*/ void handleSplitTo(ExtendableRecording& other); + + private: + Recording mAcceptedRecording; + Recording mPotentialRecording; + }; + + class ExtendablePeriodicRecording + : public LLStopWatchControlsMixin<ExtendablePeriodicRecording> + { + public: + ExtendablePeriodicRecording(); + void extend(); + + PeriodicRecording& getResults() { return mAcceptedRecording; } + const PeriodicRecording& getResults() const {return mAcceptedRecording;} + + void nextPeriod() { mPotentialRecording.nextPeriod(); } + + private: + // implementation for LLStopWatchControlsMixin + /*virtual*/ void handleStart(); + /*virtual*/ void handleStop(); + /*virtual*/ void handleReset(); + /*virtual*/ void handleSplitTo(ExtendablePeriodicRecording& other); + + private: + PeriodicRecording mAcceptedRecording; + PeriodicRecording mPotentialRecording; + }; } #endif // LL_LLTRACERECORDING_H |