summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
authorRichard Linden <none@none>2012-11-12 19:08:14 -0800
committerRichard Linden <none@none>2012-11-12 19:08:14 -0800
commita3e3e8b4ccd96e98da73acf1c584bbfa5a8b2b56 (patch)
tree292f11d2570ecf7bb9bf9094f35c45539c2a017d /indra/llcommon
parent0bb0bd514b235948c1a21c81ab0e8ab6223b1990 (diff)
SH-3406 WIP convert fast timers to lltrace system
simplified llfasttimer code down to 2 classes llunit unit conversion now done in floating point or 64 bit integer precision, depending on source type
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/llfasttimer.cpp270
-rw-r--r--indra/llcommon/llfasttimer.h121
-rw-r--r--indra/llcommon/llprocessor.cpp2
-rw-r--r--indra/llcommon/llprocessor.h4
-rw-r--r--indra/llcommon/lltrace.cpp1
-rw-r--r--indra/llcommon/lltrace.h39
-rw-r--r--indra/llcommon/lltracerecording.h18
-rw-r--r--indra/llcommon/llunit.h127
8 files changed, 245 insertions, 337 deletions
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 4f67004773..c4839fed77 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -32,6 +32,7 @@
#include "llsingleton.h"
#include "lltreeiterators.h"
#include "llsdserialize.h"
+#include "llunit.h"
#include <boost/bind.hpp>
@@ -73,13 +74,13 @@ U64 LLFastTimer::sClockResolution = 1000000; // Microsecond resolution
// FIXME: move these declarations to the relevant modules
// helper functions
-typedef LLTreeDFSPostIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_bottom_up_iterator_t;
+typedef LLTreeDFSPostIter<LLFastTimer::DeclareTimer, LLFastTimer::DeclareTimer::child_const_iter> timer_tree_bottom_up_iterator_t;
-static timer_tree_bottom_up_iterator_t begin_timer_tree_bottom_up(LLFastTimer::NamedTimer& id)
+static timer_tree_bottom_up_iterator_t begin_timer_tree_bottom_up(LLFastTimer::DeclareTimer& id)
{
return timer_tree_bottom_up_iterator_t(&id,
- boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::beginChildren), _1),
- boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::endChildren), _1));
+ boost::bind(boost::mem_fn(&LLFastTimer::DeclareTimer::beginChildren), _1),
+ boost::bind(boost::mem_fn(&LLFastTimer::DeclareTimer::endChildren), _1));
}
static timer_tree_bottom_up_iterator_t end_timer_tree_bottom_up()
@@ -87,14 +88,14 @@ static timer_tree_bottom_up_iterator_t end_timer_tree_bottom_up()
return timer_tree_bottom_up_iterator_t();
}
-typedef LLTreeDFSIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_dfs_iterator_t;
+typedef LLTreeDFSIter<LLFastTimer::DeclareTimer, LLFastTimer::DeclareTimer::child_const_iter> timer_tree_dfs_iterator_t;
-static timer_tree_dfs_iterator_t begin_timer_tree(LLFastTimer::NamedTimer& id)
+static timer_tree_dfs_iterator_t begin_timer_tree(LLFastTimer::DeclareTimer& id)
{
return timer_tree_dfs_iterator_t(&id,
- boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::beginChildren), _1),
- boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::endChildren), _1));
+ boost::bind(boost::mem_fn(&LLFastTimer::DeclareTimer::beginChildren), _1),
+ boost::bind(boost::mem_fn(&LLFastTimer::DeclareTimer::endChildren), _1));
}
static timer_tree_dfs_iterator_t end_timer_tree()
@@ -102,75 +103,12 @@ static timer_tree_dfs_iterator_t end_timer_tree()
return timer_tree_dfs_iterator_t();
}
-// factory class that creates NamedTimers via static DeclareTimer objects
-class NamedTimerFactory : public LLSingleton<NamedTimerFactory>
+LLFastTimer::DeclareTimer& LLFastTimer::DeclareTimer::getRootTimer()
{
-public:
- NamedTimerFactory()
- : mTimerRoot(NULL)
- {}
-
- /*virtual */ void initSingleton()
- {
- mTimerRoot = new LLFastTimer::NamedTimer("root");
- mRootFrameState.setNamedTimer(mTimerRoot);
- mTimerRoot->setFrameState(&mRootFrameState);
- mTimerRoot->mParent = mTimerRoot;
- mTimerRoot->setCollapsed(false);
- mRootFrameState.mParent = &mRootFrameState;
- }
-
- ~NamedTimerFactory()
- {
- std::for_each(mTimers.begin(), mTimers.end(), DeletePairedPointer());
-
- delete mTimerRoot;
- }
-
- LLFastTimer::NamedTimer& createNamedTimer(const std::string& name, LLFastTimer::FrameState* state)
- {
- LLFastTimer::NamedTimer* timer = new LLFastTimer::NamedTimer(name);
- timer->setFrameState(state);
- timer->setParent(mTimerRoot);
- mTimers.insert(std::make_pair(name, timer));
-
- return *timer;
- }
-
- LLFastTimer::NamedTimer* getTimerByName(const std::string& name)
- {
- timer_map_t::iterator found_it = mTimers.find(name);
- if (found_it != mTimers.end())
- {
- return found_it->second;
- }
- return NULL;
- }
-
- LLFastTimer::NamedTimer* getRootTimer() { return mTimerRoot; }
-
- typedef std::multimap<std::string, LLFastTimer::NamedTimer*> timer_map_t;
- timer_map_t::iterator beginTimers() { return mTimers.begin(); }
- timer_map_t::iterator endTimers() { return mTimers.end(); }
- S32 timerCount() { return mTimers.size(); }
-
-private:
- timer_map_t mTimers;
-
- LLFastTimer::NamedTimer* mTimerRoot;
- LLFastTimer::FrameState mRootFrameState;
-};
-
-LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name, bool open )
-: mTimer(NamedTimerFactory::instance().createNamedTimer(name, &mFrameState))
-{
- mTimer.setCollapsed(!open);
+ static DeclareTimer root_timer("root", true, NULL);
+ return root_timer;
}
-LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name)
-: mTimer(NamedTimerFactory::instance().createNamedTimer(name, &mFrameState))
-{
-}
//static
#if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
@@ -183,7 +121,7 @@ U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer
{
#if LL_FASTTIMER_USE_RDTSC || !LL_WINDOWS
//getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz
- static U64 sCPUClockFrequency = U64(LLProcessorInfo().getCPUFrequency()*1000000.0);
+ static LLUnit<LLUnits::Hertz, U64> sCPUClockFrequency = LLProcessorInfo().getCPUFrequency();
// we drop the low-order byte in our timers, so report a lower frequency
#else
@@ -206,49 +144,44 @@ LLFastTimer::FrameState::FrameState()
: mActiveCount(0),
mCalls(0),
mSelfTimeCounter(0),
- mParent(NULL),
mLastCaller(NULL),
mMoveUpTree(false)
{}
-LLFastTimer::NamedTimer::NamedTimer(const std::string& name)
+LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name, bool open, DeclareTimer* parent)
: mName(name),
mCollapsed(true),
mParent(NULL),
mTreeTimeCounter(0),
mCountAverage(0),
mCallAverage(0),
- mNeedsSorting(false),
- mFrameState(NULL)
+ mNeedsSorting(false)
{
+ setCollapsed(!open);
+
+ if (parent)
+ {
+ setParent(parent);
+ }
+ else
+ {
+ mParent = this;
+ }
+
mCountHistory = new U32[HISTORY_NUM];
memset(mCountHistory, 0, sizeof(U32) * HISTORY_NUM);
mCallHistory = new U32[HISTORY_NUM];
memset(mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
}
-LLFastTimer::NamedTimer::~NamedTimer()
+LLFastTimer::DeclareTimer::~DeclareTimer()
{
delete[] mCountHistory;
delete[] mCallHistory;
}
-std::string LLFastTimer::NamedTimer::getToolTip(S32 history_idx)
-{
- F64 ms_multiplier = 1000.0 / (F64)LLFastTimer::countsPerSecond();
- if (history_idx < 0)
- {
- // by default, show average number of call
- return llformat("%s (%d ms, %d calls)", getName().c_str(), (S32)(getCountAverage() * ms_multiplier), (S32)getCallAverage());
- }
- else
- {
- return llformat("%s (%d ms, %d calls)", getName().c_str(), (S32)(getHistoricalCount(history_idx) * ms_multiplier), (S32)getHistoricalCalls(history_idx));
- }
-}
-
-void LLFastTimer::NamedTimer::setParent(NamedTimer* parent)
+void LLFastTimer::DeclareTimer::setParent(DeclareTimer* parent)
{
llassert_always(parent != this);
llassert_always(parent != NULL);
@@ -264,8 +197,8 @@ void LLFastTimer::NamedTimer::setParent(NamedTimer* parent)
// subtract average timing from previous parent
mParent->mCountAverage -= mCountAverage;
- std::vector<NamedTimer*>& children = mParent->getChildren();
- std::vector<NamedTimer*>::iterator found_it = std::find(children.begin(), children.end(), this);
+ std::vector<DeclareTimer*>& children = mParent->getChildren();
+ std::vector<DeclareTimer*>::iterator found_it = std::find(children.begin(), children.end(), this);
if (found_it != children.end())
{
children.erase(found_it);
@@ -275,16 +208,15 @@ void LLFastTimer::NamedTimer::setParent(NamedTimer* parent)
mParent = parent;
if (parent)
{
- getFrameState().mParent = &parent->getFrameState();
parent->getChildren().push_back(this);
parent->mNeedsSorting = true;
}
}
-S32 LLFastTimer::NamedTimer::getDepth()
+S32 LLFastTimer::DeclareTimer::getDepth()
{
S32 depth = 0;
- NamedTimer* timerp = mParent;
+ DeclareTimer* timerp = mParent;
while(timerp)
{
depth++;
@@ -295,7 +227,7 @@ S32 LLFastTimer::NamedTimer::getDepth()
}
// static
-void LLFastTimer::NamedTimer::processTimes()
+void LLFastTimer::DeclareTimer::processTimes()
{
if (sCurFrameIndex < 0) return;
@@ -306,14 +238,14 @@ void LLFastTimer::NamedTimer::processTimes()
// sort child timers by name
struct SortTimerByName
{
- bool operator()(const LLFastTimer::NamedTimer* i1, const LLFastTimer::NamedTimer* i2)
+ bool operator()(const LLFastTimer::DeclareTimer* i1, const LLFastTimer::DeclareTimer* i2)
{
return i1->getName() < i2->getName();
}
};
//static
-void LLFastTimer::NamedTimer::buildHierarchy()
+void LLFastTimer::DeclareTimer::buildHierarchy()
{
if (sCurFrameIndex < 0 ) return;
@@ -321,16 +253,16 @@ void LLFastTimer::NamedTimer::buildHierarchy()
{
for (instance_iter it = beginInstances(), end_it = endInstances(); it != end_it; ++it)
{
- NamedTimer& timer = *it;
- if (&timer == NamedTimerFactory::instance().getRootTimer()) continue;
+ DeclareTimer& timer = *it;
+ if (&timer == &DeclareTimer::getRootTimer()) continue;
// bootstrap tree construction by attaching to last timer to be on stack
// when this timer was called
- if (timer.getFrameState().mLastCaller && timer.mParent == NamedTimerFactory::instance().getRootTimer())
+ if (timer.mLastCaller && timer.mParent == &DeclareTimer::getRootTimer())
{
- timer.setParent(timer.getFrameState().mLastCaller->mTimer);
+ timer.setParent(timer.mLastCaller);
// no need to push up tree on first use, flag can be set spuriously
- timer.getFrameState().mMoveUpTree = false;
+ timer.mMoveUpTree = false;
}
}
}
@@ -338,22 +270,22 @@ void LLFastTimer::NamedTimer::buildHierarchy()
// bump timers up tree if they've been flagged as being in the wrong place
// do this in a bottom up order to promote descendants first before promoting ancestors
// this preserves partial order derived from current frame's observations
- for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(*NamedTimerFactory::instance().getRootTimer());
+ for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(DeclareTimer::getRootTimer());
it != end_timer_tree_bottom_up();
++it)
{
- NamedTimer* timerp = *it;
+ DeclareTimer* timerp = *it;
// skip root timer
- if (timerp == NamedTimerFactory::instance().getRootTimer()) continue;
+ if (timerp == &DeclareTimer::getRootTimer()) continue;
- if (timerp->getFrameState().mMoveUpTree)
+ if (timerp->mMoveUpTree)
{
// since ancestors have already been visited, reparenting won't affect tree traversal
//step up tree, bringing our descendants with us
LL_DEBUGS("FastTimers") << "Moving " << timerp->getName() << " from child of " << timerp->getParent()->getName() <<
" to child of " << timerp->getParent()->getParent()->getName() << LL_ENDL;
timerp->setParent(timerp->getParent()->getParent());
- timerp->getFrameState().mMoveUpTree = false;
+ timerp->mMoveUpTree = false;
// don't bubble up any ancestors until descendants are done bubbling up
it.skipAncestors();
@@ -361,11 +293,11 @@ void LLFastTimer::NamedTimer::buildHierarchy()
}
// sort timers by time last called, so call graph makes sense
- for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer());
+ for(timer_tree_dfs_iterator_t it = begin_timer_tree(DeclareTimer::getRootTimer());
it != end_timer_tree();
++it)
{
- NamedTimer* timerp = (*it);
+ DeclareTimer* timerp = (*it);
if (timerp->mNeedsSorting)
{
std::sort(timerp->getChildren().begin(), timerp->getChildren().end(), SortTimerByName());
@@ -375,7 +307,7 @@ void LLFastTimer::NamedTimer::buildHierarchy()
}
//static
-void LLFastTimer::NamedTimer::accumulateTimings()
+void LLFastTimer::DeclareTimer::accumulateTimings()
{
U32 cur_time = getCPUClockCount32();
@@ -388,8 +320,8 @@ void LLFastTimer::NamedTimer::accumulateTimings()
U32 cumulative_time_delta = cur_time - cur_timer->mStartTime;
U32 self_time_delta = cumulative_time_delta - cur_data->mChildTime;
cur_data->mChildTime = 0;
- cur_data->mFrameState->mSelfTimeCounter += self_time_delta;
- cur_data->mFrameState->mTotalTimeCounter += cumulative_time_delta;
+ cur_data->mTimerData->mSelfTimeCounter += self_time_delta;
+ cur_data->mTimerData->mTotalTimeCounter += cumulative_time_delta;
cur_timer->mStartTime = cur_time;
@@ -400,12 +332,12 @@ void LLFastTimer::NamedTimer::accumulateTimings()
}
// traverse tree in DFS post order, or bottom up
- for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(*NamedTimerFactory::instance().getRootTimer());
+ for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(DeclareTimer::getRootTimer());
it != end_timer_tree_bottom_up();
++it)
{
- NamedTimer* timerp = (*it);
- timerp->mTreeTimeCounter = timerp->getFrameState().mSelfTimeCounter;
+ DeclareTimer* timerp = (*it);
+ timerp->mTreeTimeCounter = timerp->mSelfTimeCounter;
for (child_const_iter child_it = timerp->beginChildren(); child_it != timerp->endChildren(); ++child_it)
{
timerp->mTreeTimeCounter += (*child_it)->mTreeTimeCounter;
@@ -418,15 +350,15 @@ void LLFastTimer::NamedTimer::accumulateTimings()
int hidx = cur_frame % HISTORY_NUM;
timerp->mCountHistory[hidx] = timerp->mTreeTimeCounter;
- timerp->mCountAverage = ((U64)timerp->mCountAverage * cur_frame + timerp->mTreeTimeCounter) / (cur_frame+1);
- timerp->mCallHistory[hidx] = timerp->getFrameState().mCalls;
- timerp->mCallAverage = ((U64)timerp->mCallAverage * cur_frame + timerp->getFrameState().mCalls) / (cur_frame+1);
+ timerp->mCountAverage = ((U64)timerp->mCountAverage * cur_frame + timerp->mTreeTimeCounter) / (cur_frame+1);
+ timerp->mCallHistory[hidx] = timerp->mCalls;
+ timerp->mCallAverage = ((U64)timerp->mCallAverage * cur_frame + timerp->mCalls) / (cur_frame+1);
}
}
}
// static
-void LLFastTimer::NamedTimer::resetFrame()
+void LLFastTimer::DeclareTimer::resetFrame()
{
if (sLog)
{ //output current frame counts to performance log
@@ -435,11 +367,11 @@ void LLFastTimer::NamedTimer::resetFrame()
if (call_count % 100 == 0)
{
LL_DEBUGS("FastTimers") << "countsPerSecond (32 bit): " << countsPerSecond() << LL_ENDL;
- LL_DEBUGS("FastTimers") << "get_clock_count (64 bit): " << get_clock_count() << llendl;
+ LL_DEBUGS("FastTimers") << "get_clock_count (64 bit): " << get_clock_count() << LL_ENDL;
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())/((F64)LLProcessorInfo().getCPUFrequency()*1000000.0) << LL_ENDL;
+ LL_DEBUGS("FastTimers") << "elapsed sec " << ((F64)getCPUClockCount64()) / (LLUnit<LLUnits::Hertz, F64>(LLProcessorInfo().getCPUFrequency())) << LL_ENDL;
}
call_count++;
@@ -451,14 +383,13 @@ void LLFastTimer::NamedTimer::resetFrame()
{
for (instance_iter it = beginInstances(), end_it = endInstances(); it != end_it; ++it)
{
- NamedTimer& timer = *it;
- FrameState& info = timer.getFrameState();
- sd[timer.getName()]["Time"] = (LLSD::Real) (info.mSelfTimeCounter*iclock_freq);
- sd[timer.getName()]["Calls"] = (LLSD::Integer) info.mCalls;
+ DeclareTimer& timer = *it;
+ sd[timer.getName()]["Time"] = (LLSD::Real) (timer.mSelfTimeCounter*iclock_freq);
+ sd[timer.getName()]["Calls"] = (LLSD::Integer) timer.mCalls;
// computing total time here because getting the root timer's getCountHistory
// doesn't work correctly on the first frame
- total_time = total_time + info.mSelfTimeCounter * iclock_freq;
+ total_time = total_time + timer.mSelfTimeCounter * iclock_freq;
}
}
@@ -474,23 +405,16 @@ void LLFastTimer::NamedTimer::resetFrame()
// reset for next frame
for (instance_iter it = beginInstances(), end_it = endInstances(); it != end_it; ++it)
{
- NamedTimer& timer = *it;
-
- FrameState& info = timer.getFrameState();
- info.mSelfTimeCounter = 0;
- info.mCalls = 0;
- info.mLastCaller = NULL;
- info.mMoveUpTree = false;
- // update parent pointer in timer state struct
- if (timer.mParent)
- {
- info.mParent = &timer.mParent->getFrameState();
- }
+ DeclareTimer& timer = *it;
+ timer.mSelfTimeCounter = 0;
+ timer.mCalls = 0;
+ timer.mLastCaller = NULL;
+ timer.mMoveUpTree = false;
}
}
//static
-void LLFastTimer::NamedTimer::reset()
+void LLFastTimer::DeclareTimer::reset()
{
resetFrame(); // reset frame data
@@ -514,10 +438,10 @@ void LLFastTimer::NamedTimer::reset()
{
for (instance_iter it = beginInstances(), end_it = endInstances(); it != end_it; ++it)
{
- NamedTimer& timer = *it;
- if (&timer != NamedTimerFactory::instance().getRootTimer())
+ DeclareTimer& timer = *it;
+ if (&timer != &DeclareTimer::getRootTimer())
{
- timer.setParent(NamedTimerFactory::instance().getRootTimer());
+ timer.setParent(&DeclareTimer::getRootTimer());
}
timer.mCountAverage = 0;
@@ -531,34 +455,29 @@ void LLFastTimer::NamedTimer::reset()
sCurFrameIndex = 0;
}
-U32 LLFastTimer::NamedTimer::getHistoricalCount(S32 history_index) const
+U32 LLFastTimer::DeclareTimer::getHistoricalCount(S32 history_index) const
{
- S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::NamedTimer::HISTORY_NUM;
+ S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::DeclareTimer::HISTORY_NUM;
return mCountHistory[history_idx];
}
-U32 LLFastTimer::NamedTimer::getHistoricalCalls(S32 history_index ) const
+U32 LLFastTimer::DeclareTimer::getHistoricalCalls(S32 history_index ) const
{
- S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::NamedTimer::HISTORY_NUM;
+ S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::DeclareTimer::HISTORY_NUM;
return mCallHistory[history_idx];
}
-LLFastTimer::FrameState& LLFastTimer::NamedTimer::getFrameState() const
-{
- return *mFrameState;
-}
-
-std::vector<LLFastTimer::NamedTimer*>::const_iterator LLFastTimer::NamedTimer::beginChildren()
+std::vector<LLFastTimer::DeclareTimer*>::const_iterator LLFastTimer::DeclareTimer::beginChildren()
{
return mChildren.begin();
}
-std::vector<LLFastTimer::NamedTimer*>::const_iterator LLFastTimer::NamedTimer::endChildren()
+std::vector<LLFastTimer::DeclareTimer*>::const_iterator LLFastTimer::DeclareTimer::endChildren()
{
return mChildren.end();
}
-std::vector<LLFastTimer::NamedTimer*>& LLFastTimer::NamedTimer::getChildren()
+std::vector<LLFastTimer::DeclareTimer*>& LLFastTimer::DeclareTimer::getChildren()
{
return mChildren;
}
@@ -575,12 +494,12 @@ void LLFastTimer::nextFrame()
if (!sPauseHistory)
{
- NamedTimer::processTimes();
+ DeclareTimer::processTimes();
sLastFrameIndex = sCurFrameIndex++;
}
// get ready for next frame
- NamedTimer::resetFrame();
+ DeclareTimer::resetFrame();
sLastFrameTime = frame_time;
}
@@ -588,17 +507,17 @@ void LLFastTimer::nextFrame()
void LLFastTimer::dumpCurTimes()
{
// accumulate timings, etc.
- NamedTimer::processTimes();
+ DeclareTimer::processTimes();
F64 clock_freq = (F64)countsPerSecond();
F64 iclock_freq = 1000.0 / clock_freq; // clock_ticks -> milliseconds
// walk over timers in depth order and output timings
- for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer());
+ for(timer_tree_dfs_iterator_t it = begin_timer_tree(DeclareTimer::getRootTimer());
it != end_timer_tree();
++it)
{
- NamedTimer* timerp = (*it);
+ DeclareTimer* timerp = (*it);
F64 total_time_ms = ((F64)timerp->getHistoricalCount(0) * iclock_freq);
// Don't bother with really brief times, keep output concise
if (total_time_ms < 0.1) continue;
@@ -621,7 +540,7 @@ void LLFastTimer::dumpCurTimes()
//static
void LLFastTimer::reset()
{
- NamedTimer::reset();
+ DeclareTimer::reset();
}
@@ -637,22 +556,3 @@ void LLFastTimer::writeLog(std::ostream& os)
}
}
-//static
-const LLFastTimer::NamedTimer* LLFastTimer::getTimerByName(const std::string& name)
-{
- return NamedTimerFactory::instance().getTimerByName(name);
-}
-
-//LLFastTimer::LLFastTimer(LLFastTimer::FrameState* state)
-//: mFrameState(state)
-//{
-// U32 start_time = getCPUClockCount32();
-// mStartTime = start_time;
-// mFrameState->mActiveCount++;
-// LLFastTimer::sCurTimerData.mCurTimer = this;
-// LLFastTimer::sCurTimerData.mFrameState = mFrameState;
-// LLFastTimer::sCurTimerData.mChildTime = 0;
-// mLastTimerData = LLFastTimer::sCurTimerData;
-//}
-
-
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 4660fad5e3..31872e4e65 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -30,7 +30,6 @@
#include "llinstancetracker.h"
#define FAST_TIMER_ON 1
-#define DEBUG_FAST_TIMER_THREADS 1
class LLMutex;
@@ -45,64 +44,53 @@ LL_COMMON_API void assert_main_thread();
class LL_COMMON_API LLFastTimer
{
public:
- class NamedTimer;
-
+ class DeclareTimer;
struct LL_COMMON_API FrameState
{
FrameState();
- void setNamedTimer(class NamedTimer* timerp) { mTimer = timerp; }
U32 mSelfTimeCounter;
U32 mTotalTimeCounter;
U32 mCalls;
- FrameState* mParent; // info for caller timer
- FrameState* mLastCaller; // used to bootstrap tree construction
- class NamedTimer* mTimer;
+ DeclareTimer* mLastCaller; // used to bootstrap tree construction
U16 mActiveCount; // number of timers with this ID active on stack
bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame
};
// stores a "named" timer instance to be reused via multiple LLFastTimer stack instances
- class LL_COMMON_API NamedTimer
- : public LLInstanceTracker<NamedTimer>
+ class LL_COMMON_API DeclareTimer
+ : public LLInstanceTracker<DeclareTimer>
{
- friend class DeclareTimer;
public:
- ~NamedTimer();
+ DeclareTimer(const std::string& name, bool open = false, DeclareTimer* parent = &getRootTimer());
+ ~DeclareTimer();
enum { HISTORY_NUM = 300 };
const std::string& getName() const { return mName; }
- NamedTimer* getParent() const { return mParent; }
- void setParent(NamedTimer* parent);
+ DeclareTimer* getParent() const { return mParent; }
+ void setParent(DeclareTimer* parent);
S32 getDepth();
- std::string getToolTip(S32 history_index = -1);
- typedef std::vector<NamedTimer*>::const_iterator child_const_iter;
+ typedef std::vector<DeclareTimer*>::const_iterator child_const_iter;
child_const_iter beginChildren();
child_const_iter endChildren();
- std::vector<NamedTimer*>& getChildren();
+ std::vector<DeclareTimer*>& getChildren();
- void setCollapsed(bool collapsed) { mCollapsed = collapsed; }
- bool getCollapsed() const { return mCollapsed; }
+ void setCollapsed(bool collapsed) { mCollapsed = collapsed; }
+ bool getCollapsed() const { return mCollapsed; }
U32 getCountAverage() const { return mCountAverage; }
- U32 getCallAverage() const { return mCallAverage; }
+ U32 getCallAverage() const { return mCallAverage; }
U32 getHistoricalCount(S32 history_index = 0) const;
U32 getHistoricalCalls(S32 history_index = 0) const;
- void setFrameState(FrameState* state) { mFrameState = state; state->setNamedTimer(this); }
- FrameState& getFrameState() const;
+ static DeclareTimer& getRootTimer();
private:
friend class LLFastTimer;
- friend class NamedTimerFactory;
- //
- // methods
- //
- NamedTimer(const std::string& name);
// recursive call to gather total time from children
static void accumulateTimings();
@@ -117,82 +105,62 @@ public:
//
// members
//
- FrameState* mFrameState;
+ U32 mSelfTimeCounter;
+ U32 mTotalTimeCounter;
+ U32 mCalls;
+ DeclareTimer* mLastCaller; // used to bootstrap tree construction
+ U16 mActiveCount; // number of timers with this ID active on stack
+ bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame
- std::string mName;
+ std::string mName;
- // sum of recorded self time and tree time of all children timers (might not match actual recorded time of children if topology is incomplete
- U32 mTreeTimeCounter;
+ // sum of recored self time and tree time of all children timers (might not match actual recorded time of children if topology is incomplete
+ U32 mTreeTimeCounter;
- U32 mCountAverage;
- U32 mCallAverage;
+ U32 mCountAverage;
+ U32 mCallAverage;
- U32* mCountHistory;
- U32* mCallHistory;
+ U32* mCountHistory;
+ U32* mCallHistory;
// tree structure
- NamedTimer* mParent; // NamedTimer of caller(parent)
- std::vector<NamedTimer*> mChildren;
+ DeclareTimer* mParent; // DeclareTimer of caller(parent)
+ std::vector<DeclareTimer*> mChildren;
bool mCollapsed; // don't show children
bool mNeedsSorting; // sort children whenever child added
};
- // used to statically declare a new named timer
- class LL_COMMON_API DeclareTimer
- : public LLInstanceTracker<DeclareTimer>
- {
- friend class LLFastTimer;
- public:
- DeclareTimer(const std::string& name, bool open);
- DeclareTimer(const std::string& name);
-
- NamedTimer& getNamedTimer() { return mTimer; }
-
- private:
- FrameState mFrameState;
- NamedTimer& mTimer;
- };
-
public:
- //LLFastTimer(LLFastTimer::FrameState* state);
-
LL_FORCE_INLINE LLFastTimer(LLFastTimer::DeclareTimer& timer)
{
#if FAST_TIMER_ON
- LLFastTimer::FrameState* frame_state = &timer.mFrameState;
mStartTime = getCPUClockCount32();
- frame_state->mActiveCount++;
- frame_state->mCalls++;
+ timer.mActiveCount++;
+ timer.mCalls++;
// keep current parent as long as it is active when we are
- frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0);
+ timer.mMoveUpTree |= (timer.mParent->mActiveCount == 0);
LLFastTimer::CurTimerData* cur_timer_data = &LLFastTimer::sCurTimerData;
mLastTimerData = *cur_timer_data;
cur_timer_data->mCurTimer = this;
- cur_timer_data->mFrameState = frame_state;
+ cur_timer_data->mTimerData = &timer;
cur_timer_data->mChildTime = 0;
#endif
-#if DEBUG_FAST_TIMER_THREADS
-#if !LL_RELEASE
- assert_main_thread();
-#endif
-#endif
}
LL_FORCE_INLINE ~LLFastTimer()
{
#if FAST_TIMER_ON
- LLFastTimer::FrameState* frame_state = LLFastTimer::sCurTimerData.mFrameState;
U32 total_time = getCPUClockCount32() - mStartTime;
-
- frame_state->mSelfTimeCounter += total_time - LLFastTimer::sCurTimerData.mChildTime;
- frame_state->mTotalTimeCounter += total_time;
- frame_state->mActiveCount--;
+ DeclareTimer* timer_data = LLFastTimer::sCurTimerData.mTimerData;
+ timer_data->mSelfTimeCounter += total_time - LLFastTimer::sCurTimerData.mChildTime;
+ timer_data->mTotalTimeCounter += total_time;
+ timer_data->mActiveCount--;
// store last caller to bootstrap tree creation
// do this in the destructor in case of recursion to get topmost caller
- frame_state->mLastCaller = mLastTimerData.mFrameState;
+ timer_data->mLastCaller = mLastTimerData.mTimerData;
// we are only tracking self time, so subtract our total time delta from parents
mLastTimerData.mChildTime += total_time;
@@ -225,12 +193,11 @@ public:
static S32 getCurFrameIndex() { return sCurFrameIndex; }
static void writeLog(std::ostream& os);
- static const NamedTimer* getTimerByName(const std::string& name);
struct CurTimerData
{
LLFastTimer* mCurTimer;
- FrameState* mFrameState;
+ DeclareTimer* mTimerData;
U32 mChildTime;
};
static CurTimerData sCurTimerData;
@@ -374,15 +341,13 @@ private:
#endif
- static U64 sClockResolution;
-
- static S32 sCurFrameIndex;
- static S32 sLastFrameIndex;
- static U64 sLastFrameTime;
+ static U64 sClockResolution;
+ static S32 sCurFrameIndex;
+ static S32 sLastFrameIndex;
+ static U64 sLastFrameTime;
U32 mStartTime;
LLFastTimer::CurTimerData mLastTimerData;
-
};
typedef class LLFastTimer LLFastTimer;
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index fd8f603d21..87a5930c14 100644
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -877,7 +877,7 @@ LLProcessorInfo::LLProcessorInfo() : mImpl(NULL)
LLProcessorInfo::~LLProcessorInfo() {}
-F64 LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); }
+LLUnit<LLUnits::Megahertz, F64> 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 6364d3c8bb..2a21a5c115 100644
--- a/indra/llcommon/llprocessor.h
+++ b/indra/llcommon/llprocessor.h
@@ -27,6 +27,8 @@
#ifndef LLPROCESSOR_H
#define LLPROCESSOR_H
+#include "llunit.h"
+
class LLProcessorInfoImpl;
class LL_COMMON_API LLProcessorInfo
@@ -35,7 +37,7 @@ public:
LLProcessorInfo();
~LLProcessorInfo();
- F64 getCPUFrequency() const;
+ LLUnit<LLUnits::Megahertz, F64> getCPUFrequency() const;
bool hasSSE() const;
bool hasSSE2() const;
bool hasAltivec() const;
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index d5911ece25..3f605f2c74 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -42,6 +42,7 @@ void init()
void cleanup()
{
delete gMasterThreadRecorder;
+ LLUnitStrict<LLUnits::Seconds, F32> seconds;
gMasterThreadRecorder = NULL;
}
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index d289ea9a88..549e407822 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -57,8 +57,6 @@ namespace LLTrace
typedef LLUnit<LLUnits::Milliseconds, F64> Milliseconds;
typedef LLUnit<LLUnits::Minutes, F64> Minutes;
typedef LLUnit<LLUnits::Hours, F64> Hours;
- typedef LLUnit<LLUnits::Days, F64> Days;
- typedef LLUnit<LLUnits::Weeks, F64> Weeks;
typedef LLUnit<LLUnits::Milliseconds, F64> Milliseconds;
typedef LLUnit<LLUnits::Microseconds, F64> Microseconds;
typedef LLUnit<LLUnits::Nanoseconds, F64> Nanoseconds;
@@ -226,27 +224,6 @@ namespace LLTrace
size_t mAccumulatorIndex;
};
-
- template<typename T, typename IS_UNIT = void>
- struct StorageType
- {
- typedef T type_t;
- };
-
- template<typename T>
- struct StorageType<T, typename T::is_unit_tag_t>
- {
- typedef typename StorageType<typename T::storage_t>::type_t type_t;
- };
-
- template<> struct StorageType<F32> { typedef F64 type_t; };
- template<> struct StorageType<S32> { typedef S64 type_t; };
- template<> struct StorageType<U32> { typedef S64 type_t; };
- template<> struct StorageType<S16> { typedef S64 type_t; };
- template<> struct StorageType<U16> { typedef S64 type_t; };
- template<> struct StorageType<S8> { typedef S64 type_t; };
- template<> struct StorageType<U8> { typedef S64 type_t; };
-
template<typename T>
class LL_COMMON_API MeasurementAccumulator
{
@@ -406,10 +383,10 @@ namespace LLTrace
template <typename T = F64, typename IS_UNIT = void>
class LL_COMMON_API Measurement
- : public TraceType<MeasurementAccumulator<typename StorageType<T>::type_t> >
+ : public TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
{
public:
- typedef typename StorageType<T>::type_t storage_t;
+ typedef typename LLUnits::HighestPrecisionType<T>::type_t storage_t;
Measurement(const char* name, const char* description = NULL)
: TraceType(name, description)
@@ -423,10 +400,10 @@ namespace LLTrace
template <typename T>
class LL_COMMON_API Measurement <T, typename T::is_unit_tag_t>
- : public TraceType<MeasurementAccumulator<typename StorageType<typename T::storage_t>::type_t> >
+ : public TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<typename T::storage_t>::type_t> >
{
public:
- typedef typename StorageType<typename T::storage_t>::type_t storage_t;
+ typedef typename LLUnits::HighestPrecisionType<typename T::storage_t>::type_t storage_t;
Measurement(const char* name, const char* description = NULL)
: TraceType(name, description)
@@ -446,10 +423,10 @@ namespace LLTrace
template <typename T = F64, typename IS_UNIT = void>
class LL_COMMON_API Count
- : public TraceType<CountAccumulator<typename StorageType<T>::type_t> >
+ : public TraceType<CountAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
{
public:
- typedef typename StorageType<T>::type_t storage_t;
+ typedef typename LLUnits::HighestPrecisionType<T>::type_t storage_t;
Count(const char* name, const char* description = NULL)
: TraceType(name)
@@ -463,10 +440,10 @@ namespace LLTrace
template <typename T>
class LL_COMMON_API Count <T, typename T::is_unit_tag_t>
- : public TraceType<CountAccumulator<typename StorageType<typename T::storage_t>::type_t> >
+ : public TraceType<CountAccumulator<typename LLUnits::HighestPrecisionType<typename T::storage_t>::type_t> >
{
public:
- typedef typename StorageType<typename T::storage_t>::type_t storage_t;
+ typedef typename LLUnits::HighestPrecisionType<typename T::storage_t>::type_t storage_t;
Count(const char* name, const char* description = NULL)
: TraceType(name)
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index ca9950b78d..16b80fd1d8 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -122,7 +122,7 @@ namespace LLTrace
template <typename T>
T getSum(const Count<T, typename T::is_unit_tag_t>& stat) const
{
- return (T)getSum(static_cast<const TraceType<CountAccumulator<StorageType<T>::type_t> >&> (stat));
+ return (T)getSum(static_cast<const TraceType<CountAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
}
F64 getPerSec(const TraceType<CountAccumulator<F64> >& stat) const;
@@ -130,7 +130,7 @@ namespace LLTrace
template <typename T>
T getPerSec(const Count<T, typename T::is_unit_tag_t>& stat) const
{
- return (T)getPerSec(static_cast<const TraceType<CountAccumulator<StorageType<T>::type_t> >&> (stat));
+ return (T)getPerSec(static_cast<const TraceType<CountAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
}
U32 getSampleCount(const TraceType<CountAccumulator<F64> >& stat) const;
@@ -143,7 +143,7 @@ namespace LLTrace
template <typename T>
T getSum(const Measurement<T, typename T::is_unit_tag_t>& stat) const
{
- return (T)getSum(static_cast<const TraceType<MeasurementAccumulator<StorageType<T>::type_t> >&> (stat));
+ return (T)getSum(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
}
F64 getPerSec(const TraceType<MeasurementAccumulator<F64> >& stat) const;
@@ -151,7 +151,7 @@ namespace LLTrace
template <typename T>
T getPerSec(const Measurement<T, typename T::is_unit_tag_t>& stat) const
{
- return (T)getPerSec(static_cast<const TraceType<MeasurementAccumulator<StorageType<T>::type_t> >&> (stat));
+ return (T)getPerSec(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
}
F64 getMin(const TraceType<MeasurementAccumulator<F64> >& stat) const;
@@ -159,7 +159,7 @@ namespace LLTrace
template <typename T>
T getMin(const Measurement<T, typename T::is_unit_tag_t>& stat) const
{
- return (T)getMin(static_cast<const TraceType<MeasurementAccumulator<StorageType<T>::type_t> >&> (stat));
+ return (T)getMin(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
}
F64 getMax(const TraceType<MeasurementAccumulator<F64> >& stat) const;
@@ -167,7 +167,7 @@ namespace LLTrace
template <typename T>
T getMax(const Measurement<T, typename T::is_unit_tag_t>& stat) const
{
- return (T)getMax(static_cast<const TraceType<MeasurementAccumulator<StorageType<T>::type_t> >&> (stat));
+ return (T)getMax(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
}
F64 getMean(const TraceType<MeasurementAccumulator<F64> >& stat) const;
@@ -175,7 +175,7 @@ namespace LLTrace
template <typename T>
T getMean(Measurement<T, typename T::is_unit_tag_t>& stat) const
{
- return (T)getMean(static_cast<const TraceType<MeasurementAccumulator<StorageType<T>::type_t> >&> (stat));
+ return (T)getMean(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
}
F64 getStandardDeviation(const TraceType<MeasurementAccumulator<F64> >& stat) const;
@@ -183,7 +183,7 @@ namespace LLTrace
template <typename T>
T getStandardDeviation(const Measurement<T, typename T::is_unit_tag_t>& stat) const
{
- return (T)getMean(static_cast<const TraceType<MeasurementAccumulator<StorageType<T>::type_t> >&> (stat));
+ return (T)getMean(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
}
F64 getLastValue(const TraceType<MeasurementAccumulator<F64> >& stat) const;
@@ -191,7 +191,7 @@ namespace LLTrace
template <typename T>
T getLastValue(const Measurement<T, typename T::is_unit_tag_t>& stat) const
{
- return (T)getLastValue(static_cast<const TraceType<MeasurementAccumulator<StorageType<T>::type_t> >&> (stat));
+ return (T)getLastValue(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
}
U32 getSampleCount(const TraceType<MeasurementAccumulator<F64> >& stat) const;
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 0dcafbe26e..54ba1d67db 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -32,19 +32,44 @@
namespace LLUnits
{
-template<typename DERIVED_UNITS_TAG, typename BASE_UNITS_TAG>
+
+template<typename T, typename IS_UNIT = void>
+struct HighestPrecisionType
+{
+ typedef T type_t;
+};
+
+template<typename T>
+struct HighestPrecisionType<T, typename T::is_unit_tag_t>
+{
+ typedef typename HighestPrecisionType<typename T::storage_t>::type_t type_t;
+};
+
+template<> struct HighestPrecisionType<F32> { typedef F64 type_t; };
+template<> struct HighestPrecisionType<S32> { typedef S64 type_t; };
+template<> struct HighestPrecisionType<U32> { typedef S64 type_t; };
+template<> struct HighestPrecisionType<S16> { typedef S64 type_t; };
+template<> struct HighestPrecisionType<U16> { typedef S64 type_t; };
+template<> struct HighestPrecisionType<S8> { typedef S64 type_t; };
+template<> struct HighestPrecisionType<U8> { typedef S64 type_t; };
+
+template<typename DERIVED_UNITS_TAG, typename BASE_UNITS_TAG, typename VALUE_TYPE>
struct ConversionFactor
{
- static F64 get()
+ static typename HighestPrecisionType<VALUE_TYPE>::type_t get()
{
+ // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
llstatic_assert(sizeof(DERIVED_UNITS_TAG) == 0, "Cannot convert between types.");
}
};
-template<typename BASE_UNITS_TAG>
-struct ConversionFactor<BASE_UNITS_TAG, BASE_UNITS_TAG>
+template<typename BASE_UNITS_TAG, typename VALUE_TYPE>
+struct ConversionFactor<BASE_UNITS_TAG, BASE_UNITS_TAG, VALUE_TYPE>
{
- static F64 get() { return 1.0; }
+ static typename HighestPrecisionType<VALUE_TYPE>::type_t get()
+ {
+ return 1;
+ }
};
}
@@ -91,6 +116,11 @@ struct LLUnit
return mValue;
}
+ template<typename NEW_UNIT_TYPE> LLUnit<NEW_UNIT_TYPE, STORAGE_TYPE> as()
+ {
+ return LLUnit<NEW_UNIT_TYPE, STORAGE_TYPE>(*this);
+ }
+
void operator += (storage_t value)
{
mValue += value;
@@ -121,7 +151,8 @@ struct LLUnit
template<typename OTHER_UNIT, typename OTHER_STORAGE>
void operator *= (LLUnit<OTHER_UNIT, OTHER_STORAGE> multiplicand)
{
- llstatic_assert(sizeof(OTHER_UNIT) == false, "Multiplication of unit types not supported.");
+ // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+ llstatic_assert(sizeof(OTHER_UNIT) == 0, "Multiplication of unit types not supported.");
}
void operator /= (storage_t divisor)
@@ -132,15 +163,16 @@ struct LLUnit
template<typename OTHER_UNIT, typename OTHER_STORAGE>
void operator /= (LLUnit<OTHER_UNIT, OTHER_STORAGE> divisor)
{
- llstatic_assert(sizeof(OTHER_UNIT) == false, "Division of unit types not supported.");
+ // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+ llstatic_assert(sizeof(OTHER_UNIT) == 0, "Division of unit types not supported.");
}
- template<typename SOURCE_UNITS, typename SOURCE_VALUE>
- static storage_t convert(LLUnit<SOURCE_UNITS, SOURCE_VALUE> v)
+ template<typename SOURCE_UNITS, typename SOURCE_STORAGE>
+ static storage_t convert(LLUnit<SOURCE_UNITS, SOURCE_STORAGE> v)
{
return (storage_t)(v.value()
- * LLUnits::ConversionFactor<SOURCE_UNITS, typename UNIT_TYPE::base_unit_t>::get()
- * LLUnits::ConversionFactor<typename UNIT_TYPE::base_unit_t, UNIT_TYPE>::get());
+ * 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());
}
protected:
@@ -148,6 +180,32 @@ protected:
storage_t mValue;
};
+template<typename UNIT_TYPE, typename STORAGE_TYPE>
+struct LLUnitStrict : public LLUnit<UNIT_TYPE, STORAGE_TYPE>
+{
+ typedef LLUnitStrict<UNIT_TYPE, STORAGE_TYPE> self_t;
+
+ explicit LLUnitStrict(storage_t value = storage_t())
+ : LLUnit(value)
+ {}
+
+ template<typename OTHER_UNIT, typename OTHER_STORAGE>
+ LLUnitStrict(LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
+ : LLUnit(convert(other))
+ {}
+
+ LLUnitStrict(self_t& other)
+ : LLUnit(other)
+ {}
+
+
+private:
+ operator storage_t() const
+ {
+ return value();
+ }
+};
+
//
// operator +
//
@@ -221,7 +279,8 @@ LLUnit<STORAGE_TYPE, UNIT_TYPE> operator * (LLUnit<STORAGE_TYPE, UNIT_TYPE> firs
template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
void operator * (LLUnit<STORAGE_TYPE1, UNIT_TYPE1>, LLUnit<STORAGE_TYPE2, UNIT_TYPE2>)
{
- llstatic_assert(sizeof(STORAGE_TYPE1) == false, "Multiplication of unit types results in new unit type - not supported.");
+ // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+ llstatic_assert(sizeof(STORAGE_TYPE1) == 0, "Multiplication of unit types results in new unit type - not supported.");
}
//
@@ -242,7 +301,8 @@ LLUnit<STORAGE_TYPE, UNIT_TYPE> operator / (LLUnit<STORAGE_TYPE, UNIT_TYPE> firs
template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
void operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1>, LLUnit<STORAGE_TYPE2, UNIT_TYPE2>)
{
- llstatic_assert(sizeof(STORAGE_TYPE1) == false, "Multiplication of unit types results in new unit type - not supported.");
+ // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+ llstatic_assert(sizeof(STORAGE_TYPE1) == 0, "Multiplication of unit types results in new unit type - not supported.");
}
#define COMPARISON_OPERATORS(op) \
@@ -273,21 +333,21 @@ COMPARISON_OPERATORS(!=)
namespace LLUnits
{
-#define LL_DECLARE_DERIVED_UNIT(base_unit_name, unit_name, conversion_factor)\
-struct unit_name \
-{ \
- typedef base_unit_name base_unit_t; \
-}; \
-template<> \
-struct ConversionFactor<unit_name, base_unit_name> \
-{ \
- static F64 get() { return (conversion_factor); } \
-}; \
- \
-template<> \
-struct ConversionFactor<base_unit_name, unit_name> \
-{ \
- static F64 get() { return 1.0 / (conversion_factor); } \
+#define LL_DECLARE_DERIVED_UNIT(base_unit_name, unit_name, conversion_factor) \
+struct unit_name \
+{ \
+ typedef base_unit_name base_unit_t; \
+}; \
+template<typename STORAGE_TYPE> \
+struct ConversionFactor<unit_name, base_unit_name, STORAGE_TYPE> \
+{ \
+ static typename HighestPrecisionType<STORAGE_TYPE>::type_t get() { return typename HighestPrecisionType<STORAGE_TYPE>::type_t(conversion_factor); } \
+}; \
+ \
+template<typename STORAGE_TYPE> \
+struct ConversionFactor<base_unit_name, unit_name, STORAGE_TYPE> \
+{ \
+ static typename HighestPrecisionType<STORAGE_TYPE>::type_t get() { return typename HighestPrecisionType<STORAGE_TYPE>::type_t(1.0 / (conversion_factor)); } \
}
struct Bytes { typedef Bytes base_unit_t; };
@@ -302,16 +362,19 @@ LL_DECLARE_DERIVED_UNIT(Bytes, Gigabits, (1024 * 1024 * 1024 / 8));
struct Seconds { typedef Seconds base_unit_t; };
LL_DECLARE_DERIVED_UNIT(Seconds, Minutes, 60);
LL_DECLARE_DERIVED_UNIT(Seconds, Hours, 60 * 60);
-LL_DECLARE_DERIVED_UNIT(Seconds, Days, 60 * 60 * 24);
-LL_DECLARE_DERIVED_UNIT(Seconds, Weeks, 60 * 60 * 24 * 7);
LL_DECLARE_DERIVED_UNIT(Seconds, Milliseconds, (1.0 / 1000.0));
LL_DECLARE_DERIVED_UNIT(Seconds, Microseconds, (1.0 / (1000000.0)));
LL_DECLARE_DERIVED_UNIT(Seconds, Nanoseconds, (1.0 / (1000000000.0)));
struct Meters { typedef Meters base_unit_t; };
LL_DECLARE_DERIVED_UNIT(Meters, Kilometers, 1000);
-LL_DECLARE_DERIVED_UNIT(Meters, Centimeters, (1.0 / 100));
-LL_DECLARE_DERIVED_UNIT(Meters, Millimeters, (1.0 / 1000));
+LL_DECLARE_DERIVED_UNIT(Meters, Centimeters, (1.0 / 100.0));
+LL_DECLARE_DERIVED_UNIT(Meters, Millimeters, (1.0 / 1000.0));
+
+struct Hertz { typedef Hertz base_unit_t; };
+LL_DECLARE_DERIVED_UNIT(Hertz, Kilohertz, 1000);
+LL_DECLARE_DERIVED_UNIT(Hertz, Megahertz, 1000 * 1000);
+LL_DECLARE_DERIVED_UNIT(Hertz, Gigahertz, 1000 * 1000 * 1000);
}
#endif // LL_LLUNIT_H