diff options
author | Richard Linden <none@none> | 2012-10-10 20:15:21 -0700 |
---|---|---|
committer | Richard Linden <none@none> | 2012-10-10 20:15:21 -0700 |
commit | b3107e37643743118840d3f5437e62196bae3581 (patch) | |
tree | af6cbc569e7912303da6dbc3146fe9a1a229f992 /indra/llcommon | |
parent | 05510799e5a69eafcc919e72d25cf5b89c9274cf (diff) | |
parent | 74ac0182ec8f7a0f6d0ea89f5814f0998ab90b62 (diff) |
merge
Diffstat (limited to 'indra/llcommon')
-rw-r--r-- | indra/llcommon/llqueuedthread.cpp | 2 | ||||
-rw-r--r-- | indra/llcommon/llthread.cpp | 1 | ||||
-rw-r--r-- | indra/llcommon/lltrace.cpp | 1 | ||||
-rw-r--r-- | indra/llcommon/lltrace.h | 80 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.cpp | 110 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.h | 142 | ||||
-rw-r--r-- | indra/llcommon/lltracethreadrecorder.cpp | 10 | ||||
-rw-r--r-- | indra/llcommon/llunit.h | 124 |
8 files changed, 269 insertions, 201 deletions
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index 6e2a2b140f..218f6dbcd0 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -28,7 +28,7 @@ #include "llstl.h" #include "lltimer.h" // ms_sleep() -#include "lltrace.h" +#include "lltracethreadrecorder.h" //============================================================================ diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 6723e427f5..cc661bab59 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -33,6 +33,7 @@ #include "lltimer.h" #include "lltrace.h" +#include "lltracethreadrecorder.h" #if LL_LINUX || LL_SOLARIS #include <sched.h> diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp index 2b1c8d8ce8..d5911ece25 100644 --- a/indra/llcommon/lltrace.cpp +++ b/indra/llcommon/lltrace.cpp @@ -27,6 +27,7 @@ #include "lltrace.h" #include "lltracerecording.h" +#include "lltracethreadrecorder.h" namespace LLTrace { diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h index e655a3582e..a6334e176b 100644 --- a/indra/llcommon/lltrace.h +++ b/indra/llcommon/lltrace.h @@ -32,9 +32,9 @@ #include "llmemory.h" #include "llrefcount.h" -#include "lltracerecording.h" -#include "lltracethreadrecorder.h" +//#include "lltracethreadrecorder.h" #include "llunit.h" +#include "llapr.h" #include <list> @@ -44,6 +44,8 @@ namespace LLTrace { + class Recording; + void init(); void cleanup(); @@ -89,23 +91,23 @@ namespace LLTrace return mStorage[index]; } - void mergeSamples(const AccumulatorBuffer<ACCUMULATOR>& other) + void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other) { llassert(mNextStorageSlot == other.mNextStorageSlot); for (size_t i = 0; i < mNextStorageSlot; i++) { - mStorage[i].mergeSamples(other.mStorage[i]); + mStorage[i].addSamples(other.mStorage[i]); } } - void mergeDeltas(const AccumulatorBuffer<ACCUMULATOR>& start, const AccumulatorBuffer<ACCUMULATOR>& finish) + void addDeltas(const AccumulatorBuffer<ACCUMULATOR>& start, const AccumulatorBuffer<ACCUMULATOR>& finish) { llassert(mNextStorageSlot == start.mNextStorageSlot && mNextStorageSlot == finish.mNextStorageSlot); for (size_t i = 0; i < mNextStorageSlot; i++) { - mStorage[i].mergeDeltas(start.mStorage[i], finish.mStorage[i]); + mStorage[i].addDeltas(start.mStorage[i], finish.mStorage[i]); } } @@ -173,8 +175,9 @@ namespace LLTrace class LL_COMMON_API TraceType { public: - TraceType(const std::string& name) - : mName(name) + TraceType(const char* name, const char* description = NULL) + : mName(name), + mDescription(description ? description : "") { mAccumulatorIndex = AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer().reserveSlot(); } @@ -189,6 +192,7 @@ namespace LLTrace protected: std::string mName; + std::string mDescription; size_t mAccumulatorIndex; }; @@ -201,6 +205,8 @@ namespace LLTrace : mSum(0), mMin(0), mMax(0), + mMean(0), + mVarianceSum(0), mNumSamples(0) {} @@ -218,10 +224,11 @@ namespace LLTrace } F32 old_mean = mMean; mMean += ((F32)value - old_mean) / (F32)mNumSamples; - mStandardDeviation += ((F32)value - old_mean) * ((F32)value - mMean); + mVarianceSum += ((F32)value - old_mean) * ((F32)value - mMean); + mLastValue = value; } - void mergeSamples(const MeasurementAccumulator<T>& other) + void addSamples(const MeasurementAccumulator<T>& other) { mSum += other.mSum; if (other.mMin < mMin) @@ -240,19 +247,20 @@ namespace LLTrace n_2 = (F32)other.mNumSamples; F32 m_1 = mMean, m_2 = other.mMean; - F32 sd_1 = mStandardDeviation, - sd_2 = other.mStandardDeviation; + F32 sd_1 = getStandardDeviation(), + sd_2 = other.getStandardDeviation(); // combine variance (and hence standard deviation) of 2 different sized sample groups using // the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm - F32 variance = ((((n_1 - 1.f) * sd_1 * sd_1) + mVarianceSum = (F32)mNumSamples + * ((((n_1 - 1.f) * sd_1 * sd_1) + ((n_2 - 1.f) * sd_2 * sd_2) + (((n_1 * n_2) / (n_1 + n_2)) * ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2)))) / (n_1 + n_2 - 1.f)); - mStandardDeviation = sqrtf(variance); + mLastValue = other.mLastValue; } - void mergeDeltas(const MeasurementAccumulator<T>& start, const MeasurementAccumulator<T>& finish) + void addDeltas(const MeasurementAccumulator<T>& start, const MeasurementAccumulator<T>& finish) { llerrs << "Delta merge invalid for measurement accumulators" << llendl; } @@ -268,16 +276,18 @@ namespace LLTrace T getSum() const { return mSum; } T getMin() const { return mMin; } T getMax() const { return mMax; } + T getLastValue() const { return mLastValue; } F32 getMean() const { return mMean; } - F32 getStandardDeviation() const { return mStandardDeviation; } + F32 getStandardDeviation() const { return sqrtf(mVarianceSum / mNumSamples); } private: T mSum, mMin, - mMax; + mMax, + mLastValue; F32 mMean, - mStandardDeviation; + mVarianceSum; U32 mNumSamples; }; @@ -297,13 +307,13 @@ namespace LLTrace mSum += value; } - void mergeSamples(const RateAccumulator<T>& other) + void addSamples(const RateAccumulator<T>& other) { mSum += other.mSum; mNumSamples += other.mNumSamples; } - void mergeDeltas(const RateAccumulator<T>& start, const RateAccumulator<T>& finish) + void addDeltas(const RateAccumulator<T>& start, const RateAccumulator<T>& finish) { mSum += finish.mSum - start.mSum; mNumSamples += finish.mNumSamples - start.mNumSamples; @@ -329,7 +339,10 @@ namespace LLTrace public LLInstanceTracker<Measurement<T, IS_UNIT>, std::string> { public: - Measurement(const std::string& name) + typedef T storage_t; + typedef T base_unit_t; + + Measurement(const char* name, const char* description = NULL) : TraceType(name), LLInstanceTracker(name) {} @@ -345,8 +358,11 @@ namespace LLTrace : public Measurement<typename T::value_t> { public: + typedef typename T::storage_t storage_t; + typedef typename T::base_unit_t base_unit_t; + typedef Measurement<typename T::value_t> base_measurement_t; - Measurement(const std::string& name) + Measurement(const char* name, const char* description = NULL) : Measurement<typename T::value_t>(name) {} @@ -363,7 +379,10 @@ namespace LLTrace public LLInstanceTracker<Rate<T>, std::string> { public: - Rate(const std::string& name) + typedef T storage_t; + typedef T base_unit_t; + + Rate(const char* name, const char* description = NULL) : TraceType(name), LLInstanceTracker(name) {} @@ -379,7 +398,10 @@ namespace LLTrace : public Rate<typename T::value_t> { public: - Rate(const std::string& name) + typedef typename T::storage_t storage_t; + typedef typename T::base_unit_t base_unit_t; + + Rate(const char* name, const char* description = NULL) : Rate<typename T::value_t>(name) {} @@ -394,7 +416,9 @@ namespace LLTrace class LL_COMMON_API Count { public: - Count(const std::string& name) + typedef typename Rate<T>::base_unit_t base_unit_t; + + Count(const char* name) : mIncrease(name + "_increase"), mDecrease(name + "_decrease"), mTotal(name) @@ -413,7 +437,7 @@ namespace LLTrace mTotal.add(value); } private: - friend class LLTrace::Recording; + friend LLTrace::Recording; Rate<T> mIncrease; Rate<T> mDecrease; Rate<T> mTotal; @@ -433,14 +457,14 @@ namespace LLTrace bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame std::vector<TimerAccumulator*> mChildren; // currently assumed child timers - void mergeSamples(const TimerAccumulator& other) + void addSamples(const TimerAccumulator& other) { mTotalTimeCounter += other.mTotalTimeCounter; mChildTimeCounter += other.mChildTimeCounter; mCalls += other.mCalls; } - void mergeDeltas(const TimerAccumulator& start, const TimerAccumulator& finish) + void addDeltas(const TimerAccumulator& start, const TimerAccumulator& finish) { mTotalTimeCounter += finish.mTotalTimeCounter - start.mTotalTimeCounter; mChildTimeCounter += finish.mChildTimeCounter - start.mChildTimeCounter; diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp index 9a08770bd7..0883930319 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -25,8 +25,9 @@ #include "linden_common.h" -#include "lltracerecording.h" #include "lltrace.h" +#include "lltracerecording.h" +#include "lltracethreadrecorder.h" #include "llthread.h" namespace LLTrace @@ -49,7 +50,7 @@ Recording::~Recording() void Recording::update() { if (isStarted()) - { +{ LLTrace::get_thread_recorder()->update(this); mElapsedSeconds = 0.0; mSamplingTimer.reset(); @@ -67,16 +68,16 @@ void Recording::handleReset() } void Recording::handleStart() -{ - mSamplingTimer.reset(); - LLTrace::get_thread_recorder()->activate(this); + { + mSamplingTimer.reset(); + LLTrace::get_thread_recorder()->activate(this); } void Recording::handleStop() -{ - mElapsedSeconds += mSamplingTimer.getElapsedTimeF64(); - LLTrace::get_thread_recorder()->deactivate(this); -} + { + mElapsedSeconds += mSamplingTimer.getElapsedTimeF64(); + LLTrace::get_thread_recorder()->deactivate(this); + } void Recording::handleSplitTo(Recording& other) { @@ -92,99 +93,22 @@ void Recording::makePrimary() mStackTimers.write()->makePrimary(); } -bool Recording::isPrimary() +bool Recording::isPrimary() const { return mRates->isPrimary(); } void Recording::mergeRecording( const Recording& other ) { - mRates.write()->mergeSamples(*other.mRates); - mMeasurements.write()->mergeSamples(*other.mMeasurements); - mStackTimers.write()->mergeSamples(*other.mStackTimers); -} - -void Recording::mergeDeltas(const Recording& baseline, const Recording& target) -{ - mRates.write()->mergeDeltas(*baseline.mRates, *target.mRates); - mStackTimers.write()->mergeDeltas(*baseline.mStackTimers, *target.mStackTimers); + mRates.write()->addSamples(*other.mRates); + mMeasurements.write()->addSamples(*other.mMeasurements); + mStackTimers.write()->addSamples(*other.mStackTimers); } - -F32 Recording::getSum(const Rate<F32>& stat) -{ - return stat.getAccumulator(mRates).getSum(); -} - -F32 Recording::getPerSec(const Rate<F32>& stat) +void Recording::mergeRecordingDelta(const Recording& baseline, const Recording& target) { - return stat.getAccumulator(mRates).getSum() / mElapsedSeconds; + mRates.write()->addDeltas(*baseline.mRates, *target.mRates); + mStackTimers.write()->addDeltas(*baseline.mStackTimers, *target.mStackTimers); } -F32 Recording::getSum(const Measurement<F32>& stat) -{ - return stat.getAccumulator(mMeasurements).getSum(); -} - -F32 Recording::getMin(const Measurement<F32>& stat) -{ - return stat.getAccumulator(mMeasurements).getMin(); -} - -F32 Recording::getMax(const Measurement<F32>& stat) -{ - return stat.getAccumulator(mMeasurements).getMax(); -} - -F32 Recording::getMean(const Measurement<F32>& stat) -{ - return stat.getAccumulator(mMeasurements).getMean(); -} - -F32 Recording::getStandardDeviation(const Measurement<F32>& stat) -{ - return stat.getAccumulator(mMeasurements).getStandardDeviation(); -} - -F32 Recording::getSum(const Count<F32>& stat) -{ - return getSum(stat.mTotal); -} - -F32 Recording::getPerSec(const Count<F32>& stat) -{ - return getPerSec(stat.mTotal); -} - -F32 Recording::getIncrease(const Count<F32>& stat) -{ - return getSum(stat.mIncrease); -} - -F32 Recording::getIncreasePerSec(const Count<F32>& stat) -{ - return getPerSec(stat.mIncrease); -} - -F32 Recording::getDecrease(const Count<F32>& stat) -{ - return getSum(stat.mDecrease); -} - -F32 Recording::getDecreasePerSec(const Count<F32>& stat) -{ - return getPerSec(stat.mDecrease); -} - -F32 Recording::getChurn(const Count<F32>& stat) -{ - return getIncrease(stat) + getDecrease(stat); -} - -F32 Recording::getChurnPerSec(const Count<F32>& stat) -{ - return getIncreasePerSec(stat) + getDecreasePerSec(stat); -} - - } diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index 4399a65cfb..0a1a02fa02 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -32,6 +32,7 @@ #include "llpointer.h" #include "lltimer.h" +#include "lltrace.h" template<typename DERIVED> class LL_COMMON_API LLVCRControlsMixinInterface @@ -176,13 +177,13 @@ private: namespace LLTrace { - template<typename T, typename IS_UNIT> class Rate; - template<typename T, typename IS_UNIT> class Measurement; - template<typename T> class Count; - template<typename T> class AccumulatorBuffer; - template<typename T> class RateAccumulator; - template<typename T> class MeasurementAccumulator; - class TimerAccumulator; + //template<typename T, typename IS_UNIT> class Rate; + //template<typename T, typename IS_UNIT> class Measurement; + //template<typename T> class Count; + //template<typename T> class AccumulatorBuffer; + //template<typename T> class RateAccumulator; + //template<typename T> class MeasurementAccumulator; + //class TimerAccumulator; class LL_COMMON_API Recording : public LLVCRControlsMixin<Recording> { @@ -192,37 +193,120 @@ namespace LLTrace ~Recording(); void makePrimary(); - bool isPrimary(); + bool isPrimary() const; void mergeRecording(const Recording& other); - void mergeDeltas(const Recording& baseline, const Recording& target); + void mergeRecordingDelta(const Recording& baseline, const Recording& target); - void reset(); void update(); - + // Rate accessors - F32 getSum(const Rate<F32, void>& stat); - F32 getPerSec(const Rate<F32, void>& stat); + template <typename T, typename IS_UNIT> + typename Rate<T, IS_UNIT>::base_unit_t getSum(const Rate<T, IS_UNIT>& stat) const + { + return (typename Rate<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mRates).getSum(); + } + + template <typename T, typename IS_UNIT> + typename Rate<T, IS_UNIT>::base_unit_t getPerSec(const Rate<T, IS_UNIT>& stat) const + { + return (typename Rate<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mRates).getSum() / mElapsedSeconds; + } // Measurement accessors - F32 getSum(const Measurement<F32, void>& stat); - F32 getPerSec(const Measurement<F32, void>& stat); - F32 getMin(const Measurement<F32, void>& stat); - F32 getMax(const Measurement<F32, void>& stat); - F32 getMean(const Measurement<F32, void>& stat); - F32 getStandardDeviation(const Measurement<F32, void>& stat); + template <typename T, typename IS_UNIT> + typename Measurement<T, IS_UNIT>::base_unit_t getSum(const Measurement<T, IS_UNIT>& stat) const + { + return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getSum(); + + } + + template <typename T, typename IS_UNIT> + typename Measurement<T, IS_UNIT>::base_unit_t getPerSec(const Measurement<T, IS_UNIT>& stat) const + { + return (typename Rate<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getSum() / mElapsedSeconds; + } + + template <typename T, typename IS_UNIT> + typename Measurement<T, IS_UNIT>::base_unit_t getMin(const Measurement<T, IS_UNIT>& stat) const + { + return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getMin(); + } + + template <typename T, typename IS_UNIT> + typename Measurement<T, IS_UNIT>::base_unit_t getMax(const Measurement<T, IS_UNIT>& stat) const + { + return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getMax(); + } + + template <typename T, typename IS_UNIT> + typename Measurement<T, IS_UNIT>::base_unit_t getMean(const Measurement<T, IS_UNIT>& stat) const + { + return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getMean(); + } + + template <typename T, typename IS_UNIT> + typename Measurement<T, IS_UNIT>::base_unit_t getStandardDeviation(const Measurement<T, IS_UNIT>& stat) const + { + return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getStandardDeviation(); + } + + template <typename T, typename IS_UNIT> + typename Measurement<T, IS_UNIT>::base_unit_t getLastValue(const Measurement<T, IS_UNIT>& stat) const + { + return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getLastValue(); + } // Count accessors - F32 getSum(const Count<F32>& stat); - F32 getPerSec(const Count<F32>& stat); - F32 getIncrease(const Count<F32>& stat); - F32 getIncreasePerSec(const Count<F32>& stat); - F32 getDecrease(const Count<F32>& stat); - F32 getDecreasePerSec(const Count<F32>& stat); - F32 getChurn(const Count<F32>& stat); - F32 getChurnPerSec(const Count<F32>& stat); + template <typename T> + typename Count<T>::base_unit_t getSum(const Count<T>& stat) const + { + return getSum(stat.mTotal); + } + + template <typename T> + typename Count<T>::base_unit_t getPerSec(const Count<T>& stat) const + { + return getPerSec(stat.mTotal); + } + + template <typename T> + typename Count<T>::base_unit_t getIncrease(const Count<T>& stat) const + { + return getPerSec(stat.mTotal); + } + + template <typename T> + typename Count<T>::base_unit_t getIncreasePerSec(const Count<T>& stat) const + { + return getPerSec(stat.mIncrease); + } + + template <typename T> + typename Count<T>::base_unit_t getDecrease(const Count<T>& stat) const + { + return getPerSec(stat.mDecrease); + } - F64 getSampleTime() { return mElapsedSeconds; } + template <typename T> + typename Count<T>::base_unit_t getDecreasePerSec(const Count<T>& stat) const + { + return getPerSec(stat.mDecrease); + } + + template <typename T> + typename Count<T>::base_unit_t getChurn(const Count<T>& stat) const + { + return getIncrease(stat) + getDecrease(stat); + } + + template <typename T> + typename Count<T>::base_unit_t getChurnPerSec(const Count<T>& stat) const + { + return getIncreasePerSec(stat) + getDecreasePerSec(stat); + } + + F64 getSampleTime() const { return mElapsedSeconds; } private: friend class PeriodicRecording; @@ -254,7 +338,7 @@ namespace LLTrace mCurPeriod(0), mTotalValid(false), mRecordingPeriods(new Recording[num_periods]) - { + { llassert(mNumPeriods > 0); } diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp index 4d020f5650..3acd06d553 100644 --- a/indra/llcommon/lltracethreadrecorder.cpp +++ b/indra/llcommon/lltracethreadrecorder.cpp @@ -25,7 +25,7 @@ #include "linden_common.h" -#include "lltrace.h" +#include "lltracethreadrecorder.h" namespace LLTrace { @@ -118,16 +118,16 @@ ThreadRecorder::ActiveRecording::ActiveRecording( Recording* source, Recording* void ThreadRecorder::ActiveRecording::mergeMeasurements(ThreadRecorder::ActiveRecording& other) { - mBaseline.mMeasurements.write()->mergeSamples(*other.mBaseline.mMeasurements); + mBaseline.mMeasurements.write()->addSamples(*other.mBaseline.mMeasurements); } void ThreadRecorder::ActiveRecording::flushAccumulators(Recording* current) { // accumulate statistics-like measurements - mTargetRecording->mMeasurements.write()->mergeSamples(*mBaseline.mMeasurements); + mTargetRecording->mMeasurements.write()->addSamples(*mBaseline.mMeasurements); // for rate-like measurements, merge total change since baseline - mTargetRecording->mRates.write()->mergeDeltas(*mBaseline.mRates, *current->mRates); - mTargetRecording->mStackTimers.write()->mergeDeltas(*mBaseline.mStackTimers, *current->mStackTimers); + mTargetRecording->mRates.write()->addDeltas(*mBaseline.mRates, *current->mRates); + mTargetRecording->mStackTimers.write()->addDeltas(*mBaseline.mStackTimers, *current->mStackTimers); // reset baselines mBaseline.mRates.write()->copyFrom(*current->mRates); mBaseline.mStackTimers.write()->copyFrom(*current->mStackTimers); diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h index 52b837fdc3..2664bd77e9 100644 --- a/indra/llcommon/llunit.h +++ b/indra/llcommon/llunit.h @@ -30,21 +30,24 @@ #include "stdtypes.h" #include "llpreprocessor.h" -template<typename BASE_UNIT, typename DERIVED_UNIT = BASE_UNIT> -struct LLUnit : public BASE_UNIT +template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT = BASE_UNIT> +struct LLUnitType : public BASE_UNIT { - typedef LLUnit<BASE_UNIT, DERIVED_UNIT> unit_t; + typedef DERIVED_UNIT unit_t; typedef typename BASE_UNIT::value_t value_t; typedef void is_unit_t; - LLUnit() + LLUnitType() {} - explicit LLUnit(value_t value) + explicit LLUnitType(value_t value) : BASE_UNIT(convertToBase(value)) {} - operator value_t() { return value(); } + operator unit_t& () + { + return static_cast<unit_t&>(*this); + } value_t value() const { @@ -59,47 +62,72 @@ struct LLUnit : public BASE_UNIT static value_t convertToBase(value_t derived_value) { - return (value_t)((F32)derived_value * DERIVED_UNIT::conversionToBaseFactor()); + return (value_t)((F32)derived_value * unit_t::conversionToBaseFactor()); } static value_t convertToDerived(value_t base_value) { - return (value_t)((F32)base_value / DERIVED_UNIT::conversionToBaseFactor()); + return (value_t)((F32)base_value / unit_t::conversionToBaseFactor()); + } + + unit_t operator + (const unit_t other) const + { + return unit_t(mValue + other.mValue); + } + + unit_t operator - (const unit_t other) const + { + return unit_t(mValue - other.mValue); + } + + unit_t operator * (value_t multiplicand) const + { + return unit_t(mValue * multiplicand); + } + + unit_t operator / (value_t divisor) const + { + return unit_t(mValue / divisor); } }; -template<typename T> -struct LLUnit<T, T> +template<typename STORAGE_TYPE, typename T> +struct LLUnitType<STORAGE_TYPE, T, T> { - typedef LLUnit<T, T> unit_t; - typedef T value_t; + typedef T unit_t; + typedef typename STORAGE_TYPE value_t; typedef void is_unit_t; - LLUnit() + LLUnitType() : mValue() {} - explicit LLUnit(T value) + explicit LLUnitType(value_t value) : mValue(value) {} - unit_t& operator=(T value) + unit_t& operator=(value_t value) { setBaseValue(value); return *this; } + operator unit_t& () + { + return static_cast<unit_t&>(*this); + } + value_t value() { return mValue; } static value_t convertToBase(value_t derived_value) { - return (value_t)1; + return (value_t)derived_value; } static value_t convertToDerived(value_t base_value) { - return (value_t)1; + return (value_t)base_value; } unit_t operator + (const unit_t other) const @@ -143,68 +171,74 @@ struct LLUnit<T, T> } protected: - void setBaseValue(T value) + void setBaseValue(value_t value) { mValue = value; } - T mValue; + value_t mValue; }; #define LL_DECLARE_BASE_UNIT(unit_name) \ template<typename STORAGE_TYPE> \ - struct unit_name : public LLUnit<STORAGE_TYPE> \ + struct unit_name : public LLUnitType<STORAGE_TYPE, unit_name<STORAGE_TYPE> > \ { \ + typedef unit_name<STORAGE_TYPE> base_unit_t; \ + typedef STORAGE_TYPE storage_t; \ + \ unit_name(STORAGE_TYPE value) \ - : LLUnit(value) \ + : LLUnitType(value) \ {} \ \ unit_name() \ {} \ \ - template <typename T> \ - unit_name(const LLUnit<unit_name, T>& other) \ + template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE> \ + unit_name(const LLUnitType<SOURCE_STORAGE_TYPE, unit_name, SOURCE_TYPE>& source) \ { \ - setBaseValue(other.unit_name::get()); \ + setBaseValue(source.unit_t::value()); \ } \ \ - using LLUnit<STORAGE_TYPE>::operator +; \ - using LLUnit<STORAGE_TYPE>::operator +=; \ - using LLUnit<STORAGE_TYPE>::operator -; \ - using LLUnit<STORAGE_TYPE>::operator -=; \ - using LLUnit<STORAGE_TYPE>::operator *; \ - using LLUnit<STORAGE_TYPE>::operator *=; \ - using LLUnit<STORAGE_TYPE>::operator /; \ - using LLUnit<STORAGE_TYPE>::operator /=; \ + using LLUnitType::operator +; \ + using LLUnitType::operator +=; \ + using LLUnitType::operator -; \ + using LLUnitType::operator -=; \ + using LLUnitType::operator *; \ + using LLUnitType::operator *=; \ + using LLUnitType::operator /; \ + using LLUnitType::operator /=; \ }; #define LL_DECLARE_DERIVED_UNIT(base_unit, derived_unit, conversion_factor) \ template<typename STORAGE_TYPE> \ - struct derived_unit : public LLUnit<base_unit<STORAGE_TYPE>, derived_unit<STORAGE_TYPE> > \ + struct derived_unit : public LLUnitType<STORAGE_TYPE, base_unit<STORAGE_TYPE>, derived_unit<STORAGE_TYPE> > \ { \ + typedef base_unit<STORAGE_TYPE> base_unit_t; \ + typedef STORAGE_TYPE storage_t; \ + \ derived_unit(value_t value) \ - : LLUnit(value) \ + : LLUnitType(value) \ {} \ \ derived_unit() \ {} \ \ - template <typename T> \ - derived_unit(const LLUnit<base_unit<STORAGE_TYPE>, T>& other) \ + template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE> \ + derived_unit(const LLUnitType<SOURCE_STORAGE_TYPE, base_unit<STORAGE_TYPE>, SOURCE_TYPE>& source) \ { \ - setBaseValue(other.base_unit<STORAGE_TYPE>::get()); \ + setBaseValue(source.base_unit_t::value()); \ } \ \ static F32 conversionToBaseFactor() { return (F32)(conversion_factor); } \ \ - using LLUnit<STORAGE_TYPE>::operator +; \ - using LLUnit<STORAGE_TYPE>::operator +=; \ - using LLUnit<STORAGE_TYPE>::operator -; \ - using LLUnit<STORAGE_TYPE>::operator -=; \ - using LLUnit<STORAGE_TYPE>::operator *; \ - using LLUnit<STORAGE_TYPE>::operator *=; \ - using LLUnit<STORAGE_TYPE>::operator /; \ - using LLUnit<STORAGE_TYPE>::operator /=; \ + using LLUnitType::operator +; \ + using LLUnitType::operator +=; \ + using LLUnitType::operator -; \ + using LLUnitType::operator -=; \ + using LLUnitType::operator *; \ + using LLUnitType::operator *=; \ + using LLUnitType::operator /; \ + using LLUnitType::operator /=; \ }; namespace LLUnits |