diff options
author | Richard Linden <none@none> | 2013-06-17 01:20:27 -0700 |
---|---|---|
committer | Richard Linden <none@none> | 2013-06-17 01:20:27 -0700 |
commit | 1cb0c974ae410479a1f72dab556ef7c9371970ee (patch) | |
tree | 91a97b4b05e8085fdad17173b7ca874bb98a8805 /indra/llcommon | |
parent | fc88265cffe3553803314c6e895a1e3a3c988171 (diff) | |
parent | 3f2de87340b1c831ea59e4a3ca960d49f343c9fd (diff) |
Merge
Diffstat (limited to 'indra/llcommon')
-rwxr-xr-x | indra/llcommon/llcriticaldamp.cpp | 2 | ||||
-rwxr-xr-x | indra/llcommon/llcriticaldamp.h | 4 | ||||
-rwxr-xr-x | indra/llcommon/lldate.cpp | 2 | ||||
-rwxr-xr-x | indra/llcommon/lldate.h | 2 | ||||
-rwxr-xr-x | indra/llcommon/llfasttimer.cpp | 18 | ||||
-rwxr-xr-x | indra/llcommon/llfasttimer.h | 2 | ||||
-rwxr-xr-x | indra/llcommon/llprocessor.cpp | 2 | ||||
-rwxr-xr-x | indra/llcommon/llprocessor.h | 2 | ||||
-rwxr-xr-x | indra/llcommon/lltimer.cpp | 14 | ||||
-rwxr-xr-x | indra/llcommon/lltimer.h | 16 | ||||
-rw-r--r-- | indra/llcommon/lltrace.h | 86 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.cpp | 200 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.h | 58 | ||||
-rw-r--r-- | indra/llcommon/llunit.h | 442 | ||||
-rw-r--r-- | indra/llcommon/tests/llunits_test.cpp | 110 |
15 files changed, 530 insertions, 430 deletions
diff --git a/indra/llcommon/llcriticaldamp.cpp b/indra/llcommon/llcriticaldamp.cpp index 2f013fe255..575fc4149e 100755 --- a/indra/llcommon/llcriticaldamp.cpp +++ b/indra/llcommon/llcriticaldamp.cpp @@ -81,7 +81,7 @@ void LLSmoothInterpolation::updateInterpolants() //----------------------------------------------------------------------------- // getInterpolant() //----------------------------------------------------------------------------- -F32 LLSmoothInterpolation::getInterpolant(LLUnit<LLUnits::Seconds, F32> time_constant, bool use_cache) +F32 LLSmoothInterpolation::getInterpolant(LLUnit<F32, LLUnits::Seconds> time_constant, bool use_cache) { if (time_constant == 0.f) { diff --git a/indra/llcommon/llcriticaldamp.h b/indra/llcommon/llcriticaldamp.h index ab5d4ba6e2..e174643cd0 100755 --- a/indra/llcommon/llcriticaldamp.h +++ b/indra/llcommon/llcriticaldamp.h @@ -42,10 +42,10 @@ public: static void updateInterpolants(); // ACCESSORS - static F32 getInterpolant(LLUnit<LLUnits::Seconds, F32> time_constant, bool use_cache = true); + static F32 getInterpolant(LLUnit<F32, LLUnits::Seconds> time_constant, bool use_cache = true); template<typename T> - static T lerp(T a, T b, LLUnit<LLUnits::Seconds, F32> time_constant, bool use_cache = true) + static T lerp(T a, T b, LLUnit<F32, LLUnits::Seconds> time_constant, bool use_cache = true) { F32 interpolant = getInterpolant(time_constant, use_cache); return ((a * (1.f - interpolant)) diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index 2efe39e158..7892269e35 100755 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -55,7 +55,7 @@ LLDate::LLDate(const LLDate& date) : mSecondsSinceEpoch(date.mSecondsSinceEpoch) {} -LLDate::LLDate(LLUnit<LLUnits::Seconds, F64> seconds_since_epoch) : +LLDate::LLDate(LLUnit<F64, LLUnits::Seconds> seconds_since_epoch) : mSecondsSinceEpoch(seconds_since_epoch.value()) {} diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index b62a846147..1067ac5280 100755 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -59,7 +59,7 @@ public: * * @param seconds_since_epoch The number of seconds since UTC epoch. */ - LLDate(LLUnit<LLUnits::Seconds, F64> seconds_since_epoch); + LLDate(LLUnit<F64, LLUnits::Seconds> seconds_since_epoch); /** * @brief Construct a date from a string representation diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp index dfc72bd2ce..d9670891f8 100755 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -146,8 +146,8 @@ U64 TimeBlock::countsPerSecond() { #if LL_FASTTIMER_USE_RDTSC || !LL_WINDOWS //getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz - static LLUnit<LLUnits::Hertz, U64> sCPUClockFrequency = LLProcessorInfo().getCPUFrequency(); - + static LLUnit<U64, LLUnits::Hertz> sCPUClockFrequency = LLProcessorInfo().getCPUFrequency(); + return sCPUClockFrequency.value(); #else // If we're not using RDTSC, each fasttimer tick is just a performance counter tick. // Not redefining the clock frequency itself (in llprocessor.cpp/calculate_cpu_frequency()) @@ -159,8 +159,8 @@ U64 TimeBlock::countsPerSecond() QueryPerformanceFrequency((LARGE_INTEGER*)&sCPUClockFrequency); firstcall = false; } -#endif return sCPUClockFrequency.value(); +#endif } #endif @@ -318,11 +318,11 @@ void TimeBlock::logStats() LL_DEBUGS("FastTimers") << "LLProcessorInfo().getCPUFrequency() " << LLProcessorInfo().getCPUFrequency() << LL_ENDL; LL_DEBUGS("FastTimers") << "getCPUClockCount32() " << getCPUClockCount32() << LL_ENDL; LL_DEBUGS("FastTimers") << "getCPUClockCount64() " << getCPUClockCount64() << LL_ENDL; - LL_DEBUGS("FastTimers") << "elapsed sec " << ((F64)getCPUClockCount64()) / (LLUnit<LLUnits::Hertz, F64>(LLProcessorInfo().getCPUFrequency())) << LL_ENDL; + LL_DEBUGS("FastTimers") << "elapsed sec " << ((F64)getCPUClockCount64()) / (LLUnit<F64, LLUnits::Hertz>(LLProcessorInfo().getCPUFrequency())) << LL_ENDL; } call_count++; - LLUnit<LLUnits::Seconds, F64> total_time(0); + LLUnit<F64, LLUnits::Seconds> total_time(0); LLSD sd; { @@ -365,11 +365,11 @@ void TimeBlock::dumpCurTimes() ++it) { TimeBlock* timerp = (*it); - LLUnit<LLUnits::Seconds, F64> total_time_ms = last_frame_recording.getSum(*timerp); + LLUnit<F64, LLUnits::Seconds> total_time = last_frame_recording.getSum(*timerp); U32 num_calls = last_frame_recording.getSum(timerp->callCount()); // Don't bother with really brief times, keep output concise - if (total_time_ms < 0.1) continue; + if (total_time < LLUnit<F32, LLUnits::Milliseconds>(0.1)) continue; std::ostringstream out_str; TimeBlock* parent_timerp = timerp; @@ -380,7 +380,7 @@ void TimeBlock::dumpCurTimes() } out_str << timerp->getName() << " " - << std::setprecision(3) << total_time_ms.as<LLUnits::Milliseconds>().value() << " ms, " + << std::setprecision(3) << total_time.getAs<LLUnits::Milliseconds>() << " ms, " << num_calls << " calls"; llinfos << out_str.str() << llendl; @@ -449,7 +449,7 @@ void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other ) } } -LLUnit<LLUnits::Seconds, F64> BlockTimer::getElapsedTime() +LLUnit<F64, LLUnits::Seconds> BlockTimer::getElapsedTime() { U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime; diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 20514d1638..fdc6997d45 100755 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -71,7 +71,7 @@ public: BlockTimer(TimeBlock& timer); ~BlockTimer(); - LLUnit<LLUnits::Seconds, F64> getElapsedTime(); + LLUnit<F64, LLUnits::Seconds> getElapsedTime(); private: diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index 5ddfa6fcef..b80e813d84 100755 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -875,7 +875,7 @@ LLProcessorInfo::LLProcessorInfo() : mImpl(NULL) LLProcessorInfo::~LLProcessorInfo() {} -LLUnitImplicit<LLUnits::Megahertz, F64> LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); } +LLUnitImplicit<F64, LLUnits::Megahertz> LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); } bool LLProcessorInfo::hasSSE() const { return mImpl->hasSSE(); } bool LLProcessorInfo::hasSSE2() const { return mImpl->hasSSE2(); } bool LLProcessorInfo::hasAltivec() const { return mImpl->hasAltivec(); } diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h index fbd427f484..7f220467b0 100755 --- a/indra/llcommon/llprocessor.h +++ b/indra/llcommon/llprocessor.h @@ -37,7 +37,7 @@ public: LLProcessorInfo(); ~LLProcessorInfo(); - LLUnitImplicit<LLUnits::Megahertz, F64> getCPUFrequency() const; + LLUnitImplicit<F64, LLUnits::Megahertz> getCPUFrequency() const; bool hasSSE() const; bool hasSSE2() const; bool hasAltivec() const; diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index 838155d54d..693809b622 100755 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -285,14 +285,14 @@ LLTimer::~LLTimer() } // static -LLUnitImplicit<LLUnits::Microseconds, U64> LLTimer::getTotalTime() +LLUnitImplicit<U64, LLUnits::Microseconds> LLTimer::getTotalTime() { // simply call into the implementation function. return totalTime(); } // static -LLUnitImplicit<LLUnits::Seconds, F64> LLTimer::getTotalSeconds() +LLUnitImplicit<F64, LLUnits::Seconds> LLTimer::getTotalSeconds() { return U64_to_F64(getTotalTime()) * USEC_TO_SEC_F64; } @@ -341,23 +341,23 @@ U64 getElapsedTimeAndUpdate(U64& lastClockCount) } -LLUnitImplicit<LLUnits::Seconds, F64> LLTimer::getElapsedTimeF64() const +LLUnitImplicit<F64, LLUnits::Seconds> LLTimer::getElapsedTimeF64() const { U64 last = mLastClockCount; return (F64)getElapsedTimeAndUpdate(last) * gClockFrequencyInv; } -LLUnitImplicit<LLUnits::Seconds, F32> LLTimer::getElapsedTimeF32() const +LLUnitImplicit<F32, LLUnits::Seconds> LLTimer::getElapsedTimeF32() const { return (F32)getElapsedTimeF64(); } -LLUnitImplicit<LLUnits::Seconds, F64> LLTimer::getElapsedTimeAndResetF64() +LLUnitImplicit<F64, LLUnits::Seconds> LLTimer::getElapsedTimeAndResetF64() { return (F64)getElapsedTimeAndUpdate(mLastClockCount) * gClockFrequencyInv; } -LLUnitImplicit<LLUnits::Seconds, F32> LLTimer::getElapsedTimeAndResetF32() +LLUnitImplicit<F32, LLUnits::Seconds> LLTimer::getElapsedTimeAndResetF32() { return (F32)getElapsedTimeAndResetF64(); } @@ -370,7 +370,7 @@ void LLTimer::setTimerExpirySec(F32 expiration) + (U64)((F32)(expiration * gClockFrequency)); } -LLUnitImplicit<LLUnits::Seconds, F32> LLTimer::getRemainingTimeF32() const +LLUnitImplicit<F32, LLUnits::Seconds> LLTimer::getRemainingTimeF32() const { U64 cur_ticks = get_clock_count(); if (cur_ticks > mExpirationTicks) diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h index 0ba87d1e15..9e464c4b1a 100755 --- a/indra/llcommon/lltimer.h +++ b/indra/llcommon/lltimer.h @@ -67,16 +67,16 @@ public: // Return a high precision number of seconds since the start of // this application instance. - static LLUnitImplicit<LLUnits::Seconds, F64> getElapsedSeconds() + static LLUnitImplicit<F64, LLUnits::Seconds> getElapsedSeconds() { return sTimer->getElapsedTimeF64(); } // Return a high precision usec since epoch - static LLUnitImplicit<LLUnits::Microseconds, U64> getTotalTime(); + static LLUnitImplicit<U64, LLUnits::Microseconds> getTotalTime(); // Return a high precision seconds since epoch - static LLUnitImplicit<LLUnits::Seconds, F64> getTotalSeconds(); + static LLUnitImplicit<F64, LLUnits::Seconds> getTotalSeconds(); // MANIPULATORS @@ -87,16 +87,16 @@ public: void setTimerExpirySec(F32 expiration); BOOL checkExpirationAndReset(F32 expiration); BOOL hasExpired() const; - LLUnitImplicit<LLUnits::Seconds, F32> getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset - LLUnitImplicit<LLUnits::Seconds, F64> getElapsedTimeAndResetF64(); + LLUnitImplicit<F32, LLUnits::Seconds> getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset + LLUnitImplicit<F64, LLUnits::Seconds> getElapsedTimeAndResetF64(); - LLUnitImplicit<LLUnits::Seconds, F32> getRemainingTimeF32() const; + LLUnitImplicit<F32, LLUnits::Seconds> getRemainingTimeF32() const; static BOOL knownBadTimer(); // ACCESSORS - LLUnitImplicit<LLUnits::Seconds, F32> getElapsedTimeF32() const; // Returns elapsed time in seconds - LLUnitImplicit<LLUnits::Seconds, F64> getElapsedTimeF64() const; // Returns elapsed time in seconds + LLUnitImplicit<F32, LLUnits::Seconds> getElapsedTimeF32() const; // Returns elapsed time in seconds + LLUnitImplicit<F64, LLUnits::Seconds> getElapsedTimeF64() const; // Returns elapsed time in seconds bool getStarted() const { return mStarted; } diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h index cfe1273b4b..cd377531e8 100644 --- a/indra/llcommon/lltrace.h +++ b/indra/llcommon/lltrace.h @@ -44,27 +44,37 @@ namespace LLTrace { class Recording; -typedef LLUnit<LLUnits::Bytes, F64> Bytes; -typedef LLUnit<LLUnits::Kibibytes, F64> Kibibytes; -typedef LLUnit<LLUnits::Mibibytes, F64> Mibibytes; -typedef LLUnit<LLUnits::Gibibytes, F64> Gibibytes; -typedef LLUnit<LLUnits::Bits, F64> Bits; -typedef LLUnit<LLUnits::Kibibits, F64> Kibibits; -typedef LLUnit<LLUnits::Mibibits, F64> Mibibits; -typedef LLUnit<LLUnits::Gibibits, F64> Gibibits; - -typedef LLUnit<LLUnits::Seconds, F64> Seconds; -typedef LLUnit<LLUnits::Milliseconds, F64> Milliseconds; -typedef LLUnit<LLUnits::Minutes, F64> Minutes; -typedef LLUnit<LLUnits::Hours, F64> Hours; -typedef LLUnit<LLUnits::Milliseconds, F64> Milliseconds; -typedef LLUnit<LLUnits::Microseconds, F64> Microseconds; -typedef LLUnit<LLUnits::Nanoseconds, F64> Nanoseconds; - -typedef LLUnit<LLUnits::Meters, F64> Meters; -typedef LLUnit<LLUnits::Kilometers, F64> Kilometers; -typedef LLUnit<LLUnits::Centimeters, F64> Centimeters; -typedef LLUnit<LLUnits::Millimeters, F64> Millimeters; +typedef LLUnit<F64, LLUnits::Bytes> Bytes; +typedef LLUnit<F64, LLUnits::Kibibytes> Kibibytes; +typedef LLUnit<F64, LLUnits::Mibibytes> Mibibytes; +typedef LLUnit<F64, LLUnits::Gibibytes> Gibibytes; +typedef LLUnit<F64, LLUnits::Bits> Bits; +typedef LLUnit<F64, LLUnits::Kibibits> Kibibits; +typedef LLUnit<F64, LLUnits::Mibibits> Mibibits; +typedef LLUnit<F64, LLUnits::Gibibits> Gibibits; + +typedef LLUnit<F64, LLUnits::Seconds> Seconds; +typedef LLUnit<F64, LLUnits::Milliseconds> Milliseconds; +typedef LLUnit<F64, LLUnits::Minutes> Minutes; +typedef LLUnit<F64, LLUnits::Hours> Hours; +typedef LLUnit<F64, LLUnits::Milliseconds> Milliseconds; +typedef LLUnit<F64, LLUnits::Microseconds> Microseconds; +typedef LLUnit<F64, LLUnits::Nanoseconds> Nanoseconds; + +typedef LLUnit<F64, LLUnits::Meters> Meters; +typedef LLUnit<F64, LLUnits::Kilometers> Kilometers; +typedef LLUnit<F64, LLUnits::Centimeters> Centimeters; +typedef LLUnit<F64, LLUnits::Millimeters> Millimeters; + + +template<typename T> +T storage_value(T val) { return val; } + +template<typename UNIT_TYPE, typename STORAGE_TYPE> +STORAGE_TYPE storage_value(LLUnit<STORAGE_TYPE, UNIT_TYPE> val) { return val.value(); } + +template<typename UNIT_TYPE, typename STORAGE_TYPE> +STORAGE_TYPE storage_value(LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> val) { return val.value(); } void init(); void cleanup(); @@ -217,6 +227,11 @@ public: size_t size() const { + return getNumIndices(); + } + + static size_t getNumIndices() + { return sNextStorageSlot; } @@ -263,6 +278,7 @@ public: } size_t getIndex() const { return mAccumulatorIndex; } + static size_t getNumIndices() { return AccumulatorBuffer<ACCUMULATOR>::getNumIndices(); } virtual const char* getUnitLabel() { return ""; } @@ -408,8 +424,8 @@ public: void sample(F64 value) { - LLUnitImplicit<LLUnits::Seconds, F64> time_stamp = LLTimer::getTotalSeconds(); - LLUnitImplicit<LLUnits::Seconds, F64> delta_time = time_stamp - mLastSampleTimeStamp; + LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds(); + LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp; mLastSampleTimeStamp = time_stamp; if (mHasValue) @@ -498,8 +514,8 @@ public: void flush() { - LLUnitImplicit<LLUnits::Seconds, F64> time_stamp = LLTimer::getTotalSeconds(); - LLUnitImplicit<LLUnits::Seconds, F64> delta_time = time_stamp - mLastSampleTimeStamp; + LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds(); + LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp; if (mHasValue) { @@ -528,7 +544,7 @@ private: F64 mMean, mVarianceSum; - LLUnitImplicit<LLUnits::Seconds, F64> mLastSampleTimeStamp, + LLUnitImplicit<F64, LLUnits::Seconds> mLastSampleTimeStamp, mTotalSamplingTime; U32 mNumSamples; @@ -578,8 +594,8 @@ private: class TimeBlockAccumulator { public: - typedef LLUnit<LLUnits::Seconds, F64> value_t; - typedef LLUnit<LLUnits::Seconds, F64> mean_t; + typedef LLUnit<F64, LLUnits::Seconds> value_t; + typedef LLUnit<F64, LLUnits::Seconds> mean_t; typedef TimeBlockAccumulator self_t; // fake classes that allows us to view different facets of underlying statistic @@ -591,8 +607,8 @@ public: struct SelfTimeFacet { - typedef LLUnit<LLUnits::Seconds, F64> value_t; - typedef LLUnit<LLUnits::Seconds, F64> mean_t; + typedef LLUnit<F64, LLUnits::Seconds> value_t; + typedef LLUnit<F64, LLUnits::Seconds> mean_t; }; TimeBlockAccumulator(); @@ -672,7 +688,7 @@ template<typename T, typename VALUE_T> void record(EventStatHandle<T>& measurement, VALUE_T value) { T converted_value(value); - measurement.getPrimaryAccumulator()->record(LLUnits::rawValue(converted_value)); + measurement.getPrimaryAccumulator()->record(storage_value(converted_value)); } template <typename T = F64> @@ -694,7 +710,7 @@ template<typename T, typename VALUE_T> void sample(SampleStatHandle<T>& measurement, VALUE_T value) { T converted_value(value); - measurement.getPrimaryAccumulator()->sample(LLUnits::rawValue(converted_value)); + measurement.getPrimaryAccumulator()->sample(storage_value(converted_value)); } template <typename T = F64> @@ -716,7 +732,7 @@ template<typename T, typename VALUE_T> void add(CountStatHandle<T>& count, VALUE_T value) { T converted_value(value); - count.getPrimaryAccumulator()->add(LLUnits::rawValue(converted_value)); + count.getPrimaryAccumulator()->add(storage_value(converted_value)); } @@ -739,8 +755,8 @@ struct MemStatAccumulator struct ChildMemFacet { - typedef LLUnit<LLUnits::Bytes, F64> value_t; - typedef LLUnit<LLUnits::Bytes, F64> mean_t; + typedef LLUnit<F64, LLUnits::Bytes> value_t; + typedef LLUnit<F64, LLUnits::Bytes> mean_t; }; MemStatAccumulator() diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp index d32504b014..f2c5941011 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -122,21 +122,26 @@ Recording::Recording() Recording::Recording( const Recording& other ) { + *this = other; +} + +Recording& Recording::operator = (const Recording& other) +{ // this will allow us to seamlessly start without affecting any data we've acquired from other setPlayState(PAUSED); Recording& mutable_other = const_cast<Recording&>(other); + mutable_other.update(); EPlayState other_play_state = other.getPlayState(); - mutable_other.pause(); - mBuffers = other.mBuffers; + mBuffers = mutable_other.mBuffers; LLStopWatchControlsMixin<Recording>::setPlayState(other_play_state); - mutable_other.setPlayState(other_play_state); // above call will clear mElapsedSeconds as a side effect, so copy it here mElapsedSeconds = other.mElapsedSeconds; mSamplingTimer = other.mSamplingTimer; + return *this; } @@ -186,26 +191,18 @@ void Recording::handleSplitTo(Recording& other) void Recording::appendRecording( const Recording& other ) { - EPlayState play_state = getPlayState(); - { - pause(); - mBuffers.write()->append(*other.mBuffers); - mElapsedSeconds += other.mElapsedSeconds; - } - setPlayState(play_state); + update(); + mBuffers.write()->append(*other.mBuffers); + mElapsedSeconds += other.mElapsedSeconds; } void Recording::mergeRecording( const Recording& other) { - EPlayState play_state = getPlayState(); - { - pause(); - mBuffers.write()->merge(*other.mBuffers); - } - setPlayState(play_state); + update(); + mBuffers.write()->merge(*other.mBuffers); } -LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat) +LLUnit<F64, LLUnits::Seconds> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat) { const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; update(); @@ -213,7 +210,7 @@ LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumul / (F64)LLTrace::TimeBlock::countsPerSecond(); } -LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat) +LLUnit<F64, LLUnits::Seconds> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat) { const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; update(); @@ -227,85 +224,85 @@ U32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountFacet>& sta return mBuffers->mStackTimers[stat.getIndex()].mCalls; } -LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator>& stat) +LLUnit<F64, LLUnits::Seconds> Recording::getPerSec(const TraceType<TimeBlockAccumulator>& stat) { const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; update(); return (F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) - / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds); + / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value()); } -LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat) +LLUnit<F64, LLUnits::Seconds> Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat) { const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; update(); return (F64)(accumulator.mSelfTimeCounter) - / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds); + / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value()); } F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat) { update(); - return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds; + return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds.value(); } -LLUnit<LLUnits::Bytes, F64> Recording::getMin(const TraceType<MemStatAccumulator>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getMin(const TraceType<MemStatAccumulator>& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getMin(); } -LLUnit<LLUnits::Bytes, F64> Recording::getMean(const TraceType<MemStatAccumulator>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getMean(const TraceType<MemStatAccumulator>& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getMean(); } -LLUnit<LLUnits::Bytes, F64> Recording::getMax(const TraceType<MemStatAccumulator>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getMax(const TraceType<MemStatAccumulator>& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getMax(); } -LLUnit<LLUnits::Bytes, F64> Recording::getStandardDeviation(const TraceType<MemStatAccumulator>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getStandardDeviation(const TraceType<MemStatAccumulator>& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation(); } -LLUnit<LLUnits::Bytes, F64> Recording::getLastValue(const TraceType<MemStatAccumulator>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getLastValue(const TraceType<MemStatAccumulator>& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue(); } -LLUnit<LLUnits::Bytes, F64> Recording::getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMin(); } -LLUnit<LLUnits::Bytes, F64> Recording::getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMean(); } -LLUnit<LLUnits::Bytes, F64> Recording::getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMax(); } -LLUnit<LLUnits::Bytes, F64> Recording::getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getStandardDeviation(); } -LLUnit<LLUnits::Bytes, F64> Recording::getLastValue(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) +LLUnit<F64, LLUnits::Bytes> Recording::getLastValue(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) { update(); return mBuffers->mMemStats[stat.getIndex()].mChildSize.getLastValue(); @@ -341,7 +338,7 @@ F64 Recording::getPerSec( const TraceType<CountAccumulator>& stat ) update(); F64 sum = mBuffers->mCounts[stat.getIndex()].getSum(); return (sum != 0.0) - ? (sum / mElapsedSeconds) + ? (sum / mElapsedSeconds.value()) : 0.0; } @@ -430,6 +427,7 @@ U32 Recording::getSampleCount( const TraceType<EventAccumulator>& stat ) PeriodicRecording::PeriodicRecording( U32 num_periods, EPlayState state) : mAutoResize(num_periods == 0), mCurPeriod(0), + mNumPeriods(0), mRecordingPeriods(num_periods ? num_periods : 1) { setPlayState(state); @@ -443,9 +441,16 @@ void PeriodicRecording::nextPeriod() } Recording& old_recording = getCurRecording(); - mCurPeriod = (mCurPeriod + 1) % mRecordingPeriods.size(); old_recording.splitTo(getCurRecording()); + + mNumPeriods = llmin(mRecordingPeriods.size(), mNumPeriods + 1); +} + +void PeriodicRecording::appendRecording(Recording& recording) +{ + getCurRecording().appendRecording(recording); + nextPeriod(); } @@ -453,77 +458,71 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other ) { if (other.mRecordingPeriods.empty()) return; - EPlayState play_state = getPlayState(); - pause(); + getCurRecording().update(); + other.getCurRecording().update(); - EPlayState other_play_state = other.getPlayState(); - other.pause(); - - U32 other_recording_count = other.mRecordingPeriods.size(); - - Recording& other_oldest_recording = other.mRecordingPeriods[(other.mCurPeriod + 1) % other.mRecordingPeriods.size()]; - - // if I have a recording of any length, then close it off and start a fresh one - if (getCurRecording().getDuration().value()) + if (mAutoResize) { - nextPeriod(); - } - getCurRecording().appendRecording(other_oldest_recording); + S32 other_index = (other.mCurPeriod + 1) % other.mRecordingPeriods.size(); + S32 end_index = (other.mCurPeriod) % other.mRecordingPeriods.size(); - if (other_recording_count > 1) - { - if (mAutoResize) + do { - for (S32 other_index = (other.mCurPeriod + 2) % other_recording_count, - end_index = (other.mCurPeriod + 1) % other_recording_count; - other_index != end_index; - other_index = (other_index + 1) % other_recording_count) + if (other.mRecordingPeriods[other_index].getDuration().value()) { - llassert(other.mRecordingPeriods[other_index].getDuration() != 0.f - && (mRecordingPeriods.empty() - || other.mRecordingPeriods[other_index].getDuration() != mRecordingPeriods.back().getDuration())); mRecordingPeriods.push_back(other.mRecordingPeriods[other_index]); } - - mCurPeriod = mRecordingPeriods.size() - 1; + other_index = (other_index + 1) % other.mRecordingPeriods.size(); } - else + while(other_index != end_index); + + mCurPeriod = mRecordingPeriods.size() - 1; + mNumPeriods = mRecordingPeriods.size(); + } + else + { + //FIXME: get proper number of recordings from other...might not have used all its slots + size_t num_to_copy = llmin( mRecordingPeriods.size(), other.getNumRecordedPeriods()); + std::vector<Recording>::iterator src_it = other.mRecordingPeriods.begin() + + ( (other.mCurPeriod + 1 // oldest period + + (other.mRecordingPeriods.size() - num_to_copy)) // minus room for copy + % other.mRecordingPeriods.size()); + std::vector<Recording>::iterator dest_it = mRecordingPeriods.begin() + mCurPeriod; + + for(size_t i = 0; i < num_to_copy; i++) { - size_t num_to_copy = llmin( mRecordingPeriods.size(), other.mRecordingPeriods.size() - 1); - std::vector<Recording>::iterator src_it = other.mRecordingPeriods.begin() - + ( (other.mCurPeriod + 1 // oldest period - + (other.mRecordingPeriods.size() - num_to_copy)) // minus room for copy - % other.mRecordingPeriods.size()); - std::vector<Recording>::iterator dest_it = mRecordingPeriods.begin() + ((mCurPeriod + 1) % mRecordingPeriods.size()); - - for(S32 i = 0; i < num_to_copy; i++) - { - *dest_it = *src_it; + *dest_it = *src_it; - if (++src_it == other.mRecordingPeriods.end()) - { - src_it = other.mRecordingPeriods.begin(); - } + if (++src_it == other.mRecordingPeriods.end()) + { + src_it = other.mRecordingPeriods.begin(); + } - if (++dest_it == mRecordingPeriods.end()) - { - dest_it = mRecordingPeriods.begin(); - } + if (++dest_it == mRecordingPeriods.end()) + { + dest_it = mRecordingPeriods.begin(); } - - mCurPeriod = (mCurPeriod + num_to_copy) % mRecordingPeriods.size(); } + + // want argument to % to be positive, otherwise result could be negative and thus out of bounds + llassert(num_to_copy >= 1); + // advance to last recording period copied, so we can check if the last period had actually carried any data, in which case we'll advance below + // using nextPeriod() which retains continuity (mLastValue, etc) + mCurPeriod = (mCurPeriod + num_to_copy - 1) % mRecordingPeriods.size(); + mNumPeriods = llmin(mRecordingPeriods.size(), mNumPeriods + num_to_copy); } - nextPeriod(); - - setPlayState(play_state); - other.setPlayState(other_play_state); + if (getCurRecording().getDuration().value()) + { + //call this to chain last period copied to new active period + nextPeriod(); + } + getCurRecording().setPlayState(getPlayState()); } -LLUnit<LLUnits::Seconds, F64> PeriodicRecording::getDuration() const +LLUnit<F64, LLUnits::Seconds> PeriodicRecording::getDuration() const { - LLUnit<LLUnits::Seconds, F64> duration; + LLUnit<F64, LLUnits::Seconds> duration; size_t num_periods = mRecordingPeriods.size(); for (size_t i = 1; i <= num_periods; i++) { @@ -615,7 +614,7 @@ void PeriodicRecording::handleSplitTo(PeriodicRecording& other) F64 PeriodicRecording::getPeriodMean( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ ) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); F64 mean = 0; if (num_periods <= 0) { return mean; } @@ -643,7 +642,7 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<EventAccumulator>& stat, s F64 PeriodicRecording::getPeriodMin( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ ) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); F64 min_val = std::numeric_limits<F64>::max(); for (S32 i = 1; i <= num_periods; i++) @@ -657,7 +656,7 @@ F64 PeriodicRecording::getPeriodMin( const TraceType<EventAccumulator>& stat, si F64 PeriodicRecording::getPeriodMax( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ ) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); F64 max_val = std::numeric_limits<F64>::min(); for (S32 i = 1; i <= num_periods; i++) @@ -671,7 +670,7 @@ F64 PeriodicRecording::getPeriodMax( const TraceType<EventAccumulator>& stat, si F64 PeriodicRecording::getPeriodMin( const TraceType<SampleAccumulator>& stat, size_t num_periods /*= U32_MAX*/ ) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); F64 min_val = std::numeric_limits<F64>::max(); for (S32 i = 1; i <= num_periods; i++) @@ -685,7 +684,7 @@ F64 PeriodicRecording::getPeriodMin( const TraceType<SampleAccumulator>& stat, s F64 PeriodicRecording::getPeriodMax(const TraceType<SampleAccumulator>& stat, size_t num_periods /*= U32_MAX*/) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); F64 max_val = std::numeric_limits<F64>::min(); for (S32 i = 1; i <= num_periods; i++) @@ -700,9 +699,9 @@ F64 PeriodicRecording::getPeriodMax(const TraceType<SampleAccumulator>& stat, si F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& stat, size_t num_periods /*= U32_MAX*/ ) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); - LLUnit<LLUnits::Seconds, F64> total_duration = 0.f; + LLUnit<F64, LLUnits::Seconds> total_duration = 0.f; F64 mean = 0; if (num_periods <= 0) { return mean; } @@ -712,7 +711,7 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& stat, S32 index = (mCurPeriod + total_periods - i) % total_periods; if (mRecordingPeriods[index].getDuration() > 0.f) { - LLUnit<LLUnits::Seconds, F64> recording_duration = mRecordingPeriods[index].getDuration(); + LLUnit<F64, LLUnits::Seconds> recording_duration = mRecordingPeriods[index].getDuration(); mean += mRecordingPeriods[index].getMean(stat) * recording_duration.value(); total_duration += recording_duration; } @@ -734,13 +733,11 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& stat, void ExtendableRecording::extend() { // stop recording to get latest data - mPotentialRecording.stop(); + mPotentialRecording.update(); // push the data back to accepted recording mAcceptedRecording.appendRecording(mPotentialRecording); // flush data, so we can start from scratch mPotentialRecording.reset(); - // go back to play state we were in initially - mPotentialRecording.setPlayState(getPlayState()); } void ExtendableRecording::handleStart() @@ -777,15 +774,10 @@ ExtendablePeriodicRecording::ExtendablePeriodicRecording() void ExtendablePeriodicRecording::extend() { - llassert(mPotentialRecording.getPlayState() == getPlayState()); - // stop recording to get latest data - mPotentialRecording.pause(); // push the data back to accepted recording mAcceptedRecording.appendPeriodicRecording(mPotentialRecording); // flush data, so we can start from scratch mPotentialRecording.reset(); - // go back to play state we were in initially - mPotentialRecording.setPlayState(getPlayState()); } diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index 4651bfcb61..b839e85de0 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -135,6 +135,8 @@ namespace LLTrace Recording(const Recording& other); ~Recording(); + Recording& operator = (const Recording& other); + // accumulate data from subsequent, non-overlapping recording void appendRecording(const Recording& other); @@ -148,26 +150,26 @@ namespace LLTrace void makeUnique() { mBuffers.makeUnique(); } // Timer accessors - LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimeBlockAccumulator>& stat); - LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat); + LLUnit<F64, LLUnits::Seconds> getSum(const TraceType<TimeBlockAccumulator>& stat); + LLUnit<F64, LLUnits::Seconds> getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat); U32 getSum(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat); - LLUnit<LLUnits::Seconds, F64> getPerSec(const TraceType<TimeBlockAccumulator>& stat); - LLUnit<LLUnits::Seconds, F64> getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat); + LLUnit<F64, LLUnits::Seconds> getPerSec(const TraceType<TimeBlockAccumulator>& stat); + LLUnit<F64, LLUnits::Seconds> getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat); F32 getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat); // Memory accessors - LLUnit<LLUnits::Bytes, F64> getMin(const TraceType<MemStatAccumulator>& stat); - LLUnit<LLUnits::Bytes, F64> getMean(const TraceType<MemStatAccumulator>& stat); - LLUnit<LLUnits::Bytes, F64> getMax(const TraceType<MemStatAccumulator>& stat); - LLUnit<LLUnits::Bytes, F64> getStandardDeviation(const TraceType<MemStatAccumulator>& stat); - LLUnit<LLUnits::Bytes, F64> getLastValue(const TraceType<MemStatAccumulator>& stat); - - LLUnit<LLUnits::Bytes, F64> getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); - LLUnit<LLUnits::Bytes, F64> getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); - LLUnit<LLUnits::Bytes, F64> getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); - LLUnit<LLUnits::Bytes, F64> getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); - LLUnit<LLUnits::Bytes, F64> getLastValue(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); + LLUnit<F64, LLUnits::Bytes> getMin(const TraceType<MemStatAccumulator>& stat); + LLUnit<F64, LLUnits::Bytes> getMean(const TraceType<MemStatAccumulator>& stat); + LLUnit<F64, LLUnits::Bytes> getMax(const TraceType<MemStatAccumulator>& stat); + LLUnit<F64, LLUnits::Bytes> getStandardDeviation(const TraceType<MemStatAccumulator>& stat); + LLUnit<F64, LLUnits::Bytes> getLastValue(const TraceType<MemStatAccumulator>& stat); + + LLUnit<F64, LLUnits::Bytes> getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); + LLUnit<F64, LLUnits::Bytes> getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); + LLUnit<F64, LLUnits::Bytes> getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); + LLUnit<F64, LLUnits::Bytes> getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); + LLUnit<F64, LLUnits::Bytes> getLastValue(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); U32 getSum(const TraceType<MemStatAccumulator::AllocationCountFacet>& stat); U32 getSum(const TraceType<MemStatAccumulator::DeallocationCountFacet>& stat); @@ -273,7 +275,7 @@ namespace LLTrace U32 getSampleCount(const TraceType<EventAccumulator>& stat); - LLUnit<LLUnits::Seconds, F64> getDuration() const { return LLUnit<LLUnits::Seconds, F64>(mElapsedSeconds); } + LLUnit<F64, LLUnits::Seconds> getDuration() const { return mElapsedSeconds; } protected: friend class ThreadRecorder; @@ -288,7 +290,7 @@ namespace LLTrace class ThreadRecorder* getThreadRecorder(); LLTimer mSamplingTimer; - F64 mElapsedSeconds; + LLUnit<F64, LLUnits::Seconds> mElapsedSeconds; LLCopyOnWritePointer<RecordingBuffers> mBuffers; }; @@ -299,11 +301,12 @@ namespace LLTrace PeriodicRecording(U32 num_periods, EPlayState state = STOPPED); void nextPeriod(); - U32 getNumPeriods() { return mRecordingPeriods.size(); } + size_t getNumRecordedPeriods() { return mNumPeriods; } - LLUnit<LLUnits::Seconds, F64> getDuration() const; + LLUnit<F64, LLUnits::Seconds> getDuration() const; void appendPeriodicRecording(PeriodicRecording& other); + void appendRecording(Recording& recording); Recording& getLastRecording(); const Recording& getLastRecording() const; Recording& getCurRecording(); @@ -317,7 +320,7 @@ namespace LLTrace typename T::value_t getPeriodMin(const TraceType<T>& stat, size_t num_periods = U32_MAX) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); typename T::value_t min_val = std::numeric_limits<typename T::value_t>::max(); for (S32 i = 1; i <= num_periods; i++) @@ -346,7 +349,7 @@ namespace LLTrace F64 getPeriodMinPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); F64 min_val = std::numeric_limits<F64>::max(); for (S32 i = 1; i <= num_periods; i++) @@ -362,7 +365,7 @@ namespace LLTrace typename T::value_t getPeriodMax(const TraceType<T>& stat, size_t num_periods = U32_MAX) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); typename T::value_t max_val = std::numeric_limits<typename T::value_t>::min(); for (S32 i = 1; i <= num_periods; i++) @@ -391,7 +394,7 @@ namespace LLTrace F64 getPeriodMaxPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); F64 max_val = std::numeric_limits<F64>::min(); for (S32 i = 1; i <= num_periods; i++) @@ -407,7 +410,7 @@ namespace LLTrace typename T::mean_t getPeriodMean(const TraceType<T >& stat, size_t num_periods = U32_MAX) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); typename T::mean_t mean = 0; if (num_periods <= 0) { return mean; } @@ -442,7 +445,7 @@ namespace LLTrace typename T::mean_t getPeriodMeanPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX) { size_t total_periods = mRecordingPeriods.size(); - num_periods = llmin(num_periods, total_periods); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); typename T::mean_t mean = 0; if (num_periods <= 0) { return mean; } @@ -468,8 +471,9 @@ namespace LLTrace private: std::vector<Recording> mRecordingPeriods; - const bool mAutoResize; - S32 mCurPeriod; + const bool mAutoResize; + size_t mCurPeriod; + size_t mNumPeriods; }; PeriodicRecording& get_frame_recording(); diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h index f48cbe0e11..5229fe69d7 100644 --- a/indra/llcommon/llunit.h +++ b/indra/llcommon/llunit.h @@ -30,36 +30,12 @@ #include "stdtypes.h" #include "llpreprocessor.h" #include "llerrorlegacy.h" +#include <boost/type_traits/is_same.hpp> -namespace LLUnits -{ - -template<typename DERIVED_UNITS_TAG, typename BASE_UNITS_TAG, typename VALUE_TYPE> -struct ConversionFactor -{ - static F64 get() - { - // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template - llstatic_assert_template(DERIVED_UNITS_TAG, false, "Cannot convert between types."); - return 0; - } -}; - -template<typename BASE_UNITS_TAG, typename VALUE_TYPE> -struct ConversionFactor<BASE_UNITS_TAG, BASE_UNITS_TAG, VALUE_TYPE> -{ - static F64 get() - { - return 1; - } -}; - -} - -template<typename UNIT_TYPE, typename STORAGE_TYPE> +template<typename STORAGE_TYPE, typename UNIT_TYPE> struct LLUnit { - typedef LLUnit<UNIT_TYPE, STORAGE_TYPE> self_t; + typedef LLUnit<STORAGE_TYPE, UNIT_TYPE> self_t; typedef STORAGE_TYPE storage_t; // value initialization @@ -68,11 +44,16 @@ struct LLUnit {} // unit initialization and conversion - template<typename OTHER_UNIT, typename OTHER_STORAGE> - LLUnit(LLUnit<OTHER_UNIT, OTHER_STORAGE> other) - : mValue(convert(other)) + template<typename OTHER_STORAGE, typename OTHER_UNIT> + LLUnit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other) + : mValue(convert(other).mValue) {} + bool operator == (const self_t& other) + { + return mValue = other.mValue; + } + // value assignment self_t& operator = (storage_t value) { @@ -81,10 +62,10 @@ struct LLUnit } // unit assignment - template<typename OTHER_UNIT, typename OTHER_STORAGE> - self_t& operator = (LLUnit<OTHER_UNIT, OTHER_STORAGE> other) + template<typename OTHER_STORAGE, typename OTHER_UNIT> + self_t& operator = (LLUnit<OTHER_STORAGE, OTHER_UNIT> other) { - mValue = convert(other); + mValue = convert(other).mValue; return *this; } @@ -93,21 +74,27 @@ struct LLUnit return mValue; } - template<typename NEW_UNIT_TYPE> LLUnit<NEW_UNIT_TYPE, STORAGE_TYPE> as() + template<typename NEW_UNIT_TYPE> + STORAGE_TYPE getAs() { - return LLUnit<NEW_UNIT_TYPE, STORAGE_TYPE>(*this); + return LLUnit<STORAGE_TYPE, NEW_UNIT_TYPE>(*this).value(); } + template<typename NEW_UNIT_TYPE> + STORAGE_TYPE setAs(STORAGE_TYPE val) + { + *this = LLUnit<STORAGE_TYPE, NEW_UNIT_TYPE>(val); + } void operator += (storage_t value) { mValue += value; } - template<typename OTHER_UNIT, typename OTHER_STORAGE> - void operator += (LLUnit<OTHER_UNIT, OTHER_STORAGE> other) + template<typename OTHER_STORAGE, typename OTHER_UNIT> + void operator += (LLUnit<OTHER_STORAGE, OTHER_UNIT> other) { - mValue += convert(other); + mValue += convert(other).mValue; } void operator -= (storage_t value) @@ -115,10 +102,10 @@ struct LLUnit mValue -= value; } - template<typename OTHER_UNIT, typename OTHER_STORAGE> - void operator -= (LLUnit<OTHER_UNIT, OTHER_STORAGE> other) + template<typename OTHER_STORAGE, typename OTHER_UNIT> + void operator -= (LLUnit<OTHER_STORAGE, OTHER_UNIT> other) { - mValue -= convert(other); + mValue -= convert(other).mValue; } void operator *= (storage_t multiplicand) @@ -127,7 +114,7 @@ struct LLUnit } template<typename OTHER_UNIT, typename OTHER_STORAGE> - void operator *= (LLUnit<OTHER_UNIT, OTHER_STORAGE> multiplicand) + void operator *= (LLUnit<OTHER_STORAGE, OTHER_UNIT> multiplicand) { // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template llstatic_assert_template(OTHER_UNIT, false, "Multiplication of unit types not supported."); @@ -139,37 +126,37 @@ struct LLUnit } template<typename OTHER_UNIT, typename OTHER_STORAGE> - void operator /= (LLUnit<OTHER_UNIT, OTHER_STORAGE> divisor) + void operator /= (LLUnit<OTHER_STORAGE, OTHER_UNIT> divisor) { // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template llstatic_assert_template(OTHER_UNIT, false, "Illegal in-place division of unit types."); } - template<typename SOURCE_UNITS, typename SOURCE_STORAGE> - static storage_t convert(LLUnit<SOURCE_UNITS, SOURCE_STORAGE> v) + template<typename SOURCE_STORAGE, typename SOURCE_UNITS> + static self_t convert(LLUnit<SOURCE_STORAGE, SOURCE_UNITS> v) { - return (storage_t)(v.value() - * LLUnits::ConversionFactor<SOURCE_UNITS, typename UNIT_TYPE::base_unit_t, SOURCE_STORAGE>::get() - * LLUnits::ConversionFactor<typename UNIT_TYPE::base_unit_t, UNIT_TYPE, STORAGE_TYPE>::get()); + self_t result; + ll_convert_units(v, result); + return result; } protected: storage_t mValue; }; -template<typename UNIT_TYPE, typename STORAGE_TYPE> -struct LLUnitImplicit : public LLUnit<UNIT_TYPE, STORAGE_TYPE> +template<typename STORAGE_TYPE, typename UNIT_TYPE> +struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE> { - typedef LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> self_t; - typedef typename LLUnit<UNIT_TYPE, STORAGE_TYPE>::storage_t storage_t; - typedef LLUnit<UNIT_TYPE, STORAGE_TYPE> base_t; + typedef LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> self_t; + typedef typename LLUnit<STORAGE_TYPE, UNIT_TYPE>::storage_t storage_t; + typedef LLUnit<STORAGE_TYPE, UNIT_TYPE> base_t; LLUnitImplicit(storage_t value = storage_t()) : base_t(value) {} - template<typename OTHER_UNIT, typename OTHER_STORAGE> - LLUnitImplicit(LLUnit<OTHER_UNIT, OTHER_STORAGE> other) + template<typename OTHER_STORAGE, typename OTHER_UNIT> + LLUnitImplicit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other) : base_t(convert(other)) {} @@ -181,53 +168,86 @@ struct LLUnitImplicit : public LLUnit<UNIT_TYPE, STORAGE_TYPE> } }; + +template<typename S1, typename T1, typename S2, typename T2> +LL_FORCE_INLINE void ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ...) +{ + static_assert(boost::is_same<T1, T2>::value + || !boost::is_same<T1, typename T1::base_unit_t>::value + || !boost::is_same<T2, typename T2::base_unit_t>::value, + "invalid conversion"); + + if (boost::is_same<T1, typename T1::base_unit_t>::value) + { + if (boost::is_same<T2, typename T2::base_unit_t>::value) + { + // T1 and T2 fully reduced and equal...just copy + out = (S2)in.value(); + } + else + { + // reduce T2 + LLUnit<S2, typename T2::base_unit_t> new_out; + ll_convert_units(in, new_out); + ll_convert_units(new_out, out); + } + } + else + { + // reduce T1 + LLUnit<S1, typename T1::base_unit_t> new_in; + ll_convert_units(in, new_in); + ll_convert_units(new_in, out); + } +} + // // operator + // -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator + (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnit<STORAGE_TYPE1, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) { - LLUnit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + LLUnit<STORAGE_TYPE1, UNIT_TYPE1> result(first); result += second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator + (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first); result += second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator + (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second) { - LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first); result += second; return result; } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator + (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) { - LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> result(first); result += second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator + (LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator + (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> result(first); result += second; return result; } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator + (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second) { - LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> result(first); result += second; return result; } @@ -235,50 +255,50 @@ LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator + (LLUnitImplicit<UNIT_TYPE1, // // operator - // -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator - (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnit<STORAGE_TYPE1, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) { - LLUnit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + LLUnit<STORAGE_TYPE1, UNIT_TYPE1> result(first); result -= second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator - (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first); result -= second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator - (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second) { - LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first); result -= second; return result; } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator - (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second) { - LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> result(first); result -= second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator - (LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator - (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> result(first); result -= second; return result; } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator - (SCALAR_TYPE first, LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator - (SCALAR_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second) { - LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> result(first); + LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> result(first); result -= second; return result; } @@ -286,102 +306,100 @@ LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator - (SCALAR_TYPE first, LLUnitImp // // operator * // -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator * (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator * (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second) { - return LLUnit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first * second.value())); + return LLUnit<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first * second.value())); } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator * (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator * (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - return LLUnit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first.value() * second)); + return LLUnit<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first.value() * second)); } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator * (LLUnit<UNIT_TYPE1, STORAGE_TYPE1>, LLUnit<UNIT_TYPE2, STORAGE_TYPE2>) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnit<STORAGE_TYPE1, UNIT_TYPE1> operator * (LLUnit<STORAGE_TYPE1, UNIT_TYPE1>, LLUnit<STORAGE_TYPE2, UNIT_TYPE2>) { // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template llstatic_assert_template(STORAGE_TYPE1, false, "Multiplication of unit types results in new unit type - not supported."); - return LLUnit<UNIT_TYPE1, STORAGE_TYPE1>(); + return LLUnit<STORAGE_TYPE1, UNIT_TYPE1>(); } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator * (SCALAR_TYPE first, LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator * (SCALAR_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second) { - return LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE>(first * second.value()); + return LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>(first * second.value()); } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator * (LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator * (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - return LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE>(first.value() * second); + return LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>(first.value() * second); } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator * (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1>, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2>) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator * (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2>) { // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template llstatic_assert_template(STORAGE_TYPE1, false, "Multiplication of unit types results in new unit type - not supported."); - return LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1>(); + return LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(); } // // operator / // -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -SCALAR_TYPE operator / (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +SCALAR_TYPE operator / (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second) { return SCALAR_TYPE(first / second.value()); } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnit<UNIT_TYPE, STORAGE_TYPE> operator / (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnit<STORAGE_TYPE, UNIT_TYPE> operator / (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - return LLUnit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first.value() / second)); + return LLUnit<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first.value() / second)); } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -STORAGE_TYPE1 operator / (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +STORAGE_TYPE1 operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) { - // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template - return STORAGE_TYPE1(first.value() / second.value()); + return STORAGE_TYPE1(first.value() / first.convert(second)); } -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> -LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator / (LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator / (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) { - return LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first.value() / second)); + return LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first.value() / second)); } -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> -STORAGE_TYPE1 operator / (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2> second) +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> +STORAGE_TYPE1 operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second) { - // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template - return STORAGE_TYPE1(first.value() / second.value()); + return STORAGE_TYPE1(first.value() / first.convert(second)); } #define COMPARISON_OPERATORS(op) \ -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> \ -bool operator op (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) \ +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> \ +bool operator op (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second) \ { \ return first op second.value(); \ } \ \ -template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> \ -bool operator op (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) \ +template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE> \ +bool operator op (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second) \ { \ return first.value() op second; \ } \ \ -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> \ -bool operator op (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2> second) \ +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> \ +bool operator op (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second) \ { \ return first.value() op first.convert(second); \ } \ \ -template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> \ - bool operator op (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) \ +template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2> \ + bool operator op (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second) \ { \ return first.value() op first.convert(second); \ } @@ -401,80 +419,142 @@ struct LLGetUnitLabel }; template<typename T, typename STORAGE_T> -struct LLGetUnitLabel<LLUnit<T, STORAGE_T> > +struct LLGetUnitLabel<LLUnit<STORAGE_T, T> > { static const char* getUnitLabel() { return T::getUnitLabel(); } }; -// -// Unit declarations -// -namespace LLUnits +template<typename VALUE_TYPE> +struct LLUnitLinearOps { -template<typename T> -T rawValue(T val) { return val; } + typedef LLUnitLinearOps<VALUE_TYPE> self_t; + LLUnitLinearOps(VALUE_TYPE val) : mValue (val) {} -template<typename UNIT_TYPE, typename STORAGE_TYPE> -STORAGE_TYPE rawValue(LLUnit<UNIT_TYPE, STORAGE_TYPE> val) { return val.value(); } + operator VALUE_TYPE() const { return mValue; } + VALUE_TYPE mValue; -template<typename UNIT_TYPE, typename STORAGE_TYPE> -STORAGE_TYPE rawValue(LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> val) { return val.value(); } + template<typename T> + self_t operator * (T other) + { + return mValue * other; + } + + template<typename T> + self_t operator / (T other) + { + return mValue / other; + } + + template<typename T> + self_t operator + (T other) + { + return mValue + other; + } + + template<typename T> + self_t operator - (T other) + { + return mValue - other; + } +}; -#define LL_DECLARE_DERIVED_UNIT(conversion_factor, base_unit_name, unit_name, unit_label) \ +template<typename VALUE_TYPE> +struct LLUnitInverseLinearOps +{ + typedef LLUnitInverseLinearOps<VALUE_TYPE> self_t; + + LLUnitInverseLinearOps(VALUE_TYPE val) : mValue (val) {} + operator VALUE_TYPE() const { return mValue; } + VALUE_TYPE mValue; + + template<typename T> + self_t operator * (T other) + { + return mValue / other; + } + + template<typename T> + self_t operator / (T other) + { + return mValue * other; + } + + template<typename T> + self_t operator + (T other) + { + return mValue - other; + } + + template<typename T> + self_t operator - (T other) + { + return mValue + other; + } +}; + +#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label) \ +struct base_unit_name { typedef base_unit_name base_unit_t; static const char* getUnitLabel() { return unit_label; }} + +#define LL_DECLARE_DERIVED_UNIT(unit_name, unit_label, base_unit_name, conversion_operation) \ struct unit_name \ { \ typedef base_unit_name base_unit_t; \ static const char* getUnitLabel() { return unit_label; } \ }; \ -template<typename STORAGE_TYPE> \ -struct ConversionFactor<unit_name, base_unit_name, STORAGE_TYPE> \ -{ \ - static F64 get() \ - { \ - return (F64)conversion_factor; \ - } \ -}; \ \ -template<typename STORAGE_TYPE> \ -struct ConversionFactor<base_unit_name, unit_name, STORAGE_TYPE> \ +template<typename S1, typename S2> \ +void ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out) \ { \ - static F64 get() \ - { \ - return (F64)(1.0 / (conversion_factor)); \ - } \ -} + out = (S2)(LLUnitLinearOps<S1>(in.value()) conversion_operation).mValue; \ +} \ + \ +template<typename S1, typename S2> \ +void ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out) \ +{ \ + out = (S2)(LLUnitInverseLinearOps<S1>(in.value()) conversion_operation).mValue; \ +} -#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label) \ -struct base_unit_name { typedef base_unit_name base_unit_t; static const char* getUnitLabel() { return unit_label; }} +// +// Unit declarations +// +namespace LLUnits +{ LL_DECLARE_BASE_UNIT(Bytes, "B"); -LL_DECLARE_DERIVED_UNIT(1024, Bytes, Kibibytes, "KiB"); -LL_DECLARE_DERIVED_UNIT(1024 * 1024, Bytes, Mibibytes, "MiB"); -LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024, Bytes, Gibibytes, "GiB"); -LL_DECLARE_DERIVED_UNIT(1.0 / 8.0, Bytes, Bits, "b"); -LL_DECLARE_DERIVED_UNIT(1024 / 8, Bytes, Kibibits, "Kib"); -LL_DECLARE_DERIVED_UNIT(1024 / 8, Bytes, Mibibits, "Mib"); -LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024 / 8, Bytes, Gibibits, "Gib"); +LL_DECLARE_DERIVED_UNIT(Kilobytes, "KB", Bytes, * 1000); +LL_DECLARE_DERIVED_UNIT(Megabytes, "MB", Kilobytes, * 1000); +LL_DECLARE_DERIVED_UNIT(Gigabytes, "GB", Megabytes, * 1000); +LL_DECLARE_DERIVED_UNIT(Kibibytes, "KiB", Bytes, * 1024); +LL_DECLARE_DERIVED_UNIT(Mibibytes, "MiB", Kibibytes, * 1024); +LL_DECLARE_DERIVED_UNIT(Gibibytes, "GiB", Mibibytes, * 1024); + +LL_DECLARE_DERIVED_UNIT(Bits, "b", Bytes, / 8); +LL_DECLARE_DERIVED_UNIT(Kilobits, "Kb", Bytes, * 1000 / 8); +LL_DECLARE_DERIVED_UNIT(Megabits, "Mb", Kilobits, * 1000 / 8); +LL_DECLARE_DERIVED_UNIT(Gigabits, "Gb", Megabits, * 1000 / 8); +LL_DECLARE_DERIVED_UNIT(Kibibits, "Kib", Bytes, * 1024 / 8); +LL_DECLARE_DERIVED_UNIT(Mibibits, "Mib", Kibibits, * 1024 / 8); +LL_DECLARE_DERIVED_UNIT(Gibibits, "Gib", Mibibits, * 1024 / 8); LL_DECLARE_BASE_UNIT(Seconds, "s"); -LL_DECLARE_DERIVED_UNIT(60, Seconds, Minutes, "min"); -LL_DECLARE_DERIVED_UNIT(60 * 60, Seconds, Hours, "h"); -LL_DECLARE_DERIVED_UNIT(1.0 / 1000.0, Seconds, Milliseconds, "ms"); -LL_DECLARE_DERIVED_UNIT(1.0 / 1000000.0, Seconds, Microseconds, "\x09\x3cs"); -LL_DECLARE_DERIVED_UNIT(1.0 / 1000000000.0, Seconds, Nanoseconds, "ns"); +LL_DECLARE_DERIVED_UNIT(Minutes, "min", Seconds, * 60); +LL_DECLARE_DERIVED_UNIT(Hours, "h", Seconds, * 60 * 60); +LL_DECLARE_DERIVED_UNIT(Milliseconds, "ms", Seconds, / 1000); +LL_DECLARE_DERIVED_UNIT(Microseconds, "\x09\x3cs", Milliseconds, / 1000); +LL_DECLARE_DERIVED_UNIT(Nanoseconds, "ns", Microseconds, / 1000); LL_DECLARE_BASE_UNIT(Meters, "m"); -LL_DECLARE_DERIVED_UNIT(1000, Meters, Kilometers, "km"); -LL_DECLARE_DERIVED_UNIT(1.0 / 100.0, Meters, Centimeters, "cm"); -LL_DECLARE_DERIVED_UNIT(1.0 / 1000.0, Meters, Millimeters, "mm"); +LL_DECLARE_DERIVED_UNIT(Kilometers, "km", Meters, * 1000); +LL_DECLARE_DERIVED_UNIT(Centimeters, "cm", Meters, / 100); +LL_DECLARE_DERIVED_UNIT(Millimeters, "mm", Meters, / 1000); LL_DECLARE_BASE_UNIT(Hertz, "Hz"); -LL_DECLARE_DERIVED_UNIT(1000, Hertz, Kilohertz, "KHz"); -LL_DECLARE_DERIVED_UNIT(1000 * 1000, Hertz, Megahertz, "MHz"); -LL_DECLARE_DERIVED_UNIT(1000 * 1000 * 1000, Hertz, Gigahertz, "GHz"); +LL_DECLARE_DERIVED_UNIT(Kilohertz, "KHz", Hertz, * 1000); +LL_DECLARE_DERIVED_UNIT(Megahertz, "MHz", Kilohertz, * 1000); +LL_DECLARE_DERIVED_UNIT(Gigahertz, "GHz", Megahertz, * 1000); LL_DECLARE_BASE_UNIT(Radians, "rad"); -LL_DECLARE_DERIVED_UNIT(0.01745329251994, Radians, Degrees, "deg"); +LL_DECLARE_DERIVED_UNIT(Degrees, "deg", Radians, * 0.01745329251994); } // namespace LLUnits diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp index 33e30f9688..04764f6c2f 100644 --- a/indra/llcommon/tests/llunits_test.cpp +++ b/indra/llcommon/tests/llunits_test.cpp @@ -34,8 +34,8 @@ namespace LLUnits { // using powers of 2 to allow strict floating point equality LL_DECLARE_BASE_UNIT(Quatloos, "Quat"); - LL_DECLARE_DERIVED_UNIT(4, Quatloos, Latinum, "Lat"); - LL_DECLARE_DERIVED_UNIT((1.0 / 4.0), Quatloos, Solari, "Sol"); + LL_DECLARE_DERIVED_UNIT(Latinum, "Lat", Quatloos, * 4); + LL_DECLARE_DERIVED_UNIT(Solari, "Sol", Latinum, / 16); } namespace tut @@ -53,105 +53,107 @@ namespace tut template<> template<> void units_object_t::test<1>() { - LLUnit<Quatloos, F32> float_quatloos; - ensure(float_quatloos.value() == 0.f); + LLUnit<F32, Quatloos> float_quatloos; + ensure(float_quatloos == 0.f); - LLUnit<Quatloos, S32> int_quatloos; - ensure(int_quatloos.value() == 0); + LLUnit<S32, Quatloos> int_quatloos; + ensure(int_quatloos == 0); int_quatloos = 42; - ensure(int_quatloos.value() == 42); + ensure(int_quatloos == 42); float_quatloos = int_quatloos; - ensure(float_quatloos.value() == 42.f); + ensure(float_quatloos == 42.f); int_quatloos = float_quatloos; - ensure(int_quatloos.value() == 42); + ensure(int_quatloos == 42); float_quatloos = 42.1f; - ensure(float_quatloos.value() == 42.1f); + ensure(float_quatloos == 42.1f); int_quatloos = float_quatloos; - ensure(int_quatloos.value() == 42); - LLUnit<Quatloos, U32> unsigned_int_quatloos(float_quatloos); - ensure(unsigned_int_quatloos.value() == 42); + ensure(int_quatloos == 42); + LLUnit<U32, Quatloos> unsigned_int_quatloos(float_quatloos); + ensure(unsigned_int_quatloos == 42); } // conversions to/from base unit template<> template<> void units_object_t::test<2>() { - LLUnit<Quatloos, F32> quatloos(1.f); - ensure(quatloos.value() == 1.f); - LLUnit<Latinum, F32> latinum_bars(quatloos); - ensure(latinum_bars.value() == 1.f / 4.f); + LLUnit<F32, Quatloos> quatloos(1.f); + ensure(quatloos == 1.f); + LLUnit<F32, Latinum> latinum_bars(quatloos); + ensure(latinum_bars == 1.f / 4.f); latinum_bars = 256; quatloos = latinum_bars; - ensure(quatloos.value() == 1024); + ensure(quatloos == 1024); - LLUnit<Solari, F32> solari(quatloos); - ensure(solari.value() == 4096); + LLUnit<F32, Solari> solari(quatloos); + ensure(solari == 4096); } // conversions across non-base units template<> template<> void units_object_t::test<3>() { - LLUnit<Solari, F32> solari = 4.f; - LLUnit<Latinum, F32> latinum_bars = solari; - ensure(latinum_bars.value() == 0.25f); + LLUnit<F32, Solari> solari = 4.f; + LLUnit<F32, Latinum> latinum_bars = solari; + ensure(latinum_bars == 0.25f); } // math operations template<> template<> void units_object_t::test<4>() { - LLUnit<Quatloos, F32> quatloos = 1.f; + LLUnit<F32, Quatloos> quatloos = 1.f; quatloos *= 4.f; - ensure(quatloos.value() == 4); + ensure(quatloos == 4); quatloos = quatloos * 2; - ensure(quatloos.value() == 8); + ensure(quatloos == 8); quatloos = 2.f * quatloos; - ensure(quatloos.value() == 16); + ensure(quatloos == 16); quatloos += 4.f; - ensure(quatloos.value() == 20); + ensure(quatloos == 20); quatloos += 4; - ensure(quatloos.value() == 24); + ensure(quatloos == 24); quatloos = quatloos + 4; - ensure(quatloos.value() == 28); + ensure(quatloos == 28); quatloos = 4 + quatloos; - ensure(quatloos.value() == 32); + ensure(quatloos == 32); quatloos += quatloos * 3; - ensure(quatloos.value() == 128); + ensure(quatloos == 128); quatloos -= quatloos / 4 * 3; - ensure(quatloos.value() == 32); + ensure(quatloos == 32); quatloos = quatloos - 8; - ensure(quatloos.value() == 24); + ensure(quatloos == 24); quatloos -= 4; - ensure(quatloos.value() == 20); + ensure(quatloos == 20); quatloos -= 4.f; - ensure(quatloos.value() == 16); + ensure(quatloos == 16); quatloos *= 2.f; - ensure(quatloos.value() == 32); + ensure(quatloos == 32); quatloos = quatloos * 2.f; - ensure(quatloos.value() == 64); + ensure(quatloos == 64); quatloos = 0.5f * quatloos; - ensure(quatloos.value() == 32); + ensure(quatloos == 32); quatloos /= 2.f; - ensure(quatloos.value() == 16); + ensure(quatloos == 16); quatloos = quatloos / 4; - ensure(quatloos.value() == 4); + ensure(quatloos == 4); - F32 ratio = quatloos / LLUnit<Quatloos, F32>(4.f); + F32 ratio = quatloos / LLUnit<F32, Quatloos>(4.f); + ensure(ratio == 1); + ratio = quatloos / LLUnit<F32, Solari>(16.f); ensure(ratio == 1); - quatloos += LLUnit<Solari, F32>(4.f); - ensure(quatloos.value() == 5); - quatloos -= LLUnit<Latinum, F32>(1.f); - ensure(quatloos.value() == 1); + quatloos += LLUnit<F32, Solari>(4.f); + ensure(quatloos == 5); + quatloos -= LLUnit<F32, Latinum>(1.f); + ensure(quatloos == 1); } // implicit units @@ -159,16 +161,16 @@ namespace tut void units_object_t::test<5>() { // 0-initialized - LLUnit<Quatloos, F32> quatloos(0); + LLUnit<F32, Quatloos> quatloos(0); // initialize implicit unit from explicit - LLUnitImplicit<Quatloos, F32> quatloos_implicit = quatloos + 1; - ensure(quatloos_implicit.value() == 1); + LLUnitImplicit<F32, Quatloos> quatloos_implicit = quatloos + 1; + ensure(quatloos_implicit == 1); // assign implicit to explicit, or perform math operations quatloos = quatloos_implicit; - ensure(quatloos.value() == 1); + ensure(quatloos == 1); quatloos += quatloos_implicit; - ensure(quatloos.value() == 2); + ensure(quatloos == 2); // math operations on implicits quatloos_implicit = 1; @@ -204,5 +206,11 @@ namespace tut S32 int_val = quatloos_implicit; ensure(int_val == 16); + + // conversion of implicits + LLUnitImplicit<F32, Latinum> latinum_implicit(2); + ensure(latinum_implicit == 2); + + ensure(latinum_implicit * 2 == quatloos_implicit); } } |